s3: winbindd: Add new parameter "winbind request timeout" set to 60 seconds with...
[kai/samba-autobuild/.git] / source3 / param / loadparm.c
index 3f16b57b696ae03f6e5353e1b0c93081732e16c5..13bd9b9ff0b8c82d76faf9e8d3c5f208ba633730 100644 (file)
@@ -257,25 +257,13 @@ static struct db_context *ServiceHash;
 static bool bInGlobalSection = true;
 static bool bGlobalOnly = false;
 static struct file_lists *file_lists = NULL;
-
-#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
-
-/* prototypes for the special type handlers */
-static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
+static unsigned int *flags_list = NULL;
 
 static void set_allowed_client_auth(void);
 
-static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
 static void free_param_opts(struct parmlist_entry **popts);
 
-#include "lib/param/param_table.c"
-
 /* this is used to prevent lots of mallocs of size 1 */
 static const char null_string[] = "";
 
@@ -322,7 +310,7 @@ bool lp_string_set(char **dest, const char *src) {
  Initialise the sDefault parameter structure for the printer values.
 ***************************************************************************/
 
-static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
+void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
 {
        /* choose defaults depending on the type of printing */
        switch (pService->printing) {
@@ -330,52 +318,52 @@ static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pServi
                case PRINT_AIX:
                case PRINT_LPRNT:
                case PRINT_LPROS2:
-                       string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
-                       string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
-                       string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
                        break;
 
                case PRINT_LPRNG:
                case PRINT_PLP:
-                       string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
-                       string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
-                       string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
-                       string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
-                       string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
-                       string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
-                       string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
                        break;
 
                case PRINT_CUPS:
                case PRINT_IPRINT:
                        /* set the lpq command to contain the destination printer
                           name only.  This is used by cups_queue_get() */
-                       string_set(ctx, &pService->lpq_command, "%p");
-                       string_set(ctx, &pService->lprm_command, "");
-                       string_set(ctx, &pService->print_command, "");
-                       string_set(ctx, &pService->lppause_command, "");
-                       string_set(ctx, &pService->lpresume_command, "");
-                       string_set(ctx, &pService->queuepause_command, "");
-                       string_set(ctx, &pService->queueresume_command, "");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "");
+                       lpcfg_string_set(ctx, &pService->print_command, "");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "");
                        break;
 
                case PRINT_SYSV:
                case PRINT_HPUX:
-                       string_set(ctx, &pService->lpq_command, "lpstat -o%p");
-                       string_set(ctx, &pService->lprm_command, "cancel %p-%j");
-                       string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
-                       string_set(ctx, &pService->queuepause_command, "disable %p");
-                       string_set(ctx, &pService->queueresume_command, "enable %p");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpstat -o%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "cancel %p-%j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "disable %p");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "enable %p");
 #ifndef HPUX
-                       string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
-                       string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
 #endif /* HPUX */
                        break;
 
                case PRINT_QNX:
-                       string_set(ctx, &pService->lpq_command, "lpq -P%p");
-                       string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
-                       string_set(ctx, &pService->print_command, "lp -r -P%p %s");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lp -r -P%p %s");
                        break;
 
 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
@@ -383,7 +371,7 @@ static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pServi
        case PRINT_TEST:
        case PRINT_VLP: {
                const char *tdbfile;
-               TALLOC_CTX *tmp_ctx = talloc_stackframe();
+               TALLOC_CTX *tmp_ctx = talloc_new(ctx);
                char *tmp;
 
                tdbfile = talloc_asprintf(
@@ -396,37 +384,37 @@ static void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pServi
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
                                      tdbfile);
-               string_set(ctx, &pService->print_command,
+               lpcfg_string_set(ctx, &pService->print_command,
                           tmp ? tmp : "vlp print %p %s");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
                                      tdbfile);
-               string_set(ctx, &pService->lpq_command,
+               lpcfg_string_set(ctx, &pService->lpq_command,
                           tmp ? tmp : "vlp lpq %p");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
                                      tdbfile);
-               string_set(ctx, &pService->lprm_command,
+               lpcfg_string_set(ctx, &pService->lprm_command,
                           tmp ? tmp : "vlp lprm %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
                                      tdbfile);
-               string_set(ctx, &pService->lppause_command,
+               lpcfg_string_set(ctx, &pService->lppause_command,
                           tmp ? tmp : "vlp lppause %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
                                      tdbfile);
-               string_set(ctx, &pService->lpresume_command,
+               lpcfg_string_set(ctx, &pService->lpresume_command,
                           tmp ? tmp : "vlp lpresume %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
                                      tdbfile);
-               string_set(ctx, &pService->queuepause_command,
+               lpcfg_string_set(ctx, &pService->queuepause_command,
                           tmp ? tmp : "vlp queuepause %p");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
                                      tdbfile);
-               string_set(ctx, &pService->queueresume_command,
+               lpcfg_string_set(ctx, &pService->queueresume_command,
                           tmp ? tmp : "vlp queueresume %p");
                TALLOC_FREE(tmp_ctx);
 
@@ -500,7 +488,7 @@ static void free_one_parameter_common(void *parm_ptr,
            (parm.type == P_USTRING))
        {
                string_free((char**)parm_ptr);
-       } else if (parm.type == P_LIST) {
+       } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
                TALLOC_FREE(*((char***)parm_ptr));
        }
 }
@@ -549,7 +537,7 @@ static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
        } else if (parm.p_class != P_LOCAL) {
                return;
        } else {
-               parm_ptr = lp_local_ptr_by_snum(snum, &parm);
+               parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm);
        }
 
        free_one_parameter_common(parm_ptr, parm);
@@ -591,7 +579,7 @@ static struct lp_stored_option *stored_options;
   re-applied when we do a globals reset, so that cmdline set options
   are sticky across reloads of smb.conf
  */
-static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
+bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
 {
        struct lp_stored_option *entry, *entry_next;
        for (entry = stored_options; entry != NULL; entry = entry_next) {
@@ -629,7 +617,7 @@ static bool apply_lp_set_cmdline(void)
 {
        struct lp_stored_option *entry = NULL;
        for (entry = stored_options; entry != NULL; entry = entry->next) {
-               if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
+               if (!lp_set_cmdline_helper(entry->label, entry->value)) {
                        DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
                                  entry->label, entry->value));
                        return false;
@@ -673,6 +661,11 @@ static void init_globals(bool reinit_globals)
 
        Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
 
+       /* Initialize the flags list if necessary */
+       if (flags_list == NULL) {
+               get_flags();
+       }
+
        for (i = 0; parm_table[i].label; i++) {
                if ((parm_table[i].type == P_STRING ||
                     parm_table[i].type == P_USTRING))
@@ -920,6 +913,7 @@ static void init_globals(bool reinit_globals)
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
+       Globals.winbind_request_timeout = 60;   /* 60 seconds */
        Globals.winbind_max_clients = 200;
        Globals.winbind_enum_users = false;
        Globals.winbind_enum_groups = false;
@@ -982,7 +976,7 @@ static void init_globals(bool reinit_globals)
 
        string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
 
-       Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns", NULL);
+       Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
 
        Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
 
@@ -1166,6 +1160,7 @@ FN_LOCAL_CONST_STRING(const_servicename, szService)
 
 /* These functions cannot be auto-generated */
 FN_LOCAL_BOOL(autoloaded, autoloaded)
+FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
 
 /* local prototypes */
 
@@ -1173,65 +1168,11 @@ static int map_parameter_canonical(const char *pszParmName, bool *inverse);
 static const char *get_boolean(bool bool_value);
 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
                         void *userdata);
-static bool do_section(const char *pszSectionName, void *userdata);
 static bool hash_a_service(const char *name, int number);
 static void free_service_byindex(int iService);
 static void show_parameter(int parmIndex);
 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
 
-/*
- * 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 struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
-                                                          const char *option)
-{
-       bool global_section = false;
-       char* param_key;
-        struct parmlist_entry *data;
-       TALLOC_CTX *mem_ctx = talloc_stackframe();
-
-       if (service == NULL) {
-               data = Globals.param_opt;
-               global_section = true;
-       } else {
-               data = service->param_opt;
-       }
-
-       param_key = talloc_asprintf(mem_ctx, "%s:%s", type, option);
-       if (param_key == NULL) {
-               DEBUG(0,("asprintf failed!\n"));
-               TALLOC_FREE(mem_ctx);
-               return NULL;
-       }
-
-       while (data) {
-               if (strwicmp(data->key, param_key) == 0) {
-                       TALLOC_FREE(mem_ctx);
-                       return data;
-               }
-               data = data->next;
-       }
-
-       if (!global_section) {
-               /* 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 (strwicmp(data->key, param_key) == 0) {
-                               TALLOC_FREE(mem_ctx);
-                               return data;
-                       }
-                       data = data->next;
-               }
-       }
-
-       TALLOC_FREE(mem_ctx);
-
-       return NULL;
-}
-
 /*
  * This is a helper function for parametrical options support.  It returns a
  * pointer to parametrical option value if it exists or NULL otherwise. Actual
@@ -1243,9 +1184,10 @@ static struct parmlist_entry *get_parametrics(int snum, const char *type,
        if (snum >= iNumServices) return NULL;
 
        if (snum < 0) {
-               return get_parametrics_by_service(NULL, type, option);
+               return get_parametric_helper(NULL, type, option, Globals.param_opt);
        } else {
-               return get_parametrics_by_service(ServicePtrs[snum], type, option);
+               return get_parametric_helper(ServicePtrs[snum],
+                                            type, option, Globals.param_opt);
        }
 }
 
@@ -1253,54 +1195,6 @@ static struct parmlist_entry *get_parametrics(int snum, const char *type,
 #define MISSING_PARAMETER(name) \
     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
 
-/*******************************************************************
-convenience routine to return int parameters.
-********************************************************************/
-static int lp_int(const char *s)
-{
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_int);
-               return (-1);
-       }
-
-       return (int)strtol(s, NULL, 0);
-}
-
-/*******************************************************************
-convenience routine to return unsigned long parameters.
-********************************************************************/
-static unsigned long lp_ulong(const char *s)
-{
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_ulong);
-               return (0);
-       }
-
-       return strtoul(s, NULL, 0);
-}
-
-/*******************************************************************
-convenience routine to return boolean parameters.
-********************************************************************/
-static bool lp_bool(const char *s)
-{
-       bool ret = false;
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_bool);
-               return false;
-       }
-
-       if (!set_boolean(s, &ret)) {
-               DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
-               return false;
-       }
-
-       return ret;
-}
-
 /*******************************************************************
 convenience routine to return enum parameters.
 ********************************************************************/
