diff options
Diffstat (limited to 'source3/param')
-rw-r--r-- | source3/param/loadparm.c | 401 |
1 files changed, 79 insertions, 322 deletions
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 398ae88b97..1455f88156 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -81,13 +81,6 @@ extern int extra_time_offset; static BOOL defaults_saved = False; -typedef struct _param_opt_struct param_opt_struct; -struct _param_opt_struct { - param_opt_struct *prev, *next; - char *key; - char *value; -}; - /* * This structure describes global (ie., server-wide) parameters. */ @@ -118,8 +111,6 @@ typedef struct char *szSMBPasswdFile; char *szPrivateDir; char **szPassdbBackend; - char **szSamBackend; - char **szModules; char *szPasswordServer; char *szSocketOptions; char *szRealm; @@ -164,7 +155,7 @@ typedef struct char *szWinbindUID; char *szWinbindGID; char *szNonUnixAccountRange; - int AlgorithmicRidBase; + BOOL bAlgorithmicRidBase; char *szTemplateHomedir; char *szTemplateShell; char *szWinbindSeparator; @@ -264,10 +255,6 @@ typedef struct BOOL bAllowTrustedDomains; BOOL bLanmanAuth; BOOL bNTLMAuth; - BOOL bUseSpnego; - BOOL bClientLanManAuth; - BOOL bClientNTLMv2Auth; - BOOL bClientUseSpnego; BOOL bDebugHiresTimestamp; BOOL bDebugPid; BOOL bDebugUid; @@ -276,13 +263,12 @@ typedef struct BOOL bUnicode; BOOL bUseMmap; BOOL bHostnameLookups; + BOOL bUseSpnego; BOOL bUnixExtensions; BOOL bDisableNetbios; BOOL bKernelChangeNotify; int restrict_anonymous; int name_cache_timeout; - BOOL client_signing; - param_opt_struct *param_opt; } global; @@ -404,7 +390,6 @@ typedef struct BOOL bNTAclSupport; BOOL bUseSendfile; BOOL bProfileAcls; - param_opt_struct *param_opt; char dummy[3]; /* for alignment */ } @@ -524,8 +509,6 @@ static service sDefault = { True, /* bNTAclSupport */ False, /* bUseSendfile */ False, /* bProfileAcls */ - - NULL, /* Parametric options */ "" /* dummy */ }; @@ -755,10 +738,9 @@ static struct parm_struct parm_table[] = { {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"sam backend", P_LIST, P_GLOBAL, &Globals.szSamBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.bAlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER}, @@ -775,8 +757,6 @@ static struct parm_struct parm_table[] = { {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, @@ -820,7 +800,6 @@ static struct parm_struct parm_table[] = { {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE}, {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER}, {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, - {"modules", P_LIST, P_GLOBAL, &Globals.szModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL}, {"Logging Options", P_SEP, P_SEPARATOR}, @@ -868,8 +847,6 @@ static struct parm_struct parm_table[] = { {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER}, - {"client signing", P_BOOL, P_GLOBAL, &Globals.client_signing, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER}, {"Tuning Options", P_SEP, P_SEPARATOR}, @@ -1314,7 +1291,7 @@ static void init_globals(void) string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast"); string_set(&Globals.szPasswordServer, "*"); - Globals.AlgorithmicRidBase = BASE_RID; + Globals.bAlgorithmicRidBase = BASE_RID; Globals.bLoadPrinters = True; Globals.mangled_stack = 50; @@ -1381,10 +1358,8 @@ static void init_globals(void) Globals.bNTStatusSupport = True; /* Use NT status by default. */ Globals.bStatCache = True; /* use stat cache by default */ Globals.restrict_anonymous = 0; - Globals.bClientLanManAuth = True; /* Do use the LanMan hash if it is available */ Globals.bLanmanAuth = True; /* Do use the LanMan hash if it is available */ Globals.bNTLMAuth = True; /* Do use NTLMv1 if it is available (otherwise NTLMv2) */ - Globals.map_to_guest = 0; /* By Default, "Never" */ Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */ Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */ @@ -1461,7 +1436,6 @@ static void init_globals(void) Globals.name_cache_timeout = 660; /* In seconds */ Globals.bUseSpnego = True; - Globals.bClientUseSpnego = True; string_set(&Globals.smb_ports, SMB_PORTS); } @@ -1603,8 +1577,6 @@ FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName) static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion) FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases) FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend) -FN_GLOBAL_LIST(lp_sam_backend, &Globals.szSamBackend) -FN_GLOBAL_LIST(lp_modules, &Globals.szModules) FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction) FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript) FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript) @@ -1686,15 +1658,12 @@ FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains) FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous) FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth) FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth) -FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth) -FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth) FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs) FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks) FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing) FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap) FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions) FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) -FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups) FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify) FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level) @@ -1839,9 +1808,51 @@ FN_LOCAL_INTEGER(lp_block_size, iBlock_size) FN_LOCAL_CHAR(lp_magicchar, magic_char) FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time) FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers) -FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase) +FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase) FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout) -FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing) + +typedef struct _param_opt_struct param_opt_struct; +struct _param_opt_struct { + char *key; + char *value; + param_opt_struct *prev, *next; +}; + +static param_opt_struct *param_opt = NULL; + +/* Return parametric option from given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ +/* Returned value is allocated in 'lp_talloc' context */ + +char *lp_parm_string(const char *servicename, const char *type, const char *option) +{ + param_opt_struct *data; + pstring vfskey; + + if (param_opt != NULL) { + ZERO_STRUCT(vfskey); + pstr_sprintf(vfskey, "%s:%s:%s", (servicename==NULL) ? "global" : servicename, + type, option); + data = param_opt; + while (data) { + if (strcmp(data->key, vfskey) == 0) { + return lp_string(data->value); + } + data = data->next; + } + /* Try to fetch the same option but from globals */ + pstr_sprintf(vfskey, "global:%s:%s", type, option); + data = param_opt; + while (data) { + if (strcmp(data->key, vfskey) == 0) { + return lp_string(data->value); + } + data = data->next; + } + + } + return NULL; +} /* local prototypes */ @@ -1856,198 +1867,6 @@ static BOOL do_parameter(const char *pszParmName, const char *pszParmValue); static BOOL do_section(const char *pszSectionName); static void init_copymap(service * pservice); -/* This is a helper function for parametrical options support. */ -/* It returns a pointer to parametrical option value if it exists or NULL otherwise */ -/* Actual parametrical functions are quite simple */ -static const char *get_parametrics(int lookup_service, const char *type, const char *option) -{ - char* vfskey; - param_opt_struct *data; - - if (lookup_service >= iNumServices) return NULL; - - data = (lookup_service < 0) ? - Globals.param_opt : ServicePtrs[lookup_service]->param_opt; - - asprintf(&vfskey, "%s:%s", type, option); - while (data) { - if (strcmp(data->key, vfskey) == 0) { - string_free(&vfskey); - return data->value; - } - data = data->next; - } - - if (lookup_service >= 0) { - /* Try to fetch the same option but from globals */ - /* but only if we are not already working with Globals */ - data = Globals.param_opt; - while (data) { - if (strcmp(data->key, vfskey) == 0) { - string_free(&vfskey); - return data->value; - } - data = data->next; - } - } - - string_free(&vfskey); - - return NULL; -} - - -/******************************************************************* -convenience routine to return int parameters. -********************************************************************/ -static int lp_int(const char *s) -{ - - if (!s) { - DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); - return (-1); - } - - return atoi(s); -} - -/******************************************************************* -convenience routine to return unsigned long parameters. -********************************************************************/ -static int lp_ulong(const char *s) -{ - - if (!s) { - DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); - return (-1); - } - - return strtoul(s, NULL, 10); -} - -/******************************************************************* -convenience routine to return boolean parameters. -********************************************************************/ -static BOOL lp_bool(const char *s) -{ - BOOL ret = False; - - if (!s) { - DEBUG(0,("lp_bool(%s): is called with NULL!\n",s)); - return False; - } - - if (!set_boolean(&ret,s)) { - DEBUG(0,("lp_bool(%s): value is not boolean!\n",s)); - return False; - } - - return ret; -} - -/******************************************************************* -convenience routine to return enum parameters. -********************************************************************/ -static int lp_enum(const char *s,const struct enum_list *_enum) -{ - int i; - - if (!s || !_enum) { - DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s)); - return False; - } - - for (i=0; _enum[i].name; i++) { - if (strcasecmp(_enum[i].name,s)==0) - return _enum[i].value; - } - - DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s)); - return (-1); -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ -/* Returned value is allocated in 'lp_talloc' context */ - -char *lp_parm_string(int lookup_service, const char *type, const char *option) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return lp_string(value); - - return NULL; -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ -/* Returned value is allocated in 'lp_talloc' context */ - -char **lp_parm_string_list(int lookup_service, const char *type, const char *option, - const char *separator) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return str_list_make(value, separator); - - return NULL; -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ - -int lp_parm_int(int lookup_service, const char *type, const char *option) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return lp_int(value); - - return (-1); -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ - -unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return lp_ulong(value); - - return (0); -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ - -BOOL lp_parm_bool(int lookup_service, const char *type, const char *option) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return lp_bool(value); - - return False; -} - -/* Return parametric option from a given service. Type is a part of option before ':' */ -/* Parametric option has following syntax: 'Type: option = value' */ - -int lp_parm_enum(int lookup_service, const char *type, const char *option, - const struct enum_list *_enum) -{ - const char *value = get_parametrics(lookup_service, type, option); - - if (value) - return lp_enum(value, _enum); - - return (-1); -} - /*************************************************************************** Initialise a service to the defaults. @@ -2066,7 +1885,6 @@ static void init_service(service * pservice) static void free_service(service *pservice) { int i; - param_opt_struct *data, *pdata; if (!pservice) return; @@ -2091,16 +1909,6 @@ static void free_service(service *pservice) PTR_DIFF(parm_table[i].ptr, &sDefault))); } - DEBUG(5,("Freeing parametrics:\n")); - data = pservice->param_opt; - while (data) { - DEBUG(5,("[%s = %s]\n", data->key, data->value)); - string_free(&data->key); - string_free(&data->value); - pdata = data->next; - SAFE_FREE(data); - data = pdata; - } ZERO_STRUCTP(pservice); } @@ -2115,27 +1923,14 @@ static int add_a_service(const service *pservice, const char *name) int i; service tservice; int num_to_alloc = iNumServices + 1; - param_opt_struct *data, *pdata; tservice = *pservice; /* it might already exist */ if (name) { i = getservicebyname(name, NULL); - if (i >= 0) { - /* Clean all parametric options for service */ - /* They will be added during parsing again */ - data = ServicePtrs[i]->param_opt; - while (data) { - string_free(&data->key); - string_free(&data->value); - pdata = data->next; - SAFE_FREE(data); - data = pdata; - } - ServicePtrs[i]->param_opt = NULL; + if (i >= 0) return (i); - } } /* find an invalid one */ @@ -2378,8 +2173,6 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL { int i; BOOL bcopyall = (pcopymapDest == NULL); - param_opt_struct *data, *pdata, *paramo; - BOOL not_added; for (i = 0; parm_table[i].label; i++) if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && @@ -2433,30 +2226,6 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL (void *)pserviceSource->copymap, sizeof(BOOL) * NUMPARAMETERS); } - - data = pserviceSource->param_opt; - while (data) { - not_added = True; - pdata = pserviceDest->param_opt; - /* Traverse destination */ - while (pdata) { - /* If we already have same option, override it */ - if (strcmp(pdata->key, data->key) == 0) { - string_free(&pdata->value); - pdata->value = strdup(data->value); - not_added = False; - break; - } - pdata = pdata->next; - } - if (not_added) { - paramo = smb_xmalloc(sizeof(param_opt_struct)); - paramo->key = strdup(data->key); - paramo->value = strdup(data->value); - DLIST_ADD(pserviceDest->param_opt, paramo); - } - data = data->next; - } } /*************************************************************************** @@ -3071,8 +2840,7 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue void *def_ptr = NULL; pstring vfskey; char *sep; - param_opt_struct *paramo, *data; - BOOL not_added; + param_opt_struct *paramo; parmnum = map_parameter(pszParmName); @@ -3080,35 +2848,15 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue if ((sep=strchr(pszParmName, ':')) != NULL) { *sep = 0; ZERO_STRUCT(vfskey); - pstr_sprintf(vfskey, "%s:", pszParmName); + pstr_sprintf(vfskey, "%s:%s:", + (snum >= 0) ? lp_servicename(snum) : "global", pszParmName); slen = strlen(vfskey); safe_strcat(vfskey, sep+1, sizeof(pstring)); trim_string(vfskey+slen, " ", " "); - not_added = True; - data = (snum < 0) ? Globals.param_opt : - ServicePtrs[snum]->param_opt; - /* Traverse destination */ - while (data) { - /* If we already have same option, override it */ - if (strcmp(data->key, vfskey) == 0) { - string_free(&data->value); - data->value = strdup(pszParmValue); - not_added = False; - break; - } - data = data->next; - } - if (not_added) { - paramo = smb_xmalloc(sizeof(param_opt_struct)); - paramo->key = strdup(vfskey); - paramo->value = strdup(pszParmValue); - if (snum < 0) { - DLIST_ADD(Globals.param_opt, paramo); - } else { - DLIST_ADD(ServicePtrs[snum]->param_opt, paramo); - } - } - + paramo = smb_xmalloc(sizeof(param_opt_struct)); + paramo->key = strdup(vfskey); + paramo->value = strdup(pszParmValue); + DLIST_ADD(param_opt, paramo); *sep = ':'; return (True); } @@ -3457,6 +3205,7 @@ static void dump_globals(FILE *f) { int i; param_opt_struct *data; + char *s; fprintf(f, "# Global parameters\n[global]\n"); @@ -3470,11 +3219,14 @@ static void dump_globals(FILE *f) print_parameter(&parm_table[i], parm_table[i].ptr, f); fprintf(f, "\n"); } - if (Globals.param_opt != NULL) { - data = Globals.param_opt; + if (param_opt != NULL) { + data = param_opt; while(data) { - fprintf(f, "\t%s = %s\n", data->key, data->value); - data = data->next; + if (((s=strstr(data->key, "global")) == data->key) && + (*(s+strlen("global")) == ':')) { + fprintf(f, "\t%s = %s\n", s+strlen("global")+1, data->value); + } + data = data->next; } } @@ -3501,6 +3253,7 @@ static void dump_a_service(service * pService, FILE * f) { int i; param_opt_struct *data; + char *s, *sn; if (pService != &sDefault) fprintf(f, "\n[%s]\n", pService->szService); @@ -3529,11 +3282,15 @@ static void dump_a_service(service * pService, FILE * f) ((char *)pService) + pdiff, f); fprintf(f, "\n"); } - if (pService->param_opt != NULL) { - data = pService->param_opt; + if (param_opt != NULL) { + data = param_opt; + sn = (pService == &sDefault) ? "global" : pService->szService; while(data) { - fprintf(f, "\t%s = %s\n", data->key, data->value); - data = data->next; + if (((s=strstr(data->key, sn)) == data->key) && + (*(s+strlen(sn)) == ':')) { + fprintf(f, "\t%s = %s\n", s+strlen(sn)+1, data->value); + } + data = data->next; } } } @@ -3868,16 +3625,16 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, lp_save_defaults(); } - if (Globals.param_opt != NULL) { - data = Globals.param_opt; + if (param_opt != NULL) { + data = param_opt; while (data) { - string_free(&data->key); - string_free(&data->value); + SAFE_FREE(data->key); + SAFE_FREE(data->value); pdata = data->next; SAFE_FREE(data); data = pdata; } - Globals.param_opt = NULL; + param_opt = NULL; } /* We get sections first, so have to start 'behind' to make up */ |