param: Use an explicit talloc_stackframe() in lp_do_parameter for clarity and certainty.
[mat/samba.git] / source3 / param / loadparm.c
index c464861fffe1f766d33434da6848a1feef78826b..9c3119fb50038735e00c65daaabf3412b14c50c2 100644 (file)
 #include <cups/http.h>
 #endif
 
-#ifdef CLUSTER_SUPPORT
-#include "ctdb_private.h"
-#endif
-
 bool bLoaded = false;
 
 extern userdom_struct current_user_info;
@@ -108,29 +104,7 @@ static int config_backend = CONFIG_BACKEND_FILE;
 
 static bool defaults_saved = false;
 
-#define LOADPARM_EXTRA_GLOBALS \
-       struct parmlist_entry *param_opt;                               \
-       char *realm_original;                                           \
-       int iminreceivefile;                                            \
-       char *szPrintcapname;                                           \
-       int CupsEncrypt;                                                \
-       int  iPreferredMaster;                                          \
-       char *szLdapMachineSuffix;                                      \
-       char *szLdapUserSuffix;                                         \
-       char *szLdapIdmapSuffix;                                        \
-       char *szLdapGroupSuffix;                                        \
-       char *szIdmapUID;                                               \
-       char *szIdmapGID;                                               \
-       char *szIdmapBackend;                                           \
-       int winbindMaxDomainConnections;                                \
-       int ismb2_max_credits;                                          \
-       char *tls_keyfile;                                              \
-       char *tls_certfile;                                             \
-       char *tls_cafile;                                               \
-       char *tls_crlfile;                                              \
-       char *tls_dhpfile;
-
-#include "param/param_global.h"
+#include "lib/param/param_global.h"
 
 static struct loadparm_global Globals;
 
@@ -282,65 +256,16 @@ static int iServiceIndex = 0;
 static struct db_context *ServiceHash;
 static bool bInGlobalSection = true;
 static bool bGlobalOnly = false;
-
-#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
-
-/* prototypes for the special type handlers */
-static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
-static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
-
-/* these are parameter handlers which are not needed in the
- * source3 code
- */
-
-#define handle_logfile NULL
+static struct file_lists *file_lists = NULL;
 
 static void set_allowed_client_auth(void);
 
-static void add_to_file_list(const char *fname, const char *subfname);
-static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
 static void free_param_opts(struct parmlist_entry **popts);
 
-#include "lib/param/param_table.c"
-
 /* this is used to prevent lots of mallocs of size 1 */
 static const char null_string[] = "";
 
-/**
- Set a string value, allocing the space for the string
-**/
-
-static bool string_init(char **dest,const char *src)
-{
-       size_t l;
-
-       if (!src)
-               src = "";
-
-       l = strlen(src);
-
-       if (l == 0) {
-               *dest = discard_const_p(char, null_string);
-       } else {
-               (*dest) = SMB_STRDUP(src);
-               if ((*dest) == NULL) {
-                       DEBUG(0,("Out of memory in string_init\n"));
-                       return false;
-               }
-       }
-       return(true);
-}
-
 /**
  Free a string value.
 **/
@@ -351,7 +276,7 @@ static void string_free(char **s)
                return;
        if (*s == null_string)
                *s = NULL;
-       SAFE_FREE(*s);
+       TALLOC_FREE(*s);
 }
 
 /**
@@ -359,17 +284,32 @@ static void string_free(char **s)
  for the string
 **/
 
-static bool string_set(char **dest,const char *src)
+static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
 {
        string_free(dest);
-       return(string_init(dest,src));
+
+       if (!src) {
+               src = "";
+       }
+
+       (*dest) = talloc_strdup(mem_ctx, src);
+       if ((*dest) == NULL) {
+               DEBUG(0,("Out of memory in string_init\n"));
+               return false;
+       }
+
+       return true;
+}
+
+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.
 ***************************************************************************/
 
-static void init_printer_values(struct loadparm_service *pService)
+void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
 {
        /* choose defaults depending on the type of printing */
        switch (pService->printing) {
@@ -377,52 +317,52 @@ static void init_printer_values(struct loadparm_service *pService)
                case PRINT_AIX:
                case PRINT_LPRNT:
                case PRINT_LPROS2:
-                       string_set(&pService->lpq_command, "lpq -P'%p'");
-                       string_set(&pService->lprm_command, "lprm -P'%p' %j");
-                       string_set(&pService->print_command, "lpr -r -P'%p' %s");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
                        break;
 
                case PRINT_LPRNG:
                case PRINT_PLP:
-                       string_set(&pService->lpq_command, "lpq -P'%p'");
-                       string_set(&pService->lprm_command, "lprm -P'%p' %j");
-                       string_set(&pService->print_command, "lpr -r -P'%p' %s");
-                       string_set(&pService->queuepause_command, "lpc stop '%p'");
-                       string_set(&pService->queueresume_command, "lpc start '%p'");
-                       string_set(&pService->lppause_command, "lpc hold '%p' %j");
-                       string_set(&pService->lpresume_command, "lpc release '%p' %j");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
                        break;
 
                case PRINT_CUPS:
                case PRINT_IPRINT:
                        /* set the lpq command to contain the destination printer
                           name only.  This is used by cups_queue_get() */
-                       string_set(&pService->lpq_command, "%p");
-                       string_set(&pService->lprm_command, "");
-                       string_set(&pService->print_command, "");
-                       string_set(&pService->lppause_command, "");
-                       string_set(&pService->lpresume_command, "");
-                       string_set(&pService->queuepause_command, "");
-                       string_set(&pService->queueresume_command, "");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "");
+                       lpcfg_string_set(ctx, &pService->print_command, "");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "");
                        break;
 
                case PRINT_SYSV:
                case PRINT_HPUX:
-                       string_set(&pService->lpq_command, "lpstat -o%p");
-                       string_set(&pService->lprm_command, "cancel %p-%j");
-                       string_set(&pService->print_command, "lp -c -d%p %s; rm %s");
-                       string_set(&pService->queuepause_command, "disable %p");
-                       string_set(&pService->queueresume_command, "enable %p");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpstat -o%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "cancel %p-%j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
+                       lpcfg_string_set(ctx, &pService->queuepause_command, "disable %p");
+                       lpcfg_string_set(ctx, &pService->queueresume_command, "enable %p");
 #ifndef HPUX
-                       string_set(&pService->lppause_command, "lp -i %p-%j -H hold");
-                       string_set(&pService->lpresume_command, "lp -i %p-%j -H resume");
+                       lpcfg_string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
+                       lpcfg_string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
 #endif /* HPUX */
                        break;
 
                case PRINT_QNX:
-                       string_set(&pService->lpq_command, "lpq -P%p");
-                       string_set(&pService->lprm_command, "lprm -P%p %j");
-                       string_set(&pService->print_command, "lp -r -P%p %s");
+                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P%p");
+                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
+                       lpcfg_string_set(ctx, &pService->print_command, "lp -r -P%p %s");
                        break;
 
 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
@@ -430,7 +370,7 @@ static void init_printer_values(struct loadparm_service *pService)
        case PRINT_TEST:
        case PRINT_VLP: {
                const char *tdbfile;
-               TALLOC_CTX *tmp_ctx = talloc_stackframe();
+               TALLOC_CTX *tmp_ctx = talloc_new(ctx);
                char *tmp;
 
                tdbfile = talloc_asprintf(
@@ -443,37 +383,37 @@ static void init_printer_values(struct loadparm_service *pService)
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
                                      tdbfile);
-               string_set(&pService->print_command,
+               lpcfg_string_set(ctx, &pService->print_command,
                           tmp ? tmp : "vlp print %p %s");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
                                      tdbfile);
-               string_set(&pService->lpq_command,
+               lpcfg_string_set(ctx, &pService->lpq_command,
                           tmp ? tmp : "vlp lpq %p");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
                                      tdbfile);
-               string_set(&pService->lprm_command,
+               lpcfg_string_set(ctx, &pService->lprm_command,
                           tmp ? tmp : "vlp lprm %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
                                      tdbfile);
-               string_set(&pService->lppause_command,
+               lpcfg_string_set(ctx, &pService->lppause_command,
                           tmp ? tmp : "vlp lppause %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
                                      tdbfile);
-               string_set(&pService->lpresume_command,
+               lpcfg_string_set(ctx, &pService->lpresume_command,
                           tmp ? tmp : "vlp lpresume %p %j");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
                                      tdbfile);
-               string_set(&pService->queuepause_command,
+               lpcfg_string_set(ctx, &pService->queuepause_command,
                           tmp ? tmp : "vlp queuepause %p");
 
                tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
                                      tdbfile);
-               string_set(&pService->queueresume_command,
+               lpcfg_string_set(ctx, &pService->queueresume_command,
                           tmp ? tmp : "vlp queueresume %p");
                TALLOC_FREE(tmp_ctx);
 
@@ -676,7 +616,7 @@ static bool apply_lp_set_cmdline(void)
 {
        struct lp_stored_option *entry = NULL;
        for (entry = stored_options; entry != NULL; entry = entry->next) {
-               if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
+               if (!lp_set_cmdline_helper(entry->label, entry->value)) {
                        DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
                                  entry->label, entry->value));
                        return false;
@@ -718,81 +658,82 @@ static void init_globals(bool reinit_globals)
         * table once the defaults are set */
        ZERO_STRUCT(Globals);
 
-       Globals.ctx = talloc_new(NULL);
+       Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
 
        for (i = 0; parm_table[i].label; i++) {
                if ((parm_table[i].type == P_STRING ||
                     parm_table[i].type == P_USTRING))
                {
-                       string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
+                       string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
                }
        }
 
 
-       string_set(&sDefault.fstype, FSTYPE_STRING);
-       string_set(&sDefault.printjob_username, "%U");
+       string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
+       string_set(Globals.ctx, &sDefault.printjob_username, "%U");
 
-       init_printer_values(&sDefault);
+       init_printer_values(Globals.ctx, &sDefault);
 
        sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
 
        DEBUG(3, ("Initialising global parameters\n"));
 
        /* Must manually force to upper case here, as this does not go via the handler */
-       string_set(&Globals.netbios_name, myhostname_upper());
+       string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
 
-       string_set(&Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
-       string_set(&Globals.private_dir, get_dyn_PRIVATE_DIR());
+       string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
+       string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
 
        /* use the new 'hash2' method by default, with a prefix of 1 */
-       string_set(&Globals.mangling_method, "hash2");
+       string_set(Globals.ctx, &Globals.mangling_method, "hash2");
        Globals.mangle_prefix = 1;
 
-       string_set(&Globals.guest_account, GUEST_ACCOUNT);
+       string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
 
        /* using UTF8 by default allows us to support all chars */
-       string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
+       string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
 
        /* Use codepage 850 as a default for the dos character set */
-       string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
+       string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
 
        /*
         * Allow the default PASSWD_CHAT to be overridden in local.h.
         */
-       string_set(&Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
+       string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
 
-       string_set(&Globals.workgroup, DEFAULT_WORKGROUP);
+       string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
 
-       string_set(&Globals.passwd_program, "");
-       string_set(&Globals.lock_directory, get_dyn_LOCKDIR());
-       string_set(&Globals.state_directory, get_dyn_STATEDIR());
-       string_set(&Globals.cache_directory, get_dyn_CACHEDIR());
-       string_set(&Globals.pid_directory, get_dyn_PIDDIR());
-       string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
+       string_set(Globals.ctx, &Globals.passwd_program, "");
+       string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
+       string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
+       string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
+       string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
+       string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
        /*
         * By default support explicit binding to broadcast
         * addresses.
         */
        Globals.nmbd_bind_explicit_broadcast = true;
 
-       if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
+       s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
+       if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       string_set(&Globals.server_string, s);
-       SAFE_FREE(s);
+       string_set(Globals.ctx, &Globals.server_string, s);
+       TALLOC_FREE(s);
 #ifdef DEVELOPER
-       string_set(&Globals.panic_action, "/bin/sleep 999999999");
+       string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
 #endif
 
-       string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
+       string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
 
-       string_set(&Globals.logon_drive, "");
+       string_set(Globals.ctx, &Globals.logon_drive, "");
        /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
-       string_set(&Globals.logon_home, "\\\\%N\\%U");
-       string_set(&Globals.logon_path, "\\\\%N\\%U\\profile");
+       string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
+       string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
 
        Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
-       string_set(&Globals.password_server, "*");
+       string_set(Globals.ctx, &Globals.password_server, "*");
 
        Globals.algorithmic_rid_base = BASE_RID;
 
@@ -828,11 +769,12 @@ static void init_globals(bool reinit_globals)
        Globals.read_raw = true;
        Globals.write_raw = true;
        Globals.null_passwords = false;
+       Globals.old_password_allowed_period = 60;
        Globals.obey_pam_restrictions = false;
        Globals.syslog = 1;
        Globals.syslog_only = false;
        Globals.timestamp_logs = true;
-       string_set(&Globals.log_level, "0");
+       string_set(Globals.ctx, &Globals.log_level, "0");
        Globals.debug_prefix_timestamp = false;
        Globals.debug_hires_timestamp = true;
        Globals.debug_pid = false;
@@ -848,9 +790,9 @@ static void init_globals(bool reinit_globals)
 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
        Globals.nis_homedir = false;
 #ifdef WITH_NISPLUS_HOME
-       string_set(&Globals.homedir_map, "auto_home.org_dir");
+       string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
 #else
-       string_set(&Globals.homedir_map, "auto.home");
+       string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
 #endif
 #endif
        Globals.time_server = false;
@@ -891,14 +833,14 @@ static void init_globals(bool reinit_globals)
           a large number of sites (tridge) */
        Globals.hostname_lookups = false;
 
-       string_set(&Globals.passdb_backend, "tdbsam");
-       string_set(&Globals.ldap_suffix, "");
-       string_set(&Globals.szLdapMachineSuffix, "");
-       string_set(&Globals.szLdapUserSuffix, "");
-       string_set(&Globals.szLdapGroupSuffix, "");
-       string_set(&Globals.szLdapIdmapSuffix, "");
+       string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
+       string_set(Globals.ctx, &Globals.ldap_suffix, "");
+       string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
+       string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
+       string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
+       string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
 
-       string_set(&Globals.ldap_admin_dn, "");
+       string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
        Globals.ldap_ssl = LDAP_SSL_START_TLS;
        Globals.ldap_ssl_ads = false;
        Globals.ldap_deref = -1;
@@ -946,21 +888,17 @@ static void init_globals(bool reinit_globals)
        Globals.wins_dns_proxy = true;
 
        Globals.allow_trusted_domains = true;
-       string_set(&Globals.szIdmapBackend, "tdb");
+       string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
 
-       string_set(&Globals.template_shell, "/bin/false");
-       string_set(&Globals.template_homedir, "/home/%D/%U");
-       string_set(&Globals.winbind_separator, "\\");
-       string_set(&Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
+       string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
+       string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
+       string_set(Globals.ctx, &Globals.winbind_separator, "\\");
+       string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
 
-       string_set(&Globals.cups_server, "");
-       string_set(&Globals.iprint_server, "");
+       string_set(Globals.ctx, &Globals.cups_server, "");
+       string_set(Globals.ctx, &Globals.iprint_server, "");
 
-#ifdef CLUSTER_SUPPORT
-       string_set(&Globals.ctdbd_socket, CTDB_PATH);
-#else
-       string_set(&Globals.ctdbd_socket, "");
-#endif
+       string_set(Globals.ctx, &Globals._ctdbd_socket, "");
 
        Globals.cluster_addresses = NULL;
        Globals.clustering = false;
@@ -1001,12 +939,13 @@ static void init_globals(bool reinit_globals)
        Globals.enable_asu_support       = false;
 
        /* User defined shares. */
-       if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
+       s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
+       if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       string_set(&Globals.usershare_path, s);
-       SAFE_FREE(s);
-       string_set(&Globals.usershare_template_share, "");
+       string_set(Globals.ctx, &Globals.usershare_path, s);
+       TALLOC_FREE(s);
+       string_set(Globals.ctx, &Globals.usershare_template_share, "");
        Globals.usershare_max_shares = 0;
        /* By default disallow sharing of directories not owned by the sharer. */
        Globals.usershare_owner_only = true;
@@ -1028,7 +967,7 @@ static void init_globals(bool reinit_globals)
        Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
        Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
 
-       string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
+       string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
 
        Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbind ntp_signd kcc dnsupdate dns", NULL);
 
@@ -1036,37 +975,40 @@ static void init_globals(bool reinit_globals)
 
        Globals.tls_enabled = true;
 
-       string_set(&Globals.tls_keyfile, "tls/key.pem");
-       string_set(&Globals.tls_certfile, "tls/cert.pem");
-       string_set(&Globals.tls_cafile, "tls/ca.pem");
+       string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
+       string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
+       string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
 
-       string_set(&Globals.share_backend, "classic");
+       string_set(Globals.ctx, &Globals.share_backend, "classic");
 
        Globals.iPreferredMaster = Auto;
 
        Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
 
-       string_set(&Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
+       string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
 
-       string_set(&Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
+       string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
 
-       if (asprintf(&s, "%s/samba_kcc", get_dyn_SCRIPTSBINDIR()) < 0) {
+       s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
+       if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
        Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
-       SAFE_FREE(s);
+       TALLOC_FREE(s);
 
-       if (asprintf(&s, "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
+       s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
+       if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
        Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
-       SAFE_FREE(s);
+       TALLOC_FREE(s);
 
-       if (asprintf(&s, "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR()) < 0) {
+       s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
+       if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
        Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
-       SAFE_FREE(s);
+       TALLOC_FREE(s);
 
        Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
 
@@ -1094,7 +1036,7 @@ static void init_globals(bool reinit_globals)
  callers without affecting the source string.
 ********************************************************************/
 
-static char *lp_string(TALLOC_CTX *ctx, const char *s)
+char *lp_string(TALLOC_CTX *ctx, const char *s)
 {
        char *ret;
 
@@ -1211,76 +1153,19 @@ FN_LOCAL_CONST_STRING(const_servicename, szService)
 
 /* These functions cannot be auto-generated */
 FN_LOCAL_BOOL(autoloaded, autoloaded)
-FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
 
 /* local prototypes */
 
 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
 static const char *get_boolean(bool bool_value);
-static int getservicebyname(const char *pszServiceName,
-                           struct loadparm_service *pserviceDest);
-static void copy_service(struct loadparm_service *pserviceDest,
-                        struct loadparm_service *pserviceSource,
-                        struct bitmap *pcopymapDest);
 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
                         void *userdata);
 static bool do_section(const char *pszSectionName, void *userdata);
-static void init_copymap(struct loadparm_service *pservice);
 static bool hash_a_service(const char *name, int number);
 static void free_service_byindex(int iService);
 static void show_parameter(int parmIndex);
 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
 
-/*
- * This is a helper function for parametrical options support.  It returns a
- * pointer to parametrical option value if it exists or NULL otherwise. Actual
- * parametrical functions are quite simple
- */
-static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
-                                                          const char *option)
-{
-       bool global_section = false;
-       char* param_key;
-        struct parmlist_entry *data;
-
-       if (service == NULL) {
-               data = Globals.param_opt;
-               global_section = true;
-       } else {
-               data = service->param_opt;
-       }
-
-       if (asprintf(&param_key, "%s:%s", type, option) == -1) {
-               DEBUG(0,("asprintf failed!\n"));
-               return NULL;
-       }
-
-       while (data) {
-               if (strwicmp(data->key, param_key) == 0) {
-                       string_free(&param_key);
-                       return data;
-               }
-               data = data->next;
-       }
-
-       if (!global_section) {
-               /* Try to fetch the same option but from globals */
-               /* but only if we are not already working with Globals */
-               data = Globals.param_opt;
-               while (data) {
-                       if (strwicmp(data->key, param_key) == 0) {
-                               string_free(&param_key);
-                               return data;
-                       }
-                       data = data->next;
-               }
-       }
-
-       string_free(&param_key);
-
-       return NULL;
-}
-
 /*
  * This is a helper function for parametrical options support.  It returns a
  * pointer to parametrical option value if it exists or NULL otherwise. Actual
@@ -1292,9 +1177,10 @@ static struct parmlist_entry *get_parametrics(int snum, const char *type,
        if (snum >= iNumServices) return NULL;
 
        if (snum < 0) {
-               return get_parametrics_by_service(NULL, type, option);
+               return get_parametric_helper(NULL, type, option, Globals.param_opt);
        } else {
-               return get_parametrics_by_service(ServicePtrs[snum], type, option);
+               return get_parametric_helper(ServicePtrs[snum],
+                                            type, option, Globals.param_opt);
        }
 }
 
@@ -1302,54 +1188,6 @@ static struct parmlist_entry *get_parametrics(int snum, const char *type,
 #define MISSING_PARAMETER(name) \
     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
 
-/*******************************************************************
-convenience routine to return int parameters.
-********************************************************************/
-static int lp_int(const char *s)
-{
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_int);
-               return (-1);
-       }
-
-       return (int)strtol(s, NULL, 0);
-}
-
-/*******************************************************************
-convenience routine to return unsigned long parameters.
-********************************************************************/
-static unsigned long lp_ulong(const char *s)
-{
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_ulong);
-               return (0);
-       }
-
-       return strtoul(s, NULL, 0);
-}
-
-/*******************************************************************
-convenience routine to return boolean parameters.
-********************************************************************/
-static bool lp_bool(const char *s)
-{
-       bool ret = false;
-
-       if (!s || !*s) {
-               MISSING_PARAMETER(lp_bool);
-               return false;
-       }
-
-       if (!set_boolean(s, &ret)) {
-               DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
-               return false;
-       }
-
-       return ret;
-}
-
 /*******************************************************************
 convenience routine to return enum parameters.
 ********************************************************************/
@@ -1402,16 +1240,6 @@ const char *lp_parm_const_string(int snum, const char *type, const char *option,
        return data->value;
 }
 
-const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
-{
-       struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
-
-       if (data == NULL||data->value==NULL)
-               return NULL;
-
-       return data->value;
-}
-
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
@@ -1483,18 +1311,6 @@ int lp_parm_enum(int snum, const char *type, const char *option,
        return def;
 }
 
-
-/***************************************************************************
- Initialise a service to the defaults.
-***************************************************************************/
-
-static void init_service(struct loadparm_service *pservice)
-{
-       memset((char *)pservice, '\0', sizeof(struct loadparm_service));
-       copy_service(pservice, &sDefault, NULL);
-}
-
-
 /**
  * free a param_opts structure.
  * param_opts handling should be moved to talloc;
@@ -1514,7 +1330,7 @@ static void free_param_opts(struct parmlist_entry **popts)
                string_free(&opt->value);
                TALLOC_FREE(opt->list);
                next_opt = opt->next;
-               SAFE_FREE(opt);
+               TALLOC_FREE(opt);
                opt = next_opt;
        }
        *popts = NULL;
@@ -1579,12 +1395,9 @@ static void free_service_byindex(int idx)
 static int add_a_service(const struct loadparm_service *pservice, const char *name)
 {
        int i;
-       struct loadparm_service tservice;
        int num_to_alloc = iNumServices + 1;
        struct loadparm_service **tsp = NULL;
 
-       tservice = *pservice;
-
        /* it might already exist */
        if (name) {
                i = getservicebyname(name, NULL);
@@ -1595,13 +1408,13 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
 
        /* if not, then create one */
        i = iNumServices;
-       tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
+       tsp = talloc_realloc(NULL, ServicePtrs, struct loadparm_service *, num_to_alloc);
        if (tsp == NULL) {
                DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
                return (-1);
        }
        ServicePtrs = tsp;
-       ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
+       ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
        if (!ServicePtrs[iNumServices]) {
                DEBUG(0,("add_a_service: out of memory!\n"));
                return (-1);
@@ -1610,10 +1423,9 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
 
        ServicePtrs[i]->valid = true;
 
-       init_service(ServicePtrs[i]);
-       copy_service(ServicePtrs[i], &tservice, NULL);
+       copy_service(ServicePtrs[i], pservice, NULL);
        if (name)
-               string_set(&ServicePtrs[i]->szService, name);
+               string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
 
        DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
                i, ServicePtrs[i]->szService));
@@ -1702,16 +1514,16 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
        if (!(*(ServicePtrs[iDefaultService]->path))
            || strequal(ServicePtrs[iDefaultService]->path,
                        lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
-               string_set(&ServicePtrs[i]->path, pszHomedir);
+               string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
        }
 
        if (!(*(ServicePtrs[i]->comment))) {
-               char *comment = NULL;
-               if (asprintf(&comment, "Home directory of %s", user) < 0) {
+               char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
+               if (comment == NULL) {
                        return false;
                }
-               string_set(&ServicePtrs[i]->comment, comment);
-               SAFE_FREE(comment);
+               string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+               TALLOC_FREE(comment);
        }
 
        /* set the browseable flag from the global default */
@@ -1752,15 +1564,16 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
        if (i < 0)
                return false;
 
-       if (asprintf(&comment, "IPC Service (%s)",
-                               Globals.server_string) < 0) {
+       comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
+                                 Globals.server_string);
+       if (comment == NULL) {
                return false;
        }
 
-       string_set(&ServicePtrs[i]->path, tmpdir());
-       string_set(&ServicePtrs[i]->username, "");
-       string_set(&ServicePtrs[i]->comment, comment);
-       string_set(&ServicePtrs[i]->fstype, "IPC");
+       string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
+       string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
+       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+       string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
        ServicePtrs[i]->max_connections = 0;
        ServicePtrs[i]->bAvailable = true;
        ServicePtrs[i]->read_only = true;
@@ -1772,7 +1585,7 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
 
        DEBUG(3, ("adding IPC service\n"));
 
-       SAFE_FREE(comment);
+       TALLOC_FREE(comment);
        return true;
 }
 
@@ -1794,8 +1607,8 @@ bool lp_add_printer(const char *pszPrintername, int iDefaultService)
        /* entry (if/when the 'available' keyword is implemented!).    */
 
        /* the printer name is set to the service name. */
-       string_set(&ServicePtrs[i]->_printername, pszPrintername);
-       string_set(&ServicePtrs[i]->comment, comment);
+       string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
+       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
 
        /* set the browseable flag from the gloabl default */
        ServicePtrs[i]->browseable = sDefault.browseable;
@@ -2079,15 +1892,6 @@ void show_parameter_list(void)
        }
 }
 
-/***************************************************************************
- Check if a given string correctly represents a boolean value.
-***************************************************************************/
-
-bool lp_string_is_valid_boolean(const char *parm_value)
-{
-       return set_boolean(parm_value, NULL);
-}
-
 /***************************************************************************
  Get the standard string representation of a boolean value ("yes" or "no")
 ***************************************************************************/
@@ -2140,7 +1944,7 @@ bool lp_canonicalize_boolean(const char *str, const char**canon_str)
 Find a service by name. Otherwise works like get_service.
 ***************************************************************************/
 
-static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
+int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
 {
        int iService = -1;
        char *canon_name;
@@ -2196,124 +2000,6 @@ struct loadparm_service *lp_default_loadparm_service()
        return &sDefault;
 }
 
-
-/***************************************************************************
- Copy a service structure to another.
- If pcopymapDest is NULL then copy all fields
-***************************************************************************/
-
-/**
- * Add a parametric option to a parmlist_entry,
- * replacing old value, if already present.
- */
-static void set_param_opt(struct parmlist_entry **opt_list,
-                         const char *opt_name,
-                         const char *opt_value,
-                         unsigned priority)
-{
-       struct parmlist_entry *new_opt, *opt;
-       bool not_added;
-
-       opt = *opt_list;
-       not_added = true;
-
-       /* Traverse destination */
-       while (opt) {
-               /* If we already have same option, override it */
-               if (strwicmp(opt->key, opt_name) == 0) {
-                       if ((opt->priority & FLAG_CMDLINE) &&
-                           !(priority & FLAG_CMDLINE)) {
-                               /* it's been marked as not to be
-                                  overridden */
-                               return;
-                       }
-                       string_free(&opt->value);
-                       TALLOC_FREE(opt->list);
-                       opt->value = SMB_STRDUP(opt_value);
-                       opt->priority = priority;
-                       not_added = false;
-                       break;
-               }
-               opt = opt->next;
-       }
-       if (not_added) {
-           new_opt = SMB_XMALLOC_P(struct parmlist_entry);
-           new_opt->key = SMB_STRDUP(opt_name);
-           new_opt->value = SMB_STRDUP(opt_value);
-           new_opt->list = NULL;
-           new_opt->priority = priority;
-           DLIST_ADD(*opt_list, new_opt);
-       }
-}
-
-static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
-                        struct bitmap *pcopymapDest)
-{
-       int i;
-       bool bcopyall = (pcopymapDest == NULL);
-       struct parmlist_entry *data;
-
-       for (i = 0; parm_table[i].label; i++)
-               if (parm_table[i].p_class == P_LOCAL &&
-                   (bcopyall || bitmap_query(pcopymapDest,i))) {
-                       void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
-                       void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
-
-                       switch (parm_table[i].type) {
-                               case P_BOOL:
-                               case P_BOOLREV:
-                                       *(bool *)dest_ptr = *(bool *)src_ptr;
-                                       break;
-
-                               case P_INTEGER:
-                               case P_ENUM:
-                               case P_OCTAL:
-                               case P_BYTES:
-                                       *(int *)dest_ptr = *(int *)src_ptr;
-                                       break;
-
-                               case P_CHAR:
-                                       *(char *)dest_ptr = *(char *)src_ptr;
-                                       break;
-
-                               case P_STRING:
-                                       string_set((char **)dest_ptr,
-                                                  *(char **)src_ptr);
-                                       break;
-
-                               case P_USTRING:
-                               {
-                                       char *upper_string = strupper_talloc(talloc_tos(), 
-                                                                            *(char **)src_ptr);
-                                       string_set((char **)dest_ptr,
-                                                  upper_string);
-                                       TALLOC_FREE(upper_string);
-                                       break;
-                               }
-                               case P_LIST:
-                                       TALLOC_FREE(*((char ***)dest_ptr));
-                                       *((char ***)dest_ptr) = str_list_copy(NULL, 
-                                                     *(const char ***)src_ptr);
-                                       break;
-                               default:
-                                       break;
-                       }
-               }
-
-       if (bcopyall) {
-               init_copymap(pserviceDest);
-               if (pserviceSource->copymap)
-                       bitmap_copy(pserviceDest->copymap,
-                                   pserviceSource->copymap);
-       }
-
-       data = pserviceSource->param_opt;
-       while (data) {
-               set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
-               data = data->next;
-       }
-}
-
 /***************************************************************************
 Check a service for consistency. Return false if the service is in any way
 incomplete or faulty, else true.
@@ -2455,7 +2141,7 @@ static bool process_registry_globals(void)
 {
        bool ret;
 
-       add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
+       add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
 
        ret = do_parameter("registry shares", "yes", NULL);
        if (!ret) {
@@ -2537,54 +2223,6 @@ done:
 
 static uint8_t include_depth;
 
-static struct file_lists {
-       struct file_lists *next;
-       char *name;
-       char *subfname;
-       time_t modtime;
-} *file_lists = NULL;
-
-/*******************************************************************
- Keep a linked list of all config files so we know when one has changed 
- it's date and needs to be reloaded.
-********************************************************************/
-
-static void add_to_file_list(const char *fname, const char *subfname)
-{
-       struct file_lists *f = file_lists;
-
-       while (f) {
-               if (f->name && !strcmp(f->name, fname))
-                       break;
-               f = f->next;
-       }
-
-       if (!f) {
-               f = SMB_MALLOC_P(struct file_lists);
-               if (!f)
-                       return;
-               f->next = file_lists;
-               f->name = SMB_STRDUP(fname);
-               if (!f->name) {
-                       SAFE_FREE(f);
-                       return;
-               }
-               f->subfname = SMB_STRDUP(subfname);
-               if (!f->subfname) {
-                       SAFE_FREE(f->name);
-                       SAFE_FREE(f);
-                       return;
-               }
-               file_lists = f;
-               f->modtime = file_modtime(subfname);
-       } else {
-               time_t t = file_modtime(subfname);
-               if (t)
-                       f->modtime = t;
-       }
-       return;
-}
-
 /**
  * Free the file lists
  */
@@ -2596,9 +2234,7 @@ static void free_file_list(void)
        f = file_lists;
        while( f ) {
                next = f->next;
-               SAFE_FREE( f->name );
-               SAFE_FREE( f->subfname );
-               SAFE_FREE( f );
+               TALLOC_FREE( f );
                f = next;
        }
        file_lists = NULL;
@@ -2669,8 +2305,11 @@ bool lp_file_list_changed(void)
                                         ("file %s modified: %s\n", n2,
                                          ctime(&mod_time)));
                                f->modtime = mod_time;
-                               SAFE_FREE(f->subfname);
-                               f->subfname = SMB_STRDUP(n2);
+                               TALLOC_FREE(f->subfname);
+                               f->subfname = talloc_strdup(f, n2);
+                               if (f->subfname == NULL) {
+                                       smb_panic("talloc_strdup failed");
+                               }
                                TALLOC_FREE(n2);
                                return true;
                        }
@@ -2696,80 +2335,12 @@ static void init_iconv(void)
                                                      true, global_iconv_handle);
 }
 
-static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       if (strcmp(*ptr, pszParmValue) != 0) {
-               string_set(ptr, pszParmValue);
-               init_iconv();
-       }
-       return true;
-}
-
-static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       bool is_utf8 = false;
-       size_t len = strlen(pszParmValue);
-
-       if (len == 4 || len == 5) {
-               /* Don't use StrCaseCmp here as we don't want to
-                  initialize iconv. */
-               if ((toupper_m(pszParmValue[0]) == 'U') &&
-                   (toupper_m(pszParmValue[1]) == 'T') &&
-                   (toupper_m(pszParmValue[2]) == 'F')) {
-                       if (len == 4) {
-                               if (pszParmValue[3] == '8') {
-                                       is_utf8 = true;
-                               }
-                       } else {
-                               if (pszParmValue[3] == '-' &&
-                                   pszParmValue[4] == '8') {
-                                       is_utf8 = true;
-                               }
-                       }
-               }
-       }
-
-       if (strcmp(*ptr, pszParmValue) != 0) {
-               if (is_utf8) {
-                       DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
-                               "be UTF8, using (default value) %s instead.\n",
-                               DEFAULT_DOS_CHARSET));
-                       pszParmValue = DEFAULT_DOS_CHARSET;
-               }
-               string_set(ptr, pszParmValue);
-               init_iconv();
-       }
-       return true;
-}
-
-static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       bool ret = true;
-       TALLOC_CTX *frame = talloc_stackframe();
-       char *realm = strupper_talloc(frame, pszParmValue);
-       char *dnsdomain = strlower_talloc(realm, pszParmValue);
-
-       ret &= string_set(&Globals.realm_original, pszParmValue);
-       ret &= string_set(&Globals.realm, realm);
-       ret &= string_set(&Globals.dnsdomain, dnsdomain);
-       TALLOC_FREE(frame);
-
-       return ret;
-}
-
-static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       TALLOC_FREE(Globals.netbios_aliases);
-       Globals.netbios_aliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
-       return set_netbios_aliases(Globals.netbios_aliases);
-}
-
 /***************************************************************************
  Handle the include operation.
 ***************************************************************************/
 static bool bAllowIncludeRegistry = true;
 
-static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
+bool lp_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
 {
        char *fname;
 
@@ -2800,9 +2371,13 @@ static bool handle_include(struct loadparm_context *unused, int snum, const char
                                 current_user_info.domain,
                                 pszParmValue);
 
-       add_to_file_list(pszParmValue, fname);
+       add_to_file_list(NULL, &file_lists, pszParmValue, fname);
 
-       string_set(ptr, fname);
+       if (snum < 0) {
+               string_set(Globals.ctx, ptr, fname);
+       } else {
+               string_set(ServicePtrs[snum], ptr, fname);
+       }
 
        if (file_exist(fname)) {
                bool ret;
@@ -2818,74 +2393,6 @@ static bool handle_include(struct loadparm_context *unused, int snum, const char
        return true;
 }
 
-/***************************************************************************
- Handle the interpretation of the copy parameter.
-***************************************************************************/
-
-static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       bool bRetval;
-       int iTemp;
-       struct loadparm_service serviceTemp;
-
-       string_set(ptr, pszParmValue);
-
-       init_service(&serviceTemp);
-
-       bRetval = false;
-
-       DEBUG(3, ("Copying service from service %s\n", pszParmValue));
-
-       if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
-               if (iTemp == iServiceIndex) {
-                       DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
-               } else {
-                       copy_service(ServicePtrs[iServiceIndex],
-                                    &serviceTemp,
-                                    ServicePtrs[iServiceIndex]->copymap);
-                       bRetval = true;
-               }
-       } else {
-               DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
-               bRetval = false;
-       }
-
-       free_service(&serviceTemp);
-       return (bRetval);
-}
-
-static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       Globals.ldap_debug_level = lp_int(pszParmValue);
-       init_ldap_debugging();
-       return true;
-}
-
-/*
- * idmap related parameters
- */
-
-static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
-
-       return true;
-}
-
-static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : range", pszParmValue);
-
-       return true;
-}
-
-static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       lp_do_parameter(snum, "idmap config * : range", pszParmValue);
-
-       return true;
-}
-
 bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
 {
        char *config_option = NULL;
@@ -2963,16 +2470,6 @@ const char *lp_idmap_default_backend(void)
        return lp_idmap_backend("*");
 }
 
-/***************************************************************************
- Handle the DEBUG level list.
-***************************************************************************/
-
-static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
-{
-       string_set(ptr, pszParmValueIn);
-       return debug_parse_levels(pszParmValueIn);
-}
-
 /***************************************************************************
  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
 ***************************************************************************/
@@ -3023,69 +2520,6 @@ const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
        return lp_string(ctx, Globals.ldap_suffix);
 }
 
-/****************************************************************************
- set the value for a P_ENUM
- ***************************************************************************/
-
-static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
-                              int *ptr )
-{
-       int i;
-
-       for (i = 0; parm->enum_list[i].name; i++) {
-               if ( strequal(pszParmValue, parm->enum_list[i].name)) {
-                       *ptr = parm->enum_list[i].value;
-                       return;
-               }
-       }
-       DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
-                 pszParmValue, parm->label));
-}
-
-/***************************************************************************
-***************************************************************************/
-
-static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
-{
-       static int parm_num = -1;
-       struct loadparm_service *s;
-
-       if ( parm_num == -1 )
-               parm_num = lpcfg_map_parameter( "printing" );
-
-       lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
-
-       if ( snum < 0 )
-               s = &sDefault;
-       else
-               s = ServicePtrs[snum];
-
-       init_printer_values( s );
-
-       return true;
-}
-
-
-/***************************************************************************
- Initialise a copymap.
-***************************************************************************/
-
-static void init_copymap(struct loadparm_service *pservice)
-{
-       int i;
-
-       TALLOC_FREE(pservice->copymap);
-
-       pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
-       if (!pservice->copymap)
-               DEBUG(0,
-                     ("Couldn't allocate copymap!! (size %d)\n",
-                      (int)NUMPARAMETERS));
-       else
-               for (i = 0; i < NUMPARAMETERS; i++)
-                       bitmap_set(pservice->copymap, i);
-}
-
 /**
   return the parameter pointer for a parameter
 */
@@ -3121,6 +2555,8 @@ 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();
 
        parmnum = lpcfg_map_parameter(pszParmName);
 
@@ -3128,6 +2564,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                if (strchr(pszParmName, ':') == NULL) {
                        DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
                                  pszParmName));
+                       TALLOC_FREE(frame);
                        return true;
                }
 
@@ -3135,16 +2572,22 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                 * We've got a parametric option
                 */
 
-               opt_list = (snum < 0)
-                       ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
-               set_param_opt(opt_list, pszParmName, pszParmValue, 0);
+               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) {
+               TALLOC_FREE(frame);
                return true;
        }
 
@@ -3161,6 +2604,7 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        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]);
@@ -3178,12 +2622,22 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                                bitmap_clear(ServicePtrs[snum]->copymap, i);
                        }
                }
+               mem_ctx = ServicePtrs[snum];
+       } else {
+               mem_ctx = Globals.ctx;
        }
 
        /* if it is a special case then go ahead */
        if (parm_table[parmnum].special) {
-               return parm_table[parmnum].special(NULL, snum, pszParmValue,
-                                                  (char **)parm_ptr);
+               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 */
@@ -3209,6 +2663,8 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
                        if ( i != 1 ) {
                            DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
+                           TALLOC_FREE(frame);
+                               return false;
                        }
                        break;
 
@@ -3235,24 +2691,28 @@ bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        break;
 
                case P_STRING:
-                       string_set((char **)parm_ptr, pszParmValue);
+                       string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
                        break;
 
                case P_USTRING:
                {
                        char *upper_string = strupper_talloc(talloc_tos(), 
                                                             pszParmValue);
-                       string_set((char **)parm_ptr, upper_string);
+                       string_set(mem_ctx, (char **)parm_ptr, upper_string);
                        TALLOC_FREE(upper_string);
                        break;
                }
                case P_ENUM:
-                       lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
+                       if (!lp_set_enum_parm(&parm_table[parmnum], pszParmValue, (int*)parm_ptr)) {
+                               TALLOC_FREE(frame);
+                               return false;
+                       }
                        break;
                case P_SEP:
                        break;
        }
 
+       TALLOC_FREE(frame);
        return true;
 }
 
@@ -3261,7 +2721,7 @@ set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
 FLAG_CMDLINE won't be overridden by loads from smb.conf.
 ***************************************************************************/
 
-static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
+static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
 {
        int parmnum, i;
        parmnum = lpcfg_map_parameter(pszParmName);
@@ -3281,33 +2741,36 @@ static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmVa
                     i--) {
                        parm_table[i].flags |= FLAG_CMDLINE;
                }
-               for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
+               for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
                             && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
                        parm_table[i].flags |= FLAG_CMDLINE;
                }
 
-               if (store_values) {
-                       store_lp_set_cmdline(pszParmName, pszParmValue);
-               }
                return true;
        }
 
        /* it might be parametric */
        if (strchr(pszParmName, ':') != NULL) {
-               set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
-               if (store_values) {
-                       store_lp_set_cmdline(pszParmName, pszParmValue);
-               }
+               set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
                return true;
        }
 
        DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
-       return true;
+       return false;
 }
 
 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
 {
-       return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
+       bool ret;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       ret = lp_set_cmdline_helper(pszParmName, pszParmValue);
+       if (ret) {
+               store_lp_set_cmdline(pszParmName, pszParmValue);
+       }
+
+       TALLOC_FREE(frame);
+       return ret;
 }
 
 /***************************************************************************
@@ -3326,37 +2789,6 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue,
                                pszParmName, pszParmValue));
 }
 
-/*
-  set a option from the commandline in 'a=b' format. Use to support --option
-*/
-bool lp_set_option(const char *option)
-{
-       char *p, *s;
-       bool ret;
-
-       s = talloc_strdup(NULL, option);
-       if (!s) {
-               return false;
-       }
-
-       p = strchr(s, '=');
-       if (!p) {
-               talloc_free(s);
-               return false;
-       }
-
-       *p = 0;
-
-       /* skip white spaces after the = sign */
-       do {
-               p++;
-       } while (*p == ' ');
-
-       ret = lp_set_cmdline(s, p);
-       talloc_free(s);
-       return ret;
-}
-
 /***************************************************************************
  Initialize any local variables in the sDefault table, after parsing a
  [globals] section.
@@ -3458,7 +2890,7 @@ static bool is_default(int i)
        switch (parm_table[i].type) {
                case P_LIST:
                case P_CMDLIST:
-                       return str_list_equal((const char **)parm_table[i].def.lvalue, 
+                       return str_list_equal((const char * const *)parm_table[i].def.lvalue,
                                              *(const char ***)lp_parm_ptr(NULL, 
                                                                           &parm_table[i]));
                case P_STRING:
@@ -3525,46 +2957,9 @@ static void dump_globals(FILE *f)
  Display the contents of a single services record.
 ***************************************************************************/
 
-static void dump_a_service(struct loadparm_service *pService, FILE * f)
+static void dump_a_service(struct loadparm_service *pService, FILE * f, bool show_defaults)
 {
-       int i;
-       struct parmlist_entry *data;
-
-       if (pService != &sDefault)
-               fprintf(f, "[%s]\n", pService->szService);
-
-       for (i = 0; parm_table[i].label; i++) {
-
-               if (parm_table[i].p_class == P_LOCAL &&
-                   !(parm_table[i].flags & FLAG_META) &&
-                   (*parm_table[i].label != '-') &&
-                   (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
-               {
-                       if (pService == &sDefault) {
-                               if (defaults_saved && is_default(i))
-                                       continue;
-                       } else {
-                               if (lpcfg_equal_parameter(parm_table[i].type,
-                                                         lp_parm_ptr(pService, &parm_table[i]),
-                                                         lp_parm_ptr(NULL, &parm_table[i])))
-                                       continue;
-                       }
-
-                       fprintf(f, "\t%s = ", parm_table[i].label);
-                       lpcfg_print_parameter(&parm_table[i],
-                                       lp_parm_ptr(pService, &parm_table[i]),
-                                       f);
-                       fprintf(f, "\n");
-               }
-       }
-
-               if (pService->param_opt != NULL) {
-                       data = pService->param_opt;
-                       while(data) {
-                               fprintf(f, "\t%s = %s\n", data->key, data->value);
-                               data = data->next;
-                       }
-               }
+       return lpcfg_dump_a_service(pService, &sDefault, f, NULL, show_defaults);
 }
 
 /***************************************************************************
@@ -3574,30 +2969,9 @@ static void dump_a_service(struct loadparm_service *pService, FILE * f)
 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
 {
        bool result = false;
-       fstring local_parm_name;
-       char *parm_opt;
-       const char *parm_opt_value;
 
        struct loadparm_context *lp_ctx;
 
-       /* check for parametrical option */
-       fstrcpy( local_parm_name, parm_name);
-       parm_opt = strchr( local_parm_name, ':');
-
-       if (parm_opt) {
-               *parm_opt = '\0';
-               parm_opt++;
-               if (strlen(parm_opt)) {
-                       parm_opt_value = lp_parm_const_string( snum,
-                               local_parm_name, parm_opt, NULL);
-                       if (parm_opt_value) {
-                               printf( "%s\n", parm_opt_value);
-                               result = true;
-                       }
-               }
-               return result;
-       }
-
        lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
        if (lp_ctx == NULL) {
                return false;
@@ -3673,9 +3047,11 @@ static void lp_add_auto_services(char *str)
        if (!str)
                return;
 
-       s = SMB_STRDUP(str);
-       if (!s)
+       s = talloc_strdup(talloc_tos(), str);
+       if (!s) {
+               smb_panic("talloc_strdup failed");
                return;
+       }
 
        homes = lp_servicenumber(HOMES_NAME);
 
@@ -3693,7 +3069,7 @@ static void lp_add_auto_services(char *str)
 
                TALLOC_FREE(home);
        }
-       SAFE_FREE(s);
+       TALLOC_FREE(s);
 }
 
 /***************************************************************************
@@ -3709,7 +3085,7 @@ void lp_add_one_printer(const char *name, const char *comment,
        if (lp_servicenumber(name) < 0) {
                lp_add_printer(name, printers);
                if ((i = lp_servicenumber(name)) >= 0) {
-                       string_set(&ServicePtrs[i]->comment, comment);
+                       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
                        ServicePtrs[i]->autoloaded = true;
                }
        }
@@ -3788,7 +3164,10 @@ static void lp_save_defaults(void)
                                break;
                        case P_STRING:
                        case P_USTRING:
-                               parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
+                               parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
+                               if (parm_table[i].def.svalue == NULL) {
+                                       smb_panic("talloc_strdup failed");
+                               }
                                break;
                        case P_BOOL:
                        case P_BOOLREV:
@@ -4252,8 +3631,8 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 
        /* And note when it was loaded. */
        ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
-       string_set(&ServicePtrs[iService]->path, sharepath);
-       string_set(&ServicePtrs[iService]->comment, comment);
+       string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
+       string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
 
        ret = iService;
 
@@ -4278,23 +3657,25 @@ static bool usershare_exists(int iService, struct timespec *last_mod)
        const char *usersharepath = Globals.usershare_path;
        char *fname;
 
-       if (asprintf(&fname, "%s/%s",
+       fname = talloc_asprintf(talloc_tos(),
+                               "%s/%s",
                                usersharepath,
-                               ServicePtrs[iService]->szService) < 0) {
+                               ServicePtrs[iService]->szService);
+       if (fname == NULL) {
                return false;
        }
 
        if (sys_lstat(fname, &lsbuf, false) != 0) {
-               SAFE_FREE(fname);
+               TALLOC_FREE(fname);
                return false;
        }
 
        if (!S_ISREG(lsbuf.st_ex_mode)) {
-               SAFE_FREE(fname);
+               TALLOC_FREE(fname);
                return false;
        }
 
-       SAFE_FREE(fname);
+       TALLOC_FREE(fname);
        *last_mod = lsbuf.st_ex_mtime;
        return true;
 }
@@ -4551,7 +3932,7 @@ void gfree_loadparm(void)
                }
        }
 
-       SAFE_FREE( ServicePtrs );
+       TALLOC_FREE( ServicePtrs );
        iNumServices = 0;
 
        /* Now release all resources allocated to global
@@ -4629,7 +4010,7 @@ static bool lp_load_ex(const char *pszFname,
                        smb_panic("lp_load_ex: out of memory");
                }
 
-               add_to_file_list(pszFname, n2);
+               add_to_file_list(NULL, &file_lists, pszFname, n2);
 
                bRetval = pm_process(n2, do_section, do_parameter, NULL);
                TALLOC_FREE(n2);
@@ -4849,7 +4230,7 @@ void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
 
        dump_globals(f);
 
-       dump_a_service(&sDefault, f);
+       dump_a_service(&sDefault, f, show_defaults);
 
        for (iService = 0; iService < maxtoprint; iService++) {
                fprintf(f,"\n");
@@ -4866,7 +4247,7 @@ 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);
+               dump_a_service(ServicePtrs[snum], f, show_defaults);
        }
 }
 
@@ -5040,22 +4421,6 @@ void lp_remove_service(int snum)
        ServicePtrs[snum]->valid = false;
 }
 
-/*******************************************************************
- Copy a service.
-********************************************************************/
-
-void lp_copy_service(int snum, const char *new_name)
-{
-       do_section(new_name, NULL);
-       if (snum >= 0) {
-               snum = lp_servicenumber(new_name);
-               if (snum >= 0) {
-                       char *name = lp_servicename(talloc_tos(), snum);
-                       lp_do_parameter(snum, "copy", name);
-               }
-       }
-}
-
 const char *lp_printername(TALLOC_CTX *ctx, int snum)
 {
        const char *ret = lp__printername(ctx, snum);
@@ -5073,7 +4438,7 @@ const char *lp_printername(TALLOC_CTX *ctx, int snum)
 
 void lp_set_logfile(const char *name)
 {
-       string_set(&Globals.logfile, name);
+       string_set(Globals.ctx, &Globals.logfile, name);
        debug_set_logfile(name);
 }
 
@@ -5173,7 +4538,7 @@ void set_store_dos_attributes(int snum, bool val)
 
 void lp_set_mangling_method(const char *new_method)
 {
-       string_set(&Globals.mangling_method, new_method);
+       string_set(Globals.ctx, &Globals.mangling_method, new_method);
 }
 
 /*******************************************************************
@@ -5227,7 +4592,7 @@ int lp_min_receive_file_size(void)
        if (Globals.iminreceivefile < 0) {
                return 0;
        }
-       return MIN(Globals.iminreceivefile, BUFFER_SIZE);
+       return Globals.iminreceivefile;
 }
 
 /*******************************************************************
@@ -5285,3 +4650,8 @@ int lp_security(void)
        return lp_find_security(lp__server_role(),
                                lp__security());
 }
+
+struct loadparm_global * get_globals(void)
+{
+       return &Globals;
+}