param: remove lp_get_parameter
[obnox/samba/samba-obnox.git] / source3 / param / loadparm.c
index e1f52fdfe5c8a2cc44a8948c68390972798dfe14..dee62246551951617082b965468e2e227b049ab1 100644 (file)
@@ -257,6 +257,7 @@ static struct db_context *ServiceHash;
 static bool bInGlobalSection = true;
 static bool bGlobalOnly = false;
 static struct file_lists *file_lists = NULL;
+static unsigned int *flags_list = NULL;
 
 static void set_allowed_client_auth(void);
 
@@ -305,124 +306,6 @@ bool lp_string_set(char **dest, const char *src) {
        return string_set(Globals.ctx, dest, src);
 }
 
-/***************************************************************************
- Initialise the sDefault parameter structure for the printer values.
-***************************************************************************/
-
-void init_printer_values(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);
-               char *tmp;
-
-               tdbfile = talloc_asprintf(
-                       tmp_ctx, "tdbfile=%s",
-                       lp_parm_const_string(-1, "vlp", "tdbfile",
-                                            "/tmp/vlp.tdb"));
-               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 */
-
-       }
-}
 /**
  *  Function to return the default value for the maximum number of open
  *  file descriptors permitted.  This function tries to consult the
@@ -536,7 +419,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);
@@ -578,7 +461,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 +512,7 @@ static bool apply_lp_set_cmdline(void)
  Initialise the global parameter structure.
 ***************************************************************************/
 
-static void init_globals(bool reinit_globals)
+static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 {
        static bool done_init = false;
        char *s = NULL;
@@ -660,6 +543,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))
@@ -672,7 +560,7 @@ static void init_globals(bool reinit_globals)
        string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
        string_set(Globals.ctx, &sDefault.printjob_username, "%U");
 
-       init_printer_values(Globals.ctx, &sDefault);
+       init_printer_values(lp_ctx, Globals.ctx, &sDefault);
 
        sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
 
@@ -907,6 +795,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;
@@ -1030,6 +919,26 @@ static void init_globals(bool reinit_globals)
        apply_lp_set_cmdline();
 }
 
+/* Convenience routine to setup an lp_context with additional s3 variables */
+static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
+{
+       struct loadparm_context *lp_ctx;
+
+       lp_ctx = loadparm_init_s3(mem_ctx,
+                                 loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
+               DEBUG(0, ("loadparm_init_s3 failed\n"));
+               return NULL;
+       }
+
+       lp_ctx->sDefault = &sDefault;
+       lp_ctx->services = NULL; /* We do not want to access this directly */
+       lp_ctx->bInGlobalSection = bInGlobalSection;
+       lp_ctx->flags = flags_list;
+
+       return lp_ctx;
+}
+
 /*******************************************************************
  Convenience routine to grab string parameters into talloced memory
  and run standard_sub_basic on them. The buffers can be written to by
@@ -1161,7 +1070,6 @@ 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);
@@ -2001,52 +1909,6 @@ struct loadparm_service *lp_default_loadparm_service()
        return &sDefault;
 }
 
-/***************************************************************************
-Check a service for consistency. Return false if the service is in any way
-incomplete or faulty, else true.
-***************************************************************************/
-
-bool service_ok(int iService)
-{
-       bool bRetval;
-
-       bRetval = true;
-       if (ServicePtrs[iService]->szService[0] == '\0') {
-               DEBUG(0, ("The following message indicates an internal error:\n"));
-               DEBUG(0, ("No service name in service entry.\n"));
-               bRetval = false;
-       }
-
-       /* The [printers] entry MUST be printable. I'm all for flexibility, but */
-       /* I can't see why you'd want a non-printable printer service...        */
-       if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
-               if (!ServicePtrs[iService]->printable) {
-                       DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
-                              ServicePtrs[iService]->szService));
-                       ServicePtrs[iService]->printable = true;
-               }
-               /* [printers] service must also be non-browsable. */
-               if (ServicePtrs[iService]->browseable)
-                       ServicePtrs[iService]->browseable = false;
-       }
-
-       if (ServicePtrs[iService]->path[0] == '\0' &&
-           strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
-           ServicePtrs[iService]->msdfs_proxy[0] == '\0'
-           ) {
-               DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
-                       ServicePtrs[iService]->szService));
-               ServicePtrs[iService]->bAvailable = false;
-       }
-
-       /* If a service is flagged unavailable, log the fact at level 1. */
-       if (!ServicePtrs[iService]->bAvailable)
-               DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
-                         ServicePtrs[iService]->szService));
-
-       return (bRetval);
-}
-
 static struct smbconf_ctx *lp_smbconf_ctx(void)
 {
        sbcErr err;
@@ -2073,20 +1935,30 @@ 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;
                }
        }
        if (iServiceIndex >= 0) {
-               return service_ok(iServiceIndex);
+               return lpcfg_service_ok(ServicePtrs[iServiceIndex]);
        }
        return true;
 }