@@ -1353,16 +1247,6 @@ const char *lp_parm_const_string(int snum, const char *type, const char *option,
        return data->value;
 }
 
-const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
-{
-       struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
-
-       if (data == NULL||data->value==NULL)
-               return NULL;
-
-       return data->value;
-}
-
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
@@ -2195,14 +2079,24 @@ static bool process_smbconf_service(struct smbconf_service *service)
                return false;
        }
 
-       ret = do_section(service->name, NULL);
+       ret = lp_do_section(service->name, NULL);
        if (ret != true) {
                return false;
        }
        for (count = 0; count < service->num_params; count++) {
-               ret = do_parameter(service->param_names[count],
-                                  service->param_values[count],
-                                  NULL);
+
+               if (!bInGlobalSection && bGlobalOnly) {
+                       ret = true;
+               } else {
+                       const char *pszParmName = service->param_names[count];
+                       const char *pszParmValue = service->param_values[count];
+
+                       DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
+
+                       ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
+                                             pszParmName, pszParmValue);
+               }
+
                if (ret != true) {
                        return false;
                }
@@ -2266,7 +2160,18 @@ static bool process_registry_globals(void)
 
        add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
 
-       ret = do_parameter("registry shares", "yes", NULL);
+       if (!bInGlobalSection && bGlobalOnly) {
+               ret = true;
+       } else {
+               const char *pszParmName = "registry shares";
+               const char *pszParmValue = "yes";
+
+               DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
+
+               ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
+                                     pszParmName, pszParmValue);
+       }
+
        if (!ret) {
                return ret;
        }
@@ -2458,19 +2363,13 @@ static void init_iconv(void)
                                                      true, global_iconv_handle);
 }
 
-static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       TALLOC_FREE(Globals.netbios_aliases);
-       Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
-       return set_netbios_aliases(Globals.netbios_aliases);
-}
-
 /***************************************************************************
  Handle the include operation.
 ***************************************************************************/
 static bool bAllowIncludeRegistry = true;
 
-static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
+bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+               const char *pszParmValue, char **ptr)
 {
        char *fname;
 
@@ -2484,7 +2383,7 @@ static bool handle_include(struct loadparm_context *unused, int snum, const char
                if (!bAllowIncludeRegistry) {
                        return true;
                }
-               if (bInGlobalSection) {
+               if (lp_ctx->bInGlobalSection) {
                        bool ret;
                        include_depth++;
                        ret = process_registry_globals();
@@ -2503,16 +2402,16 @@ static bool handle_include(struct loadparm_context *unused, int snum, const char
 
        add_to_file_list(NULL, &file_lists, pszParmValue, fname);
 
-       if (snum < 0) {
+       if (service == NULL) {
                string_set(Globals.ctx, ptr, fname);
        } else {
-               string_set(ServicePtrs[snum], ptr, fname);
+               string_set(service, ptr, fname);
        }
 
        if (file_exist(fname)) {
                bool ret;
                include_depth++;
-               ret = pm_process(fname, do_section, do_parameter, NULL);
+               ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
                include_depth--;
                TALLOC_FREE(fname);
                return ret;
@@ -2523,38 +2422,6 @@ static bool handle_include(struct loadparm_context *unused, int snum, const char
        return true;
 }
 
-static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       Globals.ldap_debug_level = lp_int(pszParmValue);
-       init_ldap_debugging();
-       return true;
-}
-
-/*
- * idmap related parameters
- */
-
-static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
-
-       return true;
-}
-
-static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : range", pszParmValue);
-
-       return true;
-}
-
-static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : range", pszParmValue);
-
-       return true;
-}
-
 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
 {
        char *config_option = NULL;
@@ -2682,49 +2549,6 @@ const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
        return lp_string(ctx, Globals.ldap_suffix);
 }
 
-/****************************************************************************
- set the value for a P_ENUM
- ***************************************************************************/
-
-static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
-                              int *ptr )
-{
-       int i;
-
-       for (i = 0; parm->enum_list[i].name; i++) {
-               if ( strequal(pszParmValue, parm->enum_list[i].name)) {
-                       *ptr = parm->enum_list[i].value;
-                       return;
-               }
-       }
-       DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
-                 pszParmValue, parm->label));
-}
-
-/***************************************************************************
-***************************************************************************/
-
-static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       static int parm_num = -1;
-       struct loadparm_service *s;
-
-       if ( parm_num == -1 )
-               parm_num = lpcfg_map_parameter( "printing" );
-
-       lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
-
-       if ( snum < 0 ) {
-               s = &sDefault;
-               init_printer_values(Globals.ctx, s);
-       } else {
-               s = ServicePtrs[snum];
-               init_printer_values(s, s);
-       }
-
-       return true;
-}
-
 /**
   return the parameter pointer for a parameter
 */
@@ -2741,15 +2565,6 @@ void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
        }
 }
 
-/***************************************************************************
- Return the local pointer to a parameter given the service number and parameter
-***************************************************************************/
-
-void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
-{
-       return lp_parm_ptr(ServicePtrs[snum], parm);
-}
-
 /***************************************************************************
  Process a parameter for a particular service number. If snum < 0
  then assume we are in the globals.
@@ -2761,6 +2576,10 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
        void *parm_ptr = NULL;  /* where we are going to store the result */
        struct parmlist_entry **opt_list;
        TALLOC_CTX *mem_ctx;
+       TALLOC_CTX *frame = talloc_stackframe();
+       bool ok;
+       struct loadparm_context *lp_ctx;
+       struct loadparm_service *service = NULL;
 
        parmnum = lpcfg_map_parameter(pszParmName);
 
@@ -2768,6 +2587,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                if (strchr(pszParmName, ':') == NULL) {
                        DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
                                  pszParmName));
+                       TALLOC_FREE(frame);
                        return true;
                }
 
@@ -2783,12 +2603,14 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        set_param_opt(ServicePtrs[snum], opt_list, pszParmName, pszParmValue, 0);
                }
 
+               TALLOC_FREE(frame);
                return true;
        }
 
        /* if it's already been set by the command line, then we don't
           override here */
-       if (parm_table[parmnum].flags & FLAG_CMDLINE) {
+       if (flags_list[parmnum] & FLAG_CMDLINE) {
+               TALLOC_FREE(frame);
                return true;
        }
 
@@ -2800,17 +2622,17 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
        /* we might point at a service, the default service or a global */
        if (snum < 0) {
                parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
+               mem_ctx = Globals.ctx;
        } else {
                if (parm_table[parmnum].p_class == P_GLOBAL) {
                        DEBUG(0,
                              ("Global parameter %s found in service section!\n",
                               pszParmName));
+                       TALLOC_FREE(frame);
                        return true;
                }
-               parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
-       }
+               parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm_table[parmnum]);
 
-       if (snum >= 0) {
                if (!ServicePtrs[snum]->copymap)
                        init_copymap(ServicePtrs[snum]);
 
@@ -2822,91 +2644,29 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                                bitmap_clear(ServicePtrs[snum]->copymap, i);
                        }
                }
+
                mem_ctx = ServicePtrs[snum];
-       } else {
-               mem_ctx = Globals.ctx;
+               service = ServicePtrs[snum];
        }
 
-       /* if it is a special case then go ahead */
-       if (parm_table[parmnum].special) {
-               bool ok;
-               struct loadparm_context *lp_ctx = loadparm_init_s3(talloc_tos(),
-                                                                  loadparm_s3_helpers());
-               ok = parm_table[parmnum].special(lp_ctx, snum, pszParmValue,
-                                                 (char **)parm_ptr);
-               TALLOC_FREE(lp_ctx);
-
-               return ok;
+       lp_ctx = loadparm_init_s3(frame,
+                                 loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
+               DEBUG(0, ("loadparm_init_s3 failed\n"));
+               TALLOC_FREE(frame);
+               return false;
        }
 
-       /* now switch on the type of variable it is */
-       switch (parm_table[parmnum].type)
-       {
-               case P_BOOL:
-                       *(bool *)parm_ptr = lp_bool(pszParmValue);
-                       break;
-
-               case P_BOOLREV:
-                       *(bool *)parm_ptr = !lp_bool(pszParmValue);
-                       break;
-
-               case P_INTEGER:
-                       *(int *)parm_ptr = lp_int(pszParmValue);
-                       break;
+       lp_ctx->sDefault = &sDefault;
+       lp_ctx->services = ServicePtrs;
+       lp_ctx->bInGlobalSection = bInGlobalSection;
+       lp_ctx->flags = flags_list;
 
-               case P_CHAR:
-                       *(char *)parm_ptr = *pszParmValue;
-                       break;
-
-               case P_OCTAL:
-                       i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
-                       if ( i != 1 ) {
-                           DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
-                       }
-                       break;
-
-               case P_BYTES:
-               {
-                       uint64_t val;
-                       if (conv_str_size_error(pszParmValue, &val)) {
-                               if (val <= INT_MAX) {
-                                       *(int *)parm_ptr = (int)val;
-                                       break;
-                               }
-                       }
-
-                       DEBUG(0,("lp_do_parameter(%s): value is not "
-                           "a valid size specifier!\n", pszParmValue));
-                       return false;
-               }
-
-               case P_LIST:
-               case P_CMDLIST:
-                       TALLOC_FREE(*((char ***)parm_ptr));
-                       *(char ***)parm_ptr = str_list_make_v3(
-                               NULL, pszParmValue, NULL);
-                       break;
-
-               case P_STRING:
-                       string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
-                       break;
-
-               case P_USTRING:
-               {
-                       char *upper_string = strupper_talloc(talloc_tos(), 
-                                                            pszParmValue);
-                       string_set(mem_ctx, (char **)parm_ptr, upper_string);
-                       TALLOC_FREE(upper_string);
-                       break;
-               }
-               case P_ENUM:
-                       lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
-                       break;
-               case P_SEP:
-                       break;
-       }
+       ok = set_variable(mem_ctx, service, parmnum, parm_ptr, pszParmName, pszParmValue,
+                           lp_ctx, (snum < 0));
+       TALLOC_FREE(frame);
 
-       return true;
+       return ok;
 }
 
 /***************************************************************************
@@ -2914,16 +2674,16 @@ set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
 FLAG_CMDLINE won't be overridden by loads from smb.conf.
 ***************************************************************************/
 
-static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
 {
        int parmnum, i;
        parmnum = lpcfg_map_parameter(pszParmName);
        if (parmnum >= 0) {
-               parm_table[parmnum].flags &= ~FLAG_CMDLINE;
+               flags_list[parmnum] &= ~FLAG_CMDLINE;
                if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
                        return false;
                }
-               parm_table[parmnum].flags |= FLAG_CMDLINE;
+               flags_list[parmnum] |= FLAG_CMDLINE;
 
                /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
                 * be grouped in the table, so we don't have to search the
@@ -2932,35 +2692,42 @@ static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmVa
                     i>=0 && parm_table[i].offset == parm_table[parmnum].offset
                             && parm_table[i].p_class == parm_table[parmnum].p_class;
                     i--) {
-                       parm_table[i].flags |= FLAG_CMDLINE;
+                       flags_list[i] |= FLAG_CMDLINE;
                }
-               for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
+               for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
                             && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
-                       parm_table[i].flags |= FLAG_CMDLINE;
+                       flags_list[i] |= FLAG_CMDLINE;
                }
 
-               if (store_values) {
-                       store_lp_set_cmdline(pszParmName, pszParmValue);
-               }
                return true;
        }
 
        /* it might be parametric */
        if (strchr(pszParmName, ':') != NULL) {
                set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
-               if (store_values) {
-                       store_lp_set_cmdline(pszParmName, pszParmValue);
-               }
                return true;
        }
 
        DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
-       return true;
+       return false;
 }
 
 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
 {
-       return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
+       bool ret;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx;
+
+       lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
+               DEBUG(0, ("loadparm_init_s3 failed\n"));
+               return false;
+       }
+
+       ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
+
+       TALLOC_FREE(frame);
+       return ret;
 }
 
 /***************************************************************************
@@ -3022,7 +2789,7 @@ static void init_locals(void)
  Returns true on success, false on failure.
 ***************************************************************************/
 
-static bool do_section(const char *pszSectionName, void *userdata)
+bool lp_do_section(const char *pszSectionName, void *userdata)
 {
        bool bRetval;
        bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
@@ -3114,7 +2881,7 @@ static bool is_default(int i)
 Display the contents of the global structure.
 ***************************************************************************/
 
-static void dump_globals(FILE *f)
+static void dump_globals(FILE *f, bool show_defaults)
 {
        int i;
        struct parmlist_entry *data;
@@ -3125,7 +2892,7 @@ static void dump_globals(FILE *f)
                if (parm_table[i].p_class == P_GLOBAL &&
                    !(parm_table[i].flags & FLAG_META) &&
                    (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
-                       if (defaults_saved && is_default(i))
+                       if (show_defaults && is_default(i))
                                continue;
                        fprintf(f, "\t%s = ", parm_table[i].label);
                        lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
@@ -3136,6 +2903,10 @@ static void dump_globals(FILE *f)
        if (Globals.param_opt != NULL) {
                data = Globals.param_opt;
                while(data) {
+                       if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
+                               data = data->next;
+                               continue;
+                       }
                        fprintf(f, "\t%s = %s\n", data->key, data->value);
                        data = data->next;
                }
@@ -3143,52 +2914,6 @@ static void dump_globals(FILE *f)
 
 }
 
-/***************************************************************************
- Display the contents of a single services record.
-***************************************************************************/
-
-static void dump_a_service(struct loadparm_service *pService, FILE * f)
-{
-       int i;
-       struct parmlist_entry *data;
-
-       if (pService != &sDefault)
-               fprintf(f, "[%s]\n", pService->szService);
-
-       for (i = 0; parm_table[i].label; i++) {
-
-               if (parm_table[i].p_class == P_LOCAL &&
-                   !(parm_table[i].flags & FLAG_META) &&
-                   (*parm_table[i].label != '-') &&
-                   (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
-               {
-                       if (pService == &sDefault) {
-                               if (defaults_saved && is_default(i))
-                                       continue;
-                       } else {
-                               if (lpcfg_equal_parameter(parm_table[i].type,
-                                                         lp_parm_ptr(pService, &parm_table[i]),
-                                                         lp_parm_ptr(NULL, &parm_table[i])))
-                                       continue;
-                       }
-
-                       fprintf(f, "\t%s = ", parm_table[i].label);
-                       lpcfg_print_parameter(&parm_table[i],
-                                       lp_parm_ptr(pService, &parm_table[i]),
-                                       f);
-                       fprintf(f, "\n");
-               }
-       }
-
-               if (pService->param_opt != NULL) {
-                       data = pService->param_opt;
-                       while(data) {
-                               fprintf(f, "\t%s = %s\n", data->key, data->value);
-                               data = data->next;
-                       }
-               }
-}
-
 /***************************************************************************
  Display the contents of a parameter of a single services record.
 ***************************************************************************/
@@ -3196,30 +2921,9 @@ static void dump_a_service(struct loadparm_service *pService, FILE * f)
 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
 {
        bool result = false;
-       fstring local_parm_name;
-       char *parm_opt;
-       const char *parm_opt_value;
 
        struct loadparm_context *lp_ctx;
 
-       /* check for parametrical option */
-       fstrcpy( local_parm_name, parm_name);
-       parm_opt = strchr( local_parm_name, ':');
-
-       if (parm_opt) {
-               *parm_opt = '\0';
-               parm_opt++;
-               if (strlen(parm_opt)) {
-                       parm_opt_value = lp_parm_const_string( snum,
-                               local_parm_name, parm_opt, NULL);
-                       if (parm_opt_value) {
-                               printf( "%s\n", parm_opt_value);
-                               result = true;
-                       }
-               }
-               return result;
-       }
-
        lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
        if (lp_ctx == NULL) {
                return false;
@@ -3400,7 +3104,12 @@ void lp_killservice(int iServiceIn)
 static void lp_save_defaults(void)
 {
        int i;
+       struct parmlist_entry * parm;
        for (i = 0; parm_table[i].label; i++) {
+               if (!(flags_list[i] & FLAG_CMDLINE)) {
+                       flags_list[i] |= FLAG_DEFAULT;
+               }
+
                if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
                    && parm_table[i].p_class == parm_table[i - 1].p_class)
                        continue;
@@ -3437,6 +3146,19 @@ static void lp_save_defaults(void)
                                break;
                }
        }
+
+       for (parm=Globals.param_opt; parm; parm=parm->next) {
+               if (!(parm->priority & FLAG_CMDLINE)) {
+                       parm->priority |= FLAG_DEFAULT;
+               }
+       }
+
+       for (parm=sDefault.param_opt; parm; parm=parm->next) {
+               if (!(parm->priority & FLAG_CMDLINE)) {
+                       parm->priority |= FLAG_DEFAULT;
+               }
+       }
+
        defaults_saved = true;
 }
 
@@ -4222,6 +3944,7 @@ static bool lp_load_ex(const char *pszFname,
 {
        char *n2 = NULL;
        bool bRetval;
+       TALLOC_CTX *frame = talloc_stackframe();
 
        bRetval = false;
 
@@ -4260,7 +3983,7 @@ static bool lp_load_ex(const char *pszFname,
 
                add_to_file_list(NULL, &file_lists, pszFname, n2);
 
-               bRetval = pm_process(n2, do_section, do_parameter, NULL);
+               bRetval = pm_process(n2, lp_do_section, do_parameter, NULL);
                TALLOC_FREE(n2);
 
                /* finish up the last section */
@@ -4272,6 +3995,7 @@ static bool lp_load_ex(const char *pszFname,
                }
 
                if (lp_config_backend_is_registry()) {
+                       bool ok;
                        /* config backend changed to registry in config file */
                        /*
                         * We need to use this extra global variable here to
@@ -4285,10 +4009,12 @@ static bool lp_load_ex(const char *pszFname,
                                  "registry\n"));
                        init_globals(true);
                        lp_kill_all_services();
-                       return lp_load_ex(pszFname, global_only, save_defaults,
-                                         add_ipc, initialize_globals,
-                                         allow_include_registry,
-                                         load_all_shares);
+                       ok = lp_load_ex(pszFname, global_only, save_defaults,
+                                       add_ipc, initialize_globals,
+                                       allow_include_registry,
+                                       load_all_shares);
+                       TALLOC_FREE(frame);
+                       return ok;
                }
        } else if (lp_config_backend_is_registry()) {
                bRetval = process_registry_globals();
@@ -4349,6 +4075,8 @@ static bool lp_load_ex(const char *pszFname,
        if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
                lp_do_parameter(-1, "passdb backend", "samba_dsdb");
 
+               lp_do_parameter(-1, "winbindd:use external pipes", "true");
+
                lp_do_parameter(-1, "rpc_server:default", "external");
                lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
                lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
@@ -4362,6 +4090,7 @@ static bool lp_load_ex(const char *pszFname,
 
        bAllowIncludeRegistry = true;
 
+       TALLOC_FREE(frame);
        return (bRetval);
 }
 
@@ -4476,9 +4205,9 @@ void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
        if (show_defaults)
                defaults_saved = false;
 
-       dump_globals(f);
+       dump_globals(f, defaults_saved);
 
-       dump_a_service(&sDefault, f);
+       lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
 
        for (iService = 0; iService < maxtoprint; iService++) {
                fprintf(f,"\n");
@@ -4495,7 +4224,8 @@ void lp_dump_one(FILE * f, bool show_defaults, int snum)
        if (VALID(snum)) {
                if (ServicePtrs[snum]->szService[0] == '\0')
                        return;
-               dump_a_service(ServicePtrs[snum], f);
+               lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
+                                    flags_list, show_defaults);
        }
 }
 
@@ -4903,3 +4633,12 @@ struct loadparm_global * get_globals(void)
 {
        return &Globals;
 }
+
+unsigned int * get_flags(void)
+{
+       if (flags_list == NULL) {
+               flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
+       }
+
+       return flags_list;
+}