param: get rid of unnecessary get_default_loadparm_service pointer
[sfrench/samba-autobuild/.git] / lib / param / loadparm.c
index 4cc2da81aae7b91020431f11562aa246f7ac92c4..2b73d40f6c3f35c794599abcf60eea3bd6e7caf5 100644 (file)
 
 #define standard_sub_basic talloc_strdup
 
-static bool do_parameter(const char *, const char *, void *);
-static bool defaults_saved = false;
-
 #include "lib/param/param_global.h"
 
-#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
-
-/* these are parameter handlers which are not needed in the
- * non-source3 code
- */
-#define handle_netbios_aliases NULL
-#define handle_printing NULL
-#define handle_ldap_debug_level NULL
-#define handle_idmap_backend NULL
-#define handle_idmap_uid NULL
-#define handle_idmap_gid NULL
-
-#ifndef N_
-#define N_(x) x
-#endif
-
-#include "lib/param/param_table.c"
-
-/* local variables */
-struct loadparm_context {
-       const char *szConfigFile;
-       struct loadparm_global *globals;
-       struct loadparm_service **services;
-       struct loadparm_service *sDefault;
-       struct smb_iconv_handle *iconv_handle;
-       int iNumServices;
-       struct loadparm_service *currentService;
-       bool bInGlobalSection;
-       struct file_lists *file_lists;
-       unsigned int flags[NUMPARAMETERS];
-       bool loaded;
-       bool refuse_free;
-       bool global; /* Is this the global context, which may set
-                     * global variables such as debug level etc? */
-       const struct loadparm_s3_helpers *s3_fns;
-};
-
-
 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
 {
-       if (lp_ctx->s3_fns) {
-               return lp_ctx->s3_fns->get_default_loadparm_service();
-       }
        return lp_ctx->sDefault;
 }
 
@@ -270,57 +226,83 @@ FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
 /* local prototypes */
 static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
                                        const char *pszServiceName);
-static bool lpcfg_service_ok(struct loadparm_service *service);
 static bool do_section(const char *pszSectionName, void *);
+static bool set_variable_helper(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
+                               const char *pszParmName, const char *pszParmValue);
+static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
+                                      struct loadparm_service *service,
+                                      const char *pszParmName,
+                                      const char *pszParmValue, int flags);
 
-/* This is a helper function for parametrical options support. */
+/* The following are helper functions for parametrical options support. */
 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
 /* Actual parametrical functions are quite simple */
-const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
-                             struct loadparm_service *service,
-                             const char *type, const char *option)
-{
-       char *vfskey_tmp = NULL;
-       char *vfskey = NULL;
-       struct parmlist_entry *data;
-
-       if (lp_ctx == NULL)
+struct parmlist_entry *get_parametric_helper(struct loadparm_service *service,
+                                            const char *type, const char *option,
+                                            struct parmlist_entry *global_opts)
+{
+       char* param_key;
+       struct parmlist_entry *data = NULL;
+       TALLOC_CTX *mem_ctx = talloc_stackframe();
+
+       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;
-
-       if (lp_ctx->s3_fns) {
-               return lp_ctx->s3_fns->get_parametric(service, type, option);
        }
 
-       data = (service == NULL ? lp_ctx->globals->param_opt : service->param_opt);
-
-       vfskey_tmp = talloc_asprintf(NULL, "%s:%s", type, option);
-       if (vfskey_tmp == NULL) return NULL;
-       vfskey = strlower_talloc(NULL, vfskey_tmp);
-       talloc_free(vfskey_tmp);
-
-       while (data) {
-               if (strcmp(data->key, vfskey) == 0) {
-                       talloc_free(vfskey);
-                       return data->value;
+       /*
+        * Try to fetch the option from the data.
+        */
+       if (service != NULL) {
+               data = service->param_opt;
+               while (data != NULL) {
+                       if (strwicmp(data->key, param_key) == 0) {
+                               TALLOC_FREE(mem_ctx);
+                               return data;
+                       }
+                       data = data->next;
                }
-               data = data->next;
        }
 
-       if (service != NULL) {
-               /* Try to fetch the same option but from globals */
-               /* but only if we are not already working with globals */
-               for (data = lp_ctx->globals->param_opt; data;
-                    data = data->next) {
-                       if (strcmp(data->key, vfskey) == 0) {
-                               talloc_free(vfskey);
-                               return data->value;
-                       }
+       /*
+        * Fall back to fetching from the globals.
+        */
+       data = global_opts;
+       while (data != NULL) {
+               if (strwicmp(data->key, param_key) == 0) {
+                       TALLOC_FREE(mem_ctx);
+                       return data;
                }
+               data = data->next;
        }
 
-       talloc_free(vfskey);
+
+       TALLOC_FREE(mem_ctx);
 
        return NULL;
+
+
+}
+
+const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
+                             struct loadparm_service *service,
+                             const char *type, const char *option)
+{
+       struct parmlist_entry *data;
+
+       if (lp_ctx == NULL)
+               return NULL;
+
+       data = get_parametric_helper(service,
+                                    type, option, lp_ctx->globals->param_opt);
+
+       if (data == NULL) {
+               return NULL;
+       } else {
+               return data->value;
+       }
 }
 
 
@@ -541,7 +523,7 @@ bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
  * Set a string value, deallocating any existing space, and allocing the space
  * for the string
  */
-static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
+bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 {
        talloc_free(*dest);
 
@@ -561,7 +543,7 @@ static bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
  * Set a string value, deallocating any existing space, and allocing the space
  * for the string
  */
-static bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
+bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
 {
        talloc_free(*dest);
 
@@ -745,15 +727,13 @@ int lpcfg_map_parameter(const char *pszParmName)
 */
 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
 {
-       int parmnum;
+       int num = lpcfg_map_parameter(name);
 
-       if (lp_ctx->s3_fns) {
-               return lp_ctx->s3_fns->get_parm_struct(name);
+       if (num < 0) {
+               return NULL;
        }
 
-       parmnum = lpcfg_map_parameter(name);
-       if (parmnum == -1) return NULL;
-       return &parm_table[parmnum];
+       return &parm_table[num];
 }
 
 /**
@@ -784,14 +764,6 @@ bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
 {
        int parmnum;
 
-       if (lp_ctx->s3_fns) {
-               struct parm_struct *parm = lp_ctx->s3_fns->get_parm_struct(name);
-               if (parm) {
-                       return parm->flags & FLAG_CMDLINE;
-               }
-               return false;
-       }
-
        parmnum = lpcfg_map_parameter(name);
        if (parmnum == -1) return false;
 
@@ -926,6 +898,7 @@ void copy_service(struct loadparm_service *pserviceDest,
                                                         (char **)dest_ptr,
                                                         *(const char * const *)src_ptr);
                                        break;
+                               case P_CMDLIST:
                                case P_LIST:
                                        TALLOC_FREE(*((char ***)dest_ptr));
                                        *(const char * const **)dest_ptr = (const char * const *)str_list_copy(pserviceDest,
@@ -953,7 +926,7 @@ void copy_service(struct loadparm_service *pserviceDest,
  * Check a service for consistency. Return False if the service is in any way
  * incomplete or faulty, else True.
  */
-static bool lpcfg_service_ok(struct loadparm_service *service)
+bool lpcfg_service_ok(struct loadparm_service *service)
 {
        bool bRetval;
 
@@ -977,6 +950,15 @@ static bool lpcfg_service_ok(struct loadparm_service *service)
                        service->browseable = false;
        }
 
+       if (service->path[0] == '\0' &&
+           strwicmp(service->szService, HOMES_NAME) != 0 &&
+           service->msdfs_proxy[0] == '\0')
+       {
+               DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
+                       service->szService));
+               service->bAvailable = false;
+       }
+
        /* If a service is flagged unavailable, log the fact at level 0. */
        if (!service->bAvailable)
                DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
@@ -1056,8 +1038,10 @@ bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
                        f->modtime = mod_time;
                        talloc_free(f->subfname);
                        f->subfname = talloc_strdup(f, n2);
+                       TALLOC_FREE(n2);
                        return true;
                }
+               TALLOC_FREE(n2);
        }
        return false;
 }
@@ -1086,7 +1070,7 @@ bool lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
  Handle the "realm" parameter
 ***************************************************************************/
 
-bool handle_realm(struct loadparm_context *lp_ctx, int unused,
+bool handle_realm(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                  const char *pszParmValue, char **ptr)
 {
        char *upper;
@@ -1103,15 +1087,9 @@ bool handle_realm(struct loadparm_context *lp_ctx, int unused,
                return false;
        }
 
-       if (lp_ctx->s3_fns != NULL) {
-               lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
-               lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->realm, upper);
-               lp_ctx->s3_fns->lp_string_set(&lp_ctx->globals->dnsdomain, lower);
-       } else {
-               lpcfg_string_set(lp_ctx, ptr, pszParmValue);
-               lpcfg_string_set(lp_ctx, &lp_ctx->globals->realm, upper);
-               lpcfg_string_set(lp_ctx, &lp_ctx->globals->dnsdomain, lower);
-       }
+       lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+       lpcfg_string_set(lp_ctx->globals->ctx, &lp_ctx->globals->realm, upper);
+       lpcfg_string_set(lp_ctx->globals->ctx, &lp_ctx->globals->dnsdomain, lower);
 
        return true;
 }
@@ -1120,13 +1098,13 @@ bool handle_realm(struct loadparm_context *lp_ctx, int unused,
  Handle the include operation.
 ***************************************************************************/
 
-bool handle_include(struct loadparm_context *lp_ctx, int unused,
+bool handle_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                           const char *pszParmValue, char **ptr)
 {
        char *fname;
 
        if (lp_ctx->s3_fns) {
-               return lp_ctx->s3_fns->lp_include(lp_ctx, unused, pszParmValue, ptr);
+               return lp_ctx->s3_fns->lp_include(lp_ctx, service, pszParmValue, ptr);
        }
 
        fname = standard_sub_basic(lp_ctx, pszParmValue);
@@ -1136,7 +1114,7 @@ bool handle_include(struct loadparm_context *lp_ctx, int unused,
        lpcfg_string_set(lp_ctx, ptr, fname);
 
        if (file_exist(fname))
-               return pm_process(fname, do_section, do_parameter, lp_ctx);
+               return pm_process(fname, do_section, lpcfg_do_parameter, lp_ctx);
 
        DEBUG(2, ("Can't find include file %s\n", fname));
 
@@ -1147,37 +1125,31 @@ bool handle_include(struct loadparm_context *lp_ctx, int unused,
  Handle the interpretation of the copy parameter.
 ***************************************************************************/
 
-bool handle_copy(struct loadparm_context *lp_ctx, int snum,
+bool handle_copy(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                        const char *pszParmValue, char **ptr)
 {
        bool bRetval;
        struct loadparm_service *serviceTemp = NULL;
-       struct loadparm_service *current = NULL;
 
        bRetval = false;
 
        DEBUG(3, ("Copying service from service %s\n", pszParmValue));
 
        serviceTemp = lpcfg_getservicebyname(lp_ctx, pszParmValue);
-       if (lp_ctx->s3_fns != NULL) {
-               current = lp_ctx->s3_fns->get_servicebynum(snum);
-       } else {
-               current = lp_ctx->currentService;
-       }
 
-       if (current == NULL) {
-               DEBUG(0, ("Unable to copy service - invalid service destination"));
+       if (service == NULL) {
+               DEBUG(0, ("Unable to copy service - invalid service destination.\n"));
                return false;
        }
 
        if (serviceTemp != NULL) {
-               if (serviceTemp == current) {
+               if (serviceTemp == service) {
                        DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
                } else {
-                       copy_service(current,
+                       copy_service(service,
                                     serviceTemp,
-                                    current->copymap);
-                       lpcfg_string_set(current, ptr, pszParmValue);
+                                    service->copymap);
+                       lpcfg_string_set(service, ptr, pszParmValue);
 
                        bRetval = true;
                }
@@ -1190,28 +1162,23 @@ bool handle_copy(struct loadparm_context *lp_ctx, int snum,
        return bRetval;
 }
 
-bool handle_debug_list(struct loadparm_context *lp_ctx, int unused,
+bool handle_debug_list(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                        const char *pszParmValue, char **ptr)
 {
-       if (lp_ctx->s3_fns != NULL) {
-               lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
-       } else {
-               lpcfg_string_set(lp_ctx, ptr, pszParmValue);
-       }
+       lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
 
        return debug_parse_levels(pszParmValue);
 }
 
-bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
+bool handle_logfile(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                    const char *pszParmValue, char **ptr)
 {
-       if (lp_ctx->s3_fns != NULL) {
-               lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
-       } else {
+       if (lp_ctx->s3_fns == NULL) {
                debug_set_logfile(pszParmValue);
-               lpcfg_string_set(lp_ctx, ptr, pszParmValue);
        }
 
+       lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+
        return true;
 }
 
@@ -1219,25 +1186,23 @@ bool handle_logfile(struct loadparm_context *lp_ctx, int unused,
  * These special charset handling methods only run in the source3 code.
  */
 
-bool handle_charset(struct loadparm_context *lp_ctx, int snum,
+bool handle_charset(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                        const char *pszParmValue, char **ptr)
 {
        if (lp_ctx->s3_fns) {
                if (*ptr == NULL || strcmp(*ptr, pszParmValue) != 0) {
-                       lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
                        global_iconv_handle = smb_iconv_handle_reinit(NULL,
                                                        lpcfg_dos_charset(lp_ctx),
                                                        lpcfg_unix_charset(lp_ctx),
                                                        true, global_iconv_handle);
                }
 
-               return true;
        }
-       return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+       return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
 
 }
 
-bool handle_dos_charset(struct loadparm_context *lp_ctx, int snum,
+bool handle_dos_charset(struct loadparm_context *lp_ctx, struct loadparm_service *service,
                        const char *pszParmValue, char **ptr)
 {
        bool is_utf8 = false;
@@ -1270,16 +1235,138 @@ bool handle_dos_charset(struct loadparm_context *lp_ctx, int snum,
                                        DEFAULT_DOS_CHARSET));
                                pszParmValue = DEFAULT_DOS_CHARSET;
                        }
-                       lp_ctx->s3_fns->lp_string_set(ptr, pszParmValue);
                        global_iconv_handle = smb_iconv_handle_reinit(NULL,
                                                        lpcfg_dos_charset(lp_ctx),
                                                        lpcfg_unix_charset(lp_ctx),
                                                        true, global_iconv_handle);
                }
-               return true;
        }
 
-       return lpcfg_string_set(lp_ctx, ptr, pszParmValue);
+       return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+}
+
+bool handle_printing(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                           const char *pszParmValue, char **ptr)
+{
+       static int parm_num = -1;
+
+       if (parm_num == -1) {
+               parm_num = lpcfg_map_parameter("printing");
+       }
+
+       if (!lp_set_enum_parm(&parm_table[parm_num], pszParmValue, (int*)ptr)) {
+               return false;
+       }
+
+       if (lp_ctx->s3_fns) {
+               if (service == NULL) {
+                       init_printer_values(lp_ctx, lp_ctx->globals->ctx, lp_ctx->sDefault);
+               } else {
+                       init_printer_values(lp_ctx, service, service);
+               }
+       }
+
+       return true;
+}
+
+bool handle_ldap_debug_level(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                            const char *pszParmValue, char **ptr)
+{
+       lp_ctx->globals->ldap_debug_level = lp_int(pszParmValue);
+
+       if (lp_ctx->s3_fns) {
+               lp_ctx->s3_fns->init_ldap_debugging();
+       }
+       return true;
+}
+
+bool handle_netbios_aliases(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                           const char *pszParmValue, char **ptr)
+{
+       TALLOC_FREE(lp_ctx->globals->netbios_aliases);
+       lp_ctx->globals->netbios_aliases = (const char **)str_list_make_v3(lp_ctx->globals->ctx,
+                                                                          pszParmValue, NULL);
+
+       if (lp_ctx->s3_fns) {
+               return lp_ctx->s3_fns->set_netbios_aliases(lp_ctx->globals->netbios_aliases);
+       }
+       return true;
+}
+
+/*
+ * idmap related parameters
+ */
+
+bool handle_idmap_backend(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                         const char *pszParmValue, char **ptr)
+{
+       if (lp_ctx->s3_fns) {
+               lp_do_parameter_parametric(lp_ctx, service, "idmap config * : backend",
+                                          pszParmValue, 0);
+       }
+
+       return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+}
+
+bool handle_idmap_uid(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                     const char *pszParmValue, char **ptr)
+{
+       if (lp_ctx->s3_fns) {
+               lp_do_parameter_parametric(lp_ctx, service, "idmap config * : range",
+                                          pszParmValue, 0);
+       }
+
+       return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+}
+
+bool handle_idmap_gid(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                     const char *pszParmValue, char **ptr)
+{
+       if (lp_ctx->s3_fns) {
+               lp_do_parameter_parametric(lp_ctx, service, "idmap config * : range",
+                                          pszParmValue, 0);
+       }
+
+       return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
+}
+
+bool handle_smb_ports(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+                     const char *pszParmValue, char **ptr)
+{
+       static int parm_num = -1;
+       int i;
+       const char **list;
+
+       if (!pszParmValue || !*pszParmValue) {
+               return false;
+       }
+
+       if (parm_num == -1) {
+               parm_num = lpcfg_map_parameter("smb ports");
+       }
+
+       if(!set_variable_helper(lp_ctx->globals->ctx, parm_num, ptr, "smb ports",
+                               pszParmValue)) {
+               return false;
+       }
+
+       list = lp_ctx->globals->smb_ports;
+       if (list == NULL) {
+               return false;
+       }
+
+       /* Check that each port is a valid integer and within range */
+       for (i = 0; list[i] != NULL; i++) {
+               char *end = NULL;
+               int port = 0;
+               port = strtol(list[i], &end, 10);
+               if (*end != '\0' || port <= 0 || port > 65535) {
+                       TALLOC_FREE(list);
+                       return false;
+               }
+       }
+
+       return true;
 }
 
 /***************************************************************************
@@ -1292,13 +1379,13 @@ void init_copymap(struct loadparm_service *pservice)
 
        TALLOC_FREE(pservice->copymap);
 
-       pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
+       pservice->copymap = bitmap_talloc(NULL, num_parameters());
        if (!pservice->copymap)
                DEBUG(0,
                      ("Couldn't allocate copymap!! (size %d)\n",
-                      (int)NUMPARAMETERS));
+                      (int)num_parameters()));
        else
-               for (i = 0; i < NUMPARAMETERS; i++)
+               for (i = 0; i < num_parameters(); i++)
                        bitmap_set(pservice->copymap, i);
 }
 
@@ -1310,7 +1397,7 @@ static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
                                       const char *pszParmName,
                                       const char *pszParmValue, int flags)
 {
-       struct parmlist_entry *paramo, *data;
+       struct parmlist_entry **data;
        char *name;
        TALLOC_CTX *mem_ctx;
 
@@ -1322,72 +1409,39 @@ static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
        if (!name) return false;
 
        if (service == NULL) {
-               data = lp_ctx->globals->param_opt;
-               mem_ctx = lp_ctx->globals;
+               data = &lp_ctx->globals->param_opt;
+               /**
+                * s3 code cannot deal with parametric options stored on the globals ctx.
+                */
+               if (lp_ctx->s3_fns != NULL) {
+                       mem_ctx = NULL;
+               } else {
+                       mem_ctx = lp_ctx->globals->ctx;
+               }
        } else {
-               data = service->param_opt;
+               data = &service->param_opt;
                mem_ctx = service;
        }
 
-       /* Traverse destination */
-       for (paramo=data; paramo; paramo=paramo->next) {
-               /* If we already have the option set, override it unless
-                  it was a command line option and the new one isn't */
-               if (strcmp(paramo->key, name) == 0) {
-                       if ((paramo->priority & FLAG_CMDLINE) &&
-                           !(flags & FLAG_CMDLINE)) {
-                               talloc_free(name);
-                               return true;
-                       }
-
-                       talloc_free(paramo->value);
-                       paramo->value = talloc_strdup(paramo, pszParmValue);
-                       paramo->priority = flags;
-                       talloc_free(name);
-                       return true;
-               }
-       }
-
-       paramo = talloc_zero(mem_ctx, struct parmlist_entry);
-       if (!paramo)
-               smb_panic("OOM");
-       paramo->key = talloc_strdup(paramo, name);
-       paramo->value = talloc_strdup(paramo, pszParmValue);
-       paramo->priority = flags;
-       if (service == NULL) {
-               DLIST_ADD(lp_ctx->globals->param_opt, paramo);
-       } else {
-               DLIST_ADD(service->param_opt, paramo);
-       }
+       set_param_opt(mem_ctx, data, name, pszParmValue, flags);
 
        talloc_free(name);
 
        return true;
 }
 
-static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
-                        const char *pszParmName, const char *pszParmValue,
-                        struct loadparm_context *lp_ctx, bool on_globals)
+static bool set_variable_helper(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
+                        const char *pszParmName, const char *pszParmValue)
 {
        int i;
-       /* if it is a special case then go ahead */
-       if (parm_table[parmnum].special) {
-               bool ret;
-               ret = parm_table[parmnum].special(lp_ctx, -1, pszParmValue,
-                                                 (char **)parm_ptr);
-               if (!ret) {
-                       return false;
-               }
-               goto mark_non_default;
-       }
 
-       /* now switch on the type of variable it is */
+       /* switch on the type of variable it is */
        switch (parm_table[parmnum].type)
        {
                case P_BOOL: {
                        bool b;
                        if (!set_boolean(pszParmValue, &b)) {
-                               DEBUG(0, ("set_variable(%s): value is not "
+                               DEBUG(0, ("set_variable_helper(%s): value is not "
                                          "boolean!\n", pszParmValue));
                                return false;
                        }
@@ -1398,7 +1452,7 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                case P_BOOLREV: {
                        bool b;
                        if (!set_boolean(pszParmValue, &b)) {
-                               DEBUG(0, ("set_variable(%s): value is not "
+                               DEBUG(0, ("set_variable_helper(%s): value is not "
                                          "boolean!\n", pszParmValue));
                                return false;
                        }
@@ -1407,7 +1461,7 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                        break;
 
                case P_INTEGER:
-                       *(int *)parm_ptr = atoi(pszParmValue);
+                       *(int *)parm_ptr = lp_int(pszParmValue);
                        break;
 
                case P_CHAR:
@@ -1415,7 +1469,11 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                        break;
 
                case P_OCTAL:
-                       *(int *)parm_ptr = strtol(pszParmValue, NULL, 8);
+                       i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
+                       if ( i != 1 ) {
+                               DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
+                               return false;
+                       }
                        break;
 
                case P_BYTES:
@@ -1428,20 +1486,26 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                                }
                        }
 
-                       DEBUG(0, ("set_variable(%s): value is not "
+                       DEBUG(0, ("set_variable_helper(%s): value is not "
                                  "a valid size specifier!\n", pszParmValue));
                        return false;
                }
 
                case P_CMDLIST:
+                       TALLOC_FREE(*(char ***)parm_ptr);
                        *(const char * const **)parm_ptr
-                               = (const char * const *)str_list_make(mem_ctx,
-                                                                     pszParmValue, NULL);
+                               = (const char * const *)str_list_make_v3(mem_ctx,
+                                                                        pszParmValue, NULL);
                        break;
+
                case P_LIST:
                {
-                       char **new_list = str_list_make(mem_ctx,
+                       char **new_list = str_list_make_v3(mem_ctx,
                                                        pszParmValue, NULL);
+                       if (new_list == NULL) {
+                               break;
+                       }
+
                        for (i=0; new_list[i]; i++) {
                                if (*(const char ***)parm_ptr != NULL &&
                                    new_list[i][0] == '+' &&
@@ -1470,6 +1534,7 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                        }
                        break;
                }
+
                case P_STRING:
                        lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
                        break;
@@ -1488,6 +1553,33 @@ static bool set_variable(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
                        break;
        }
 
+       return true;
+
+}
+
+bool set_variable(TALLOC_CTX *mem_ctx, struct loadparm_service *service, int parmnum, void *parm_ptr,
+                        const char *pszParmName, const char *pszParmValue,
+                        struct loadparm_context *lp_ctx, bool on_globals)
+{
+       int i;
+       bool ok;
+
+       /* if it is a special case then go ahead */
+       if (parm_table[parmnum].special) {
+               ok = parm_table[parmnum].special(lp_ctx, service, pszParmValue,
+                                                 (char **)parm_ptr);
+               if (!ok) {
+                       return false;
+               }
+               goto mark_non_default;
+       }
+
+       ok = set_variable_helper(mem_ctx, parmnum, parm_ptr, pszParmName, pszParmValue);
+
+       if (!ok) {
+               return false;
+       }
+
 mark_non_default:
        if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
                lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
@@ -1495,7 +1587,7 @@ mark_non_default:
                for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
                        lp_ctx->flags[i] &= ~FLAG_DEFAULT;
                }
-               for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
+               for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset;i++) {
                        lp_ctx->flags[i] &= ~FLAG_DEFAULT;
                }
        }
@@ -1523,9 +1615,14 @@ bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
                return true;
        }
 
+       if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
+               DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
+                         pszParmName));
+       }
+
        parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
 
-       return set_variable(lp_ctx->globals, parmnum, parm_ptr,
+       return set_variable(lp_ctx->globals->ctx, NULL, parmnum, parm_ptr,
                            pszParmName, pszParmValue, lp_ctx, true);
 }
 
@@ -1551,6 +1648,11 @@ bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
                return true;
        }
 
+       if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
+               DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
+                         pszParmName));
+       }
+
        if (parm_table[parmnum].p_class == P_GLOBAL) {
                DEBUG(0,
                      ("Global parameter %s found in service section!\n",
@@ -1569,7 +1671,7 @@ bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
                    parm_table[i].p_class == parm_table[parmnum].p_class)
                        bitmap_clear(service->copymap, i);
 
-       return set_variable(service, parmnum, parm_ptr, pszParmName,
+       return set_variable(service, service, parmnum, parm_ptr, pszParmName,
                            pszParmValue, lp_ctx, false);
 }
 
@@ -1577,7 +1679,7 @@ bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
  * Process a parameter.
  */
 
-static bool do_parameter(const char *pszParmName, const char *pszParmValue,
+bool lpcfg_do_parameter(const char *pszParmName, const char *pszParmValue,
                         void *userdata)
 {
        struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
@@ -1623,16 +1725,19 @@ bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
 
        while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
 
-       if (lp_ctx->s3_fns) {
-               return lp_ctx->s3_fns->set_cmdline(pszParmName, pszParmValue);
-       }
-
        parmnum = lpcfg_map_parameter(pszParmName);
 
        if (parmnum < 0 && strchr(pszParmName, ':')) {
                /* set a parametric option */
-               return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
-                                                 pszParmValue, FLAG_CMDLINE);
+               bool ok;
+               ok = lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
+                                               pszParmValue, FLAG_CMDLINE);
+               if (lp_ctx->s3_fns != NULL) {
+                       if (ok) {
+                               lp_ctx->s3_fns->store_cmdline(pszParmName, pszParmValue);
+                       }
+               }
+               return ok;
        }
 
        if (parmnum < 0) {
@@ -1657,13 +1762,17 @@ bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
                lp_ctx->flags[i] |= FLAG_CMDLINE;
        }
        for (i=parmnum+1;
-            i<NUMPARAMETERS &&
+            i<num_parameters() &&
             parm_table[i].p_class == parm_table[parmnum].p_class &&
             parm_table[i].offset == parm_table[parmnum].offset;
             i++) {
                lp_ctx->flags[i] |= FLAG_CMDLINE;
        }
 
+       if (lp_ctx->s3_fns != NULL) {
+               lp_ctx->s3_fns->store_cmdline(pszParmName, pszParmValue);
+       }
+
        return true;
 }
 
@@ -1780,7 +1889,7 @@ void lpcfg_print_parameter(struct parm_struct *p, void *ptr, FILE * f)
  * Check if two parameters are equal.
  */
 
- bool lpcfg_equal_parameter(parm_type type, void *ptr1, void *ptr2)
+static bool lpcfg_equal_parameter(parm_type type, void *ptr1, void *ptr2)
 {
        switch (type) {
                case P_BOOL:
@@ -1828,8 +1937,15 @@ static bool do_section(const char *pszSectionName, void *userdata)
 {
        struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
        bool bRetval;
-       bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
+       bool isglobal;
+
+       if (lp_ctx->s3_fns != NULL) {
+               return lp_ctx->s3_fns->do_section(pszSectionName, lp_ctx);
+       }
+
+       isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
                         (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
+
        bRetval = false;
 
        /* if we've just struck a global section, note the fact. */
@@ -1869,14 +1985,14 @@ static bool do_section(const char *pszSectionName, void *userdata)
  * Determine if a particular base parameter is currently set to the default value.
  */
 
-static bool is_default(struct loadparm_service *sDefault, int i)
+static bool is_default(void *base_structure, int i)
 {
-       void *def_ptr = ((char *)sDefault) + parm_table[i].offset;
+       void *def_ptr = ((char *)base_structure) + parm_table[i].offset;
        switch (parm_table[i].type) {
                case P_CMDLIST:
                case P_LIST:
                        return str_list_equal((const char * const *)parm_table[i].def.lvalue,
-                                             (const char **)def_ptr);
+                                             *(const char ***)def_ptr);
                case P_STRING:
                case P_USTRING:
                        return strequal(parm_table[i].def.svalue,
@@ -1902,7 +2018,7 @@ static bool is_default(struct loadparm_service *sDefault, int i)
  *Display the contents of the global structure.
  */
 
-static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
+void lpcfg_dump_globals(struct loadparm_context *lp_ctx, FILE *f,
                         bool show_defaults)
 {
        int i;
@@ -1913,8 +2029,16 @@ static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
        for (i = 0; parm_table[i].label; i++)
                if (parm_table[i].p_class == P_GLOBAL &&
                    (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
-                       if (!show_defaults && (lp_ctx->flags[i] & FLAG_DEFAULT))
-                               continue;
+                       if (!show_defaults) {
+                               if (lp_ctx->flags && (lp_ctx->flags[i] & FLAG_DEFAULT)) {
+                                       continue;
+                               }
+
+                               if (is_default(lp_ctx->globals, i)) {
+                                       continue;
+                               }
+                       }
+
                        fprintf(f, "\t%s = ", parm_table[i].label);
                        lpcfg_print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
                        fprintf(f, "\n");
@@ -1935,8 +2059,8 @@ static void dump_globals(struct loadparm_context *lp_ctx, FILE *f,
  * Display the contents of a single services record.
  */
 
-static void dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
-                          unsigned int *flags)
+void lpcfg_dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
+                         unsigned int *flags, bool show_defaults)
 {
        int i;
        struct parmlist_entry *data;
@@ -1953,7 +2077,7 @@ static void dump_a_service(struct loadparm_service * pService, struct loadparm_s
                                if (flags && (flags[i] & FLAG_DEFAULT)) {
                                        continue;
                                }
-                               if (defaults_saved) {
+                               if (!show_defaults) {
                                        if (is_default(sDefault, i)) {
                                                continue;
                                        }
@@ -1975,6 +2099,9 @@ static void dump_a_service(struct loadparm_service * pService, struct loadparm_s
        }
        if (pService->param_opt != NULL) {
                for (data = pService->param_opt; data; data = data->next) {
+                       if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
+                               continue;
+                       }
                        fprintf(f, "\t%s = %s\n", data->key, data->value);
                }
         }
@@ -1986,7 +2113,33 @@ bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
 {
        struct parm_struct *parm;
        void *ptr;
+       char *local_parm_name;
+       char *parm_opt;
+       const char *parm_opt_value;
+
+       /* check for parametrical option */
+       local_parm_name = talloc_strdup(lp_ctx, parm_name);
+       if (local_parm_name == NULL) {
+               return false;
+       }
 
+       parm_opt = strchr( local_parm_name, ':');
+
+       if (parm_opt) {
+               *parm_opt = '\0';
+               parm_opt++;
+               if (strlen(parm_opt)) {
+                       parm_opt_value = lpcfg_parm_string(lp_ctx, service,
+                               local_parm_name, parm_opt);
+                       if (parm_opt_value) {
+                               fprintf(f, "%s\n", parm_opt_value);
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /* parameter is not parametric, search the table */
        parm = lpcfg_parm_struct(lp_ctx, parm_name);
        if (!parm) {
                return false;
@@ -2012,6 +2165,127 @@ static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
        return;
 }
 
+/***************************************************************************
+ Initialise the sDefault parameter structure for the printer values.
+***************************************************************************/
+
+void init_printer_values(struct loadparm_context *lp_ctx, TALLOC_CTX *ctx,
+                        struct loadparm_service *pService)
+{
+       /* choose defaults depending on the type of printing */
+       switch (pService->printing) {
+               case PRINT_BSD:
+               case PRINT_AIX:
+               case PRINT_LPRNT:
+               case PRINT_LPROS2:
+                       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:
+                       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() */
+                       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:
+                       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
+                       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:
+                       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)
+
+       case PRINT_TEST:
+       case PRINT_VLP: {
+               const char *tdbfile;
+               TALLOC_CTX *tmp_ctx = talloc_new(ctx);
+               const char *tmp;
+
+               tmp = lpcfg_parm_string(lp_ctx, NULL, "vlp", "tdbfile");
+               if (tmp == NULL) {
+                       tmp = "/tmp/vlp.tdb";
+               }
+
+               tdbfile = talloc_asprintf(tmp_ctx, "tdbfile=%s", tmp);
+               if (tdbfile == NULL) {
+                       tdbfile="tdbfile=/tmp/vlp.tdb";
+               }
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->print_command,
+                          tmp ? tmp : "vlp print %p %s");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->lpq_command,
+                          tmp ? tmp : "vlp lpq %p");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->lprm_command,
+                          tmp ? tmp : "vlp lprm %p %j");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->lppause_command,
+                          tmp ? tmp : "vlp lppause %p %j");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->lpresume_command,
+                          tmp ? tmp : "vlp lpresume %p %j");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->queuepause_command,
+                          tmp ? tmp : "vlp queuepause %p");
+
+               tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
+                                     tdbfile);
+               lpcfg_string_set(ctx, &pService->queueresume_command,
+                          tmp ? tmp : "vlp queueresume %p");
+               TALLOC_FREE(tmp_ctx);
+
+               break;
+       }
+#endif /* DEVELOPER */
+
+       }
+}
 
 /**
  * Unload unused services.
@@ -2078,7 +2352,10 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
        talloc_set_destructor(lp_ctx, lpcfg_destructor);
        lp_ctx->bInGlobalSection = true;
        lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
+       /* This appears odd, but globals in s3 isn't a pointer */
+       lp_ctx->globals->ctx = lp_ctx->globals;
        lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
+       lp_ctx->flags = talloc_zero_array(lp_ctx, unsigned int, num_parameters());
 
        lp_ctx->sDefault->iMaxPrintJobs = 1000;
        lp_ctx->sDefault->bAvailable = true;
@@ -2146,7 +2423,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
        lpcfg_do_global_parameter(lp_ctx, "max connections", "0");
 
        lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver");
-       lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns");
+       lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns");
        lpcfg_do_global_parameter(lp_ctx, "kccsrv:samba_kcc", "true");
        /* the winbind method for domain controllers is for both RODC
           auth forwarding and for trusted domains */
@@ -2226,7 +2503,7 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
        lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
                                        "%s/samba_kcc", dyn_SCRIPTSBINDIR);
        lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
-       lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%WORKGROUP%/%ACCOUNTNAME%");
+       lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%D/%U");
 
        lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
        lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
@@ -2334,6 +2611,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 
        lpcfg_do_global_parameter(lp_ctx, "winbind reconnect delay", "30");
 
+       lpcfg_do_global_parameter(lp_ctx, "winbind request timeout", "60");
+
        lpcfg_do_global_parameter(lp_ctx, "nt acl support", "yes");
 
        lpcfg_do_global_parameter(lp_ctx, "acl check permissions", "yes");
@@ -2468,6 +2747,13 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
                }
        }
 
+       for (parm=lp_ctx->sDefault->param_opt; parm; parm=parm->next) {
+               if (!(parm->priority & FLAG_CMDLINE)) {
+                       parm->priority |= FLAG_DEFAULT;
+               }
+       }
+
+
        return lp_ctx;
 }
 
@@ -2502,6 +2788,8 @@ struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx,
        }
        loadparm_context->s3_fns = s3_fns;
        loadparm_context->globals = s3_fns->globals;
+       loadparm_context->flags = s3_fns->flags;
+
        return loadparm_context;
 }
 
@@ -2613,7 +2901,7 @@ bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
 
        /* We get sections first, so have to start 'behind' to make up */
        lp_ctx->currentService = NULL;
-       bRetval = pm_process(n2, do_section, do_parameter, lp_ctx);
+       bRetval = pm_process(n2, do_section, lpcfg_do_parameter, lp_ctx);
 
        /* finish up the last section */
        DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
@@ -2668,11 +2956,9 @@ void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
                return;
        }
 
-       defaults_saved = !show_defaults;
-
-       dump_globals(lp_ctx, f, show_defaults);
+       lpcfg_dump_globals(lp_ctx, f, show_defaults);
 
-       dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags);
+       lpcfg_dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags, show_defaults);
 
        for (iService = 0; iService < maxtoprint; iService++)
                lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault);
@@ -2686,7 +2972,7 @@ void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *servic
        if (service != NULL) {
                if (service->szService[0] == '\0')
                        return;
-               dump_a_service(service, sDefault, f, NULL);
+               lpcfg_dump_a_service(service, sDefault, f, NULL, show_defaults);
        }
 }