@@ -2144,7 +2016,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;
        }
@@ -2269,8 +2152,6 @@ bool lp_file_list_changed(void)
        DEBUG(6, ("lp_file_list_changed()\n"));
 
        while (f) {
-               time_t mod_time;
-
                if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
                        struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
 
@@ -2284,7 +2165,9 @@ bool lp_file_list_changed(void)
                                return true;
                        }
                } else {
+                       time_t mod_time;
                        char *n2 = NULL;
+
                        n2 = talloc_sub_basic(talloc_tos(),
                                              get_current_username(),
                                              current_user_info.domain,
@@ -2341,7 +2224,8 @@ static void init_iconv(void)
 ***************************************************************************/
 static bool bAllowIncludeRegistry = true;
 
-bool lp_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;
 
@@ -2355,7 +2239,7 @@ bool lp_include(struct loadparm_context *unused, int snum, const char *pszParmVa
                if (!bAllowIncludeRegistry) {
                        return true;
                }
-               if (bInGlobalSection) {
+               if (lp_ctx->bInGlobalSection) {
                        bool ret;
                        include_depth++;
                        ret = process_registry_globals();
@@ -2374,16 +2258,16 @@ bool lp_include(struct loadparm_context *unused, int snum, const char *pszParmVa
 
        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;
@@ -2537,15 +2421,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.
@@ -2553,203 +2428,26 @@ void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
 
 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
 {
-       int parmnum, i;
-       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();
+       struct loadparm_context *lp_ctx;
+       bool ok;
 
-       parmnum = lpcfg_map_parameter(pszParmName);
-
-       if (parmnum < 0) {
-               if (strchr(pszParmName, ':') == NULL) {
-                       DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
-                                 pszParmName));
-                       TALLOC_FREE(frame);
-                       return true;
-               }
-
-               /*
-                * We've got a parametric option
-                */
-
-               if (snum < 0) {
-                       opt_list = &Globals.param_opt;
-                       set_param_opt(NULL, opt_list, pszParmName, pszParmValue, 0);
-               } else {
-                       opt_list = &ServicePtrs[snum]->param_opt;
-                       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) {
+       lp_ctx = setup_lp_context(frame);
+       if (lp_ctx == NULL) {
                TALLOC_FREE(frame);
-               return true;
-       }
-
-       if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
-               DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
-                         pszParmName));
+               return false;
        }
 
-       /* we might point at a service, the default service or a global */
        if (snum < 0) {
-               parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
-       } 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]);
-       }
-
-       if (snum >= 0) {
-               if (!ServicePtrs[snum]->copymap)
-                       init_copymap(ServicePtrs[snum]);
-
-               /* this handles the aliases - set the copymap for other entries with
-                  the same data pointer */
-               for (i = 0; parm_table[i].label; i++) {
-                       if ((parm_table[i].offset == parm_table[parmnum].offset)
-                           && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
-                               bitmap_clear(ServicePtrs[snum]->copymap, i);
-                       }
-               }
-               mem_ctx = ServicePtrs[snum];
+               ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
        } else {
-               mem_ctx = Globals.ctx;
-       }
-
-       /* if it is a special case then go ahead */
-       if (parm_table[parmnum].special) {
-               bool ok;
-               struct loadparm_context *lp_ctx = loadparm_init_s3(frame,
-                                                                  loadparm_s3_helpers());
-               lp_ctx->sDefault = &sDefault;
-               lp_ctx->services = ServicePtrs;
-               ok = parm_table[parmnum].special(lp_ctx, snum, pszParmValue,
-                                                 (char **)parm_ptr);
-               TALLOC_FREE(frame);
-               return ok;
-       }
-
-       /* 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;
-
-               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 ));
-                           TALLOC_FREE(frame);
-                               return false;
-                       }
-                       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:
-               {
-                       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] == '+' &&
-                                   new_list[i][1])
-                               {
-                                       if (!str_list_check(*(const char ***)parm_ptr,
-                                                           &new_list[i][1])) {
-                                               *(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
-                                                                                        &new_list[i][1]);
-                                       }
-                               } else if (*(const char ***)parm_ptr != NULL &&
-                                          new_list[i][0] == '-' &&
-                                          new_list[i][1])
-                               {
-                                       str_list_remove(*(const char ***)parm_ptr,
-                                                       &new_list[i][1]);
-                               } else {
-                                       if (i != 0) {
-                                               DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
-                                                         pszParmName, pszParmValue));
-                                               return false;
-                                       }
-                                       *(const char * const **)parm_ptr = (const char * const *) new_list;
-                                       break;
-                               }
-                       }
-                       break;
-               }
-               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:
-                       if (!lp_set_enum_parm(&parm_table[parmnum], pszParmValue, (int*)parm_ptr)) {
-                               TALLOC_FREE(frame);
-                               return false;
-                       }
-                       break;
-               case P_SEP:
-                       break;
+               ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
+                                               pszParmName, pszParmValue);
        }
 
        TALLOC_FREE(frame);
-       return true;
+
+       return ok;
 }
 
 /***************************************************************************
@@ -2762,11 +2460,11 @@ static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmVa
        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
@@ -2775,11 +2473,11 @@ 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<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;
                }
 
                return true;
@@ -2799,12 +2497,16 @@ bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
 {
        bool ret;
        TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx;
 
-       ret = lp_set_cmdline_helper(pszParmName, pszParmValue);
-       if (ret) {
-               store_lp_set_cmdline(pszParmName, pszParmValue);
+       lp_ctx = setup_lp_context(frame);
+       if (lp_ctx == NULL) {
+               TALLOC_FREE(frame);
+               return false;
        }
 
+       ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
+
        TALLOC_FREE(frame);
        return ret;
 }
@@ -2821,8 +2523,12 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue,
 
        DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
 
-       return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
-                               pszParmName, pszParmValue));
+       if (bInGlobalSection) {
+               return lpcfg_do_global_parameter(userdata, pszParmName, pszParmValue);
+       } else {
+               return lpcfg_do_service_parameter(userdata, ServicePtrs[iServiceIndex],
+                                                 pszParmName, pszParmValue);
+       }
 }
 
 /***************************************************************************
@@ -2868,8 +2574,9 @@ 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)
 {
+       struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
        bool bRetval;
        bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
                         (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
@@ -2881,6 +2588,7 @@ static bool do_section(const char *pszSectionName, void *userdata)
 
        /* if we've just struck a global section, note the fact. */
        bInGlobalSection = isglobal;
+       lp_ctx->bInGlobalSection = isglobal;
 
        /* check for multiple global sections */
        if (bInGlobalSection) {
@@ -2895,7 +2603,7 @@ static bool do_section(const char *pszSectionName, void *userdata)
        bRetval = true;
 
        if (iServiceIndex >= 0)
-               bRetval = service_ok(iServiceIndex);
+               bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
 
        /* if all is still well, move to the next record in the services array */
        if (bRetval) {
@@ -2916,88 +2624,6 @@ static bool do_section(const char *pszSectionName, void *userdata)
        return bRetval;
 }
 
-
-/***************************************************************************
- Determine if a partcular base parameter is currentl set to the default value.
-***************************************************************************/
-
-static bool is_default(int i)
-{
-       switch (parm_table[i].type) {
-               case P_LIST:
-               case P_CMDLIST:
-                       return str_list_equal((const char * const *)parm_table[i].def.lvalue,
-                                             *(const char ***)lp_parm_ptr(NULL, 
-                                                                          &parm_table[i]));
-               case P_STRING:
-               case P_USTRING:
-                       return strequal(parm_table[i].def.svalue,
-                                       *(char **)lp_parm_ptr(NULL, 
-                                                             &parm_table[i]));
-               case P_BOOL:
-               case P_BOOLREV:
-                       return parm_table[i].def.bvalue ==
-                               *(bool *)lp_parm_ptr(NULL, 
-                                                    &parm_table[i]);
-               case P_CHAR:
-                       return parm_table[i].def.cvalue ==
-                               *(char *)lp_parm_ptr(NULL, 
-                                                    &parm_table[i]);
-               case P_INTEGER:
-               case P_OCTAL:
-               case P_ENUM:
-               case P_BYTES:
-                       return parm_table[i].def.ivalue ==
-                               *(int *)lp_parm_ptr(NULL, 
-                                                   &parm_table[i]);
-               case P_SEP:
-                       break;
-       }
-       return false;
-}
-
-/***************************************************************************
-Display the contents of the global structure.
-***************************************************************************/
-
-static void dump_globals(FILE *f)
-{
-       int i;
-       struct parmlist_entry *data;
-
-       fprintf(f, "[global]\n");
-
-       for (i = 0; parm_table[i].label; i++)
-               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))
-                               continue;
-                       fprintf(f, "\t%s = ", parm_table[i].label);
-                       lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
-                                                                         &parm_table[i]),
-                                       f);
-                       fprintf(f, "\n");
-       }
-       if (Globals.param_opt != NULL) {
-               data = Globals.param_opt;
-               while(data) {
-                       fprintf(f, "\t%s = %s\n", data->key, data->value);
-                       data = data->next;
-               }
-        }
-
-}
-
-/***************************************************************************
- Display the contents of a single services record.
-***************************************************************************/
-
-static void dump_a_service(struct loadparm_service *pService, FILE * f, bool show_defaults)
-{
-       return lpcfg_dump_a_service(pService, &sDefault, f, NULL, show_defaults);
-}
-
 /***************************************************************************
  Display the contents of a parameter of a single services record.
 ***************************************************************************/
@@ -3005,10 +2631,9 @@ static void dump_a_service(struct loadparm_service *pService, FILE * f, bool sho
 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
 {
        bool result = false;
-
        struct loadparm_context *lp_ctx;
 
-       lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
+       lp_ctx = setup_lp_context(talloc_tos());
        if (lp_ctx == NULL) {
                return false;
        }
@@ -3022,22 +2647,6 @@ bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
        return result;
 }
 
-/***************************************************************************
- Return info about the requested parameter (given as a string).
- Return NULL when the string is not a valid parameter name.
-***************************************************************************/
-
-struct parm_struct *lp_get_parameter(const char *param_name)
-{
-       int num = lpcfg_map_parameter(param_name);
-
-       if (num < 0) {
-               return NULL;
-       }
-
-       return &parm_table[num];
-}
-
 #if 0
 /***************************************************************************
  Display the contents of a single copy structure.
@@ -3188,7 +2797,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;
@@ -3225,6 +2839,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;
 }
 
@@ -4011,6 +3638,7 @@ static bool lp_load_ex(const char *pszFname,
        char *n2 = NULL;
        bool bRetval;
        TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx;
 
        bRetval = false;
 
@@ -4020,7 +3648,9 @@ static bool lp_load_ex(const char *pszFname,
        bGlobalOnly = global_only;
        bAllowIncludeRegistry = allow_include_registry;
 
-       init_globals(initialize_globals);
+       lp_ctx = setup_lp_context(talloc_tos());
+
+       init_globals(lp_ctx, initialize_globals);
 
        free_file_list();
 
@@ -4049,14 +3679,14 @@ 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, lp_ctx);
                TALLOC_FREE(n2);
 
                /* finish up the last section */
                DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
                if (bRetval) {
                        if (iServiceIndex >= 0) {
-                               bRetval = service_ok(iServiceIndex);
+                               bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
                        }
                }
 
@@ -4069,11 +3699,15 @@ static bool lp_load_ex(const char *pszFname,
                         * for config_backend. Otherwise, init_globals would
                         *  send us into an endless loop here.
                         */
+
                        config_backend = CONFIG_BACKEND_REGISTRY;
                        /* start over */
                        DEBUG(1, ("lp_load_ex: changing to config backend "
                                  "registry\n"));
-                       init_globals(true);
+                       init_globals(lp_ctx, true);
+
+                       TALLOC_FREE(lp_ctx);
+
                        lp_kill_all_services();
                        ok = lp_load_ex(pszFname, global_only, save_defaults,
                                        add_ipc, initialize_globals,
@@ -4267,13 +3901,19 @@ Display the contents of the services array in human-readable form.
 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
 {
        int iService;
+       struct loadparm_context *lp_ctx;
 
        if (show_defaults)
                defaults_saved = false;
 
-       dump_globals(f);
+       lp_ctx = setup_lp_context(talloc_tos());
+       if (lp_ctx == NULL) {
+               return;
+       }
+
+       lpcfg_dump_globals(lp_ctx, f, !defaults_saved);
 
-       dump_a_service(&sDefault, f, show_defaults);
+       lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
 
        for (iService = 0; iService < maxtoprint; iService++) {
                fprintf(f,"\n");
@@ -4290,7 +3930,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, show_defaults);
+               lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
+                                    flags_list, show_defaults);
        }
 }
 
@@ -4698,3 +4339,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;
+}