build: Remove special case for the build farm
[samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "lib/param/loadparm.h"
60 #include "printing.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
63
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71
72 #ifdef HAVE_SYS_SYSCTL_H
73 #include <sys/sysctl.h>
74 #endif
75
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
79
80 #ifdef CLUSTER_SUPPORT
81 #include "ctdb_private.h"
82 #endif
83
84 bool bLoaded = false;
85
86 extern userdom_struct current_user_info;
87
88 /* the special value for the include parameter
89  * to be interpreted not as a file name but to
90  * trigger loading of the global smb.conf options
91  * from registry. */
92 #ifndef INCLUDE_REGISTRY_NAME
93 #define INCLUDE_REGISTRY_NAME "registry"
94 #endif
95
96 static bool in_client = false;          /* Not in the client by default */
97 static struct smbconf_csn conf_last_csn;
98
99 static int config_backend = CONFIG_BACKEND_FILE;
100
101 /* some helpful bits */
102 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
103 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
104
105 #define USERSHARE_VALID 1
106 #define USERSHARE_PENDING_DELETE 2
107
108 static bool defaults_saved = false;
109
110 #define LOADPARM_EXTRA_GLOBALS \
111         struct parmlist_entry *param_opt;                               \
112         char *szRealm;                                                  \
113         char *loglevel;                                                 \
114         int iminreceivefile;                                            \
115         char *szPrintcapname;                                           \
116         int CupsEncrypt;                                                \
117         int  iPreferredMaster;                                          \
118         char *szLdapMachineSuffix;                                      \
119         char *szLdapUserSuffix;                                         \
120         char *szLdapIdmapSuffix;                                        \
121         char *szLdapGroupSuffix;                                        \
122         char *szStateDir;                                               \
123         char *szCacheDir;                                               \
124         char *szUsershareTemplateShare;                                 \
125         char *szIdmapUID;                                               \
126         char *szIdmapGID;                                               \
127         int winbindMaxDomainConnections;                                \
128         int ismb2_max_credits;                                          \
129         char *tls_keyfile;                                              \
130         char *tls_certfile;                                             \
131         char *tls_cafile;                                               \
132         char *tls_crlfile;                                              \
133         char *tls_dhpfile;                                              \
134         char *panic_action;                                             \
135         int bPreferredMaster;
136
137 #include "param/param_global.h"
138
139 static struct loadparm_global Globals;
140
141 /* This is a default service used to prime a services structure */
142 static struct loadparm_service sDefault =
143 {
144         .valid = true,
145         .autoloaded = false,
146         .usershare = 0,
147         .usershare_last_mod = {0, 0},
148         .szService = NULL,
149         .szPath = NULL,
150         .szUsername = NULL,
151         .szInvalidUsers = NULL,
152         .szValidUsers = NULL,
153         .szAdminUsers = NULL,
154         .szCopy = NULL,
155         .szInclude = NULL,
156         .szPreExec = NULL,
157         .szPostExec = NULL,
158         .szRootPreExec = NULL,
159         .szRootPostExec = NULL,
160         .szCupsOptions = NULL,
161         .szPrintcommand = NULL,
162         .szLpqcommand = NULL,
163         .szLprmcommand = NULL,
164         .szLppausecommand = NULL,
165         .szLpresumecommand = NULL,
166         .szQueuepausecommand = NULL,
167         .szQueueresumecommand = NULL,
168         .szPrintername = NULL,
169         .szPrintjobUsername = NULL,
170         .szDontdescend = NULL,
171         .szHostsallow = NULL,
172         .szHostsdeny = NULL,
173         .szMagicScript = NULL,
174         .szMagicOutput = NULL,
175         .szVetoFiles = NULL,
176         .szHideFiles = NULL,
177         .szVetoOplockFiles = NULL,
178         .comment = NULL,
179         .force_user = NULL,
180         .force_group = NULL,
181         .readlist = NULL,
182         .writelist = NULL,
183         .volume = NULL,
184         .fstype = NULL,
185         .szVfsObjects = NULL,
186         .szMSDfsProxy = NULL,
187         .szAioWriteBehind = NULL,
188         .szDfree = NULL,
189         .iMinPrintSpace = 0,
190         .iMaxPrintJobs = 1000,
191         .iMaxReportedPrintJobs = 0,
192         .iWriteCacheSize = 0,
193         .iCreate_mask = 0744,
194         .iCreate_force_mode = 0,
195         .iSecurity_mask = 0777,
196         .iSecurity_force_mode = 0,
197         .iDir_mask = 0755,
198         .iDir_force_mode = 0,
199         .iDir_Security_mask = 0777,
200         .iDir_Security_force_mode = 0,
201         .iMaxConnections = 0,
202         .iDefaultCase = CASE_LOWER,
203         .iPrinting = DEFAULT_PRINTING,
204         .iOplockContentionLimit = 2,
205         .iCSCPolicy = 0,
206         .iBlock_size = 1024,
207         .iDfreeCacheTime = 0,
208         .bPreexecClose = false,
209         .bRootpreexecClose = false,
210         .iCaseSensitive = Auto,
211         .bCasePreserve = true,
212         .bShortCasePreserve = true,
213         .bHideDotFiles = true,
214         .bHideSpecialFiles = false,
215         .bHideUnReadable = false,
216         .bHideUnWriteableFiles = false,
217         .bBrowseable = true,
218         .bAccessBasedShareEnum = false,
219         .bAvailable = true,
220         .bRead_only = true,
221         .bNo_set_dir = true,
222         .bGuest_only = false,
223         .bAdministrative_share = false,
224         .bGuest_ok = false,
225         .bPrint_ok = false,
226         .bPrintNotifyBackchannel = true,
227         .bMap_system = false,
228         .bMap_hidden = false,
229         .bMap_archive = true,
230         .bStoreDosAttributes = false,
231         .bDmapiSupport = false,
232         .bLocking = true,
233         .iStrictLocking = Auto,
234         .bPosixLocking = true,
235         .bShareModes = true,
236         .bOpLocks = true,
237         .bKernelOplocks = false,
238         .bLevel2OpLocks = true,
239         .bOnlyUser = false,
240         .bMangledNames = true,
241         .bWidelinks = false,
242         .bSymlinks = true,
243         .bSyncAlways = false,
244         .bStrictAllocate = false,
245         .bStrictSync = false,
246         .magic_char = '~',
247         .copymap = NULL,
248         .bDeleteReadonly = false,
249         .bFakeOplocks = false,
250         .bDeleteVetoFiles = false,
251         .bDosFilemode = false,
252         .bDosFiletimes = true,
253         .bDosFiletimeResolution = false,
254         .bFakeDirCreateTimes = false,
255         .bBlockingLocks = true,
256         .bInheritPerms = false,
257         .bInheritACLS = false,
258         .bInheritOwner = false,
259         .bMSDfsRoot = false,
260         .bUseClientDriver = false,
261         .bDefaultDevmode = true,
262         .bForcePrintername = false,
263         .bNTAclSupport = true,
264         .bForceUnknownAclUser = false,
265         .bUseSendfile = false,
266         .bProfileAcls = false,
267         .bMap_acl_inherit = false,
268         .bAfs_Share = false,
269         .bEASupport = false,
270         .bAclCheckPermissions = true,
271         .bAclMapFullControl = true,
272         .bAclGroupControl = false,
273         .bChangeNotify = true,
274         .bKernelChangeNotify = true,
275         .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
276         .iAioReadSize = 0,
277         .iAioWriteSize = 0,
278         .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280         .iDirectoryNameCacheSize = 0,
281 #else
282         .iDirectoryNameCacheSize = 100,
283 #endif
284         .ismb_encrypt = SMB_SIGNING_DEFAULT,
285         .param_opt = NULL,
286         .dummy = ""
287 };
288
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
298
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
300
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
314
315 /* these are parameter handlers which are not needed in the
316  * source3 code
317  */
318
319 #define handle_logfile NULL
320
321 static void set_allowed_client_auth(void);
322
323 static void add_to_file_list(const char *fname, const char *subfname);
324 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
325 static void free_param_opts(struct parmlist_entry **popts);
326
327 #include "lib/param/param_table.c"
328
329 /* this is used to prevent lots of mallocs of size 1 */
330 static const char null_string[] = "";
331
332 /**
333  Set a string value, allocing the space for the string
334 **/
335
336 static bool string_init(char **dest,const char *src)
337 {
338         size_t l;
339
340         if (!src)
341                 src = "";
342
343         l = strlen(src);
344
345         if (l == 0) {
346                 *dest = discard_const_p(char, null_string);
347         } else {
348                 (*dest) = SMB_STRDUP(src);
349                 if ((*dest) == NULL) {
350                         DEBUG(0,("Out of memory in string_init\n"));
351                         return false;
352                 }
353         }
354         return(true);
355 }
356
357 /**
358  Free a string value.
359 **/
360
361 static void string_free(char **s)
362 {
363         if (!s || !(*s))
364                 return;
365         if (*s == null_string)
366                 *s = NULL;
367         SAFE_FREE(*s);
368 }
369
370 /**
371  Set a string value, deallocating any existing space, and allocing the space
372  for the string
373 **/
374
375 static bool string_set(char **dest,const char *src)
376 {
377         string_free(dest);
378         return(string_init(dest,src));
379 }
380
381 /***************************************************************************
382  Initialise the sDefault parameter structure for the printer values.
383 ***************************************************************************/
384
385 static void init_printer_values(struct loadparm_service *pService)
386 {
387         /* choose defaults depending on the type of printing */
388         switch (pService->iPrinting) {
389                 case PRINT_BSD:
390                 case PRINT_AIX:
391                 case PRINT_LPRNT:
392                 case PRINT_LPROS2:
393                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
394                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
395                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
396                         break;
397
398                 case PRINT_LPRNG:
399                 case PRINT_PLP:
400                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
401                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
402                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
403                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
404                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
405                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
406                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
407                         break;
408
409                 case PRINT_CUPS:
410                 case PRINT_IPRINT:
411 #ifdef HAVE_CUPS
412                         /* set the lpq command to contain the destination printer
413                            name only.  This is used by cups_queue_get() */
414                         string_set(&pService->szLpqcommand, "%p");
415                         string_set(&pService->szLprmcommand, "");
416                         string_set(&pService->szPrintcommand, "");
417                         string_set(&pService->szLppausecommand, "");
418                         string_set(&pService->szLpresumecommand, "");
419                         string_set(&pService->szQueuepausecommand, "");
420                         string_set(&pService->szQueueresumecommand, "");
421 #else
422                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
423                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
424                         string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
425                         string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
426                         string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
427                         string_set(&pService->szQueuepausecommand, "disable '%p'");
428                         string_set(&pService->szQueueresumecommand, "enable '%p'");
429 #endif /* HAVE_CUPS */
430                         break;
431
432                 case PRINT_SYSV:
433                 case PRINT_HPUX:
434                         string_set(&pService->szLpqcommand, "lpstat -o%p");
435                         string_set(&pService->szLprmcommand, "cancel %p-%j");
436                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
437                         string_set(&pService->szQueuepausecommand, "disable %p");
438                         string_set(&pService->szQueueresumecommand, "enable %p");
439 #ifndef HPUX
440                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
441                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
442 #endif /* HPUX */
443                         break;
444
445                 case PRINT_QNX:
446                         string_set(&pService->szLpqcommand, "lpq -P%p");
447                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
448                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
449                         break;
450
451 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
452
453         case PRINT_TEST:
454         case PRINT_VLP: {
455                 const char *tdbfile;
456                 TALLOC_CTX *tmp_ctx = talloc_stackframe();
457                 char *tmp;
458
459                 tdbfile = talloc_asprintf(
460                         tmp_ctx, "tdbfile=%s",
461                         lp_parm_const_string(-1, "vlp", "tdbfile",
462                                              "/tmp/vlp.tdb"));
463                 if (tdbfile == NULL) {
464                         tdbfile="tdbfile=/tmp/vlp.tdb";
465                 }
466
467                 tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
468                                       tdbfile);
469                 string_set(&pService->szPrintcommand,
470                            tmp ? tmp : "vlp print %p %s");
471
472                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
473                                       tdbfile);
474                 string_set(&pService->szLpqcommand,
475                            tmp ? tmp : "vlp lpq %p");
476
477                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
478                                       tdbfile);
479                 string_set(&pService->szLprmcommand,
480                            tmp ? tmp : "vlp lprm %p %j");
481
482                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
483                                       tdbfile);
484                 string_set(&pService->szLppausecommand,
485                            tmp ? tmp : "vlp lppause %p %j");
486
487                 tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
488                                       tdbfile);
489                 string_set(&pService->szLpresumecommand,
490                            tmp ? tmp : "vlp lpresume %p %j");
491
492                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
493                                       tdbfile);
494                 string_set(&pService->szQueuepausecommand,
495                            tmp ? tmp : "vlp queuepause %p");
496
497                 tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
498                                       tdbfile);
499                 string_set(&pService->szQueueresumecommand,
500                            tmp ? tmp : "vlp queueresume %p");
501                 TALLOC_FREE(tmp_ctx);
502
503                 break;
504         }
505 #endif /* DEVELOPER */
506
507         }
508 }
509 /**
510  *  Function to return the default value for the maximum number of open
511  *  file descriptors permitted.  This function tries to consult the
512  *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
513  *  the smaller of those.
514  */
515 static int max_open_files(void)
516 {
517         int sysctl_max = MAX_OPEN_FILES;
518         int rlimit_max = MAX_OPEN_FILES;
519
520 #ifdef HAVE_SYSCTLBYNAME
521         {
522                 size_t size = sizeof(sysctl_max);
523                 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
524                              0);
525         }
526 #endif
527
528 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
529         {
530                 struct rlimit rl;
531
532                 ZERO_STRUCT(rl);
533
534                 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
535                         rlimit_max = rl.rlim_cur;
536
537 #if defined(RLIM_INFINITY)
538                 if(rl.rlim_cur == RLIM_INFINITY)
539                         rlimit_max = MAX_OPEN_FILES;
540 #endif
541         }
542 #endif
543
544         if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
545                 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
546                         "minimum Windows limit (%d)\n",
547                         sysctl_max,
548                         MIN_OPEN_FILES_WINDOWS));
549                 sysctl_max = MIN_OPEN_FILES_WINDOWS;
550         }
551
552         if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
553                 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
554                         "minimum Windows limit (%d)\n",
555                         rlimit_max,
556                         MIN_OPEN_FILES_WINDOWS));
557                 rlimit_max = MIN_OPEN_FILES_WINDOWS;
558         }
559
560         return MIN(sysctl_max, rlimit_max);
561 }
562
563 /**
564  * Common part of freeing allocated data for one parameter.
565  */
566 static void free_one_parameter_common(void *parm_ptr,
567                                       struct parm_struct parm)
568 {
569         if ((parm.type == P_STRING) ||
570             (parm.type == P_USTRING))
571         {
572                 string_free((char**)parm_ptr);
573         } else if (parm.type == P_LIST) {
574                 TALLOC_FREE(*((char***)parm_ptr));
575         }
576 }
577
578 /**
579  * Free the allocated data for one parameter for a share
580  * given as a service struct.
581  */
582 static void free_one_parameter(struct loadparm_service *service,
583                                struct parm_struct parm)
584 {
585         void *parm_ptr;
586
587         if (parm.p_class != P_LOCAL) {
588                 return;
589         }
590
591         parm_ptr = lp_parm_ptr(service, &parm);
592
593         free_one_parameter_common(parm_ptr, parm);
594 }
595
596 /**
597  * Free the allocated parameter data of a share given
598  * as a service struct.
599  */
600 static void free_parameters(struct loadparm_service *service)
601 {
602         uint32_t i;
603
604         for (i=0; parm_table[i].label; i++) {
605                 free_one_parameter(service, parm_table[i]);
606         }
607 }
608
609 /**
610  * Free the allocated data for one parameter for a given share
611  * specified by an snum.
612  */
613 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
614 {
615         void *parm_ptr;
616
617         if (snum < 0) {
618                 parm_ptr = lp_parm_ptr(NULL, &parm);
619         } else if (parm.p_class != P_LOCAL) {
620                 return;
621         } else {
622                 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
623         }
624
625         free_one_parameter_common(parm_ptr, parm);
626 }
627
628 /**
629  * Free the allocated parameter data for a share specified
630  * by an snum.
631  */
632 static void free_parameters_by_snum(int snum)
633 {
634         uint32_t i;
635
636         for (i=0; parm_table[i].label; i++) {
637                 free_one_parameter_by_snum(snum, parm_table[i]);
638         }
639 }
640
641 /**
642  * Free the allocated global parameters.
643  */
644 static void free_global_parameters(void)
645 {
646         free_param_opts(&Globals.param_opt);
647         free_parameters_by_snum(GLOBAL_SECTION_SNUM);
648         TALLOC_FREE(Globals.ctx);
649 }
650
651 static int map_parameter(const char *pszParmName);
652
653 struct lp_stored_option {
654         struct lp_stored_option *prev, *next;
655         const char *label;
656         const char *value;
657 };
658
659 static struct lp_stored_option *stored_options;
660
661 /*
662   save options set by lp_set_cmdline() into a list. This list is
663   re-applied when we do a globals reset, so that cmdline set options
664   are sticky across reloads of smb.conf
665  */
666 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
667 {
668         struct lp_stored_option *entry, *entry_next;
669         for (entry = stored_options; entry != NULL; entry = entry_next) {
670                 entry_next = entry->next;
671                 if (strcmp(pszParmName, entry->label) == 0) {
672                         DLIST_REMOVE(stored_options, entry);
673                         talloc_free(entry);
674                         break;
675                 }
676         }
677
678         entry = talloc(NULL, struct lp_stored_option);
679         if (!entry) {
680                 return false;
681         }
682
683         entry->label = talloc_strdup(entry, pszParmName);
684         if (!entry->label) {
685                 talloc_free(entry);
686                 return false;
687         }
688
689         entry->value = talloc_strdup(entry, pszParmValue);
690         if (!entry->value) {
691                 talloc_free(entry);
692                 return false;
693         }
694
695         DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
696
697         return true;
698 }
699
700 static bool apply_lp_set_cmdline(void)
701 {
702         struct lp_stored_option *entry = NULL;
703         for (entry = stored_options; entry != NULL; entry = entry->next) {
704                 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
705                         DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
706                                   entry->label, entry->value));
707                         return false;
708                 }
709         }
710         return true;
711 }
712
713 /***************************************************************************
714  Initialise the global parameter structure.
715 ***************************************************************************/
716
717 static void init_globals(bool reinit_globals)
718 {
719         static bool done_init = false;
720         char *s = NULL;
721         int i;
722
723         /* If requested to initialize only once and we've already done it... */
724         if (!reinit_globals && done_init) {
725                 /* ... then we have nothing more to do */
726                 return;
727         }
728
729         if (!done_init) {
730                 /* The logfile can be set before this is invoked. Free it if so. */
731                 if (Globals.logfile != NULL) {
732                         string_free(&Globals.logfile);
733                         Globals.logfile = NULL;
734                 }
735                 done_init = true;
736         } else {
737                 free_global_parameters();
738         }
739
740         /* This memset and the free_global_parameters() above will
741          * wipe out smb.conf options set with lp_set_cmdline().  The
742          * apply_lp_set_cmdline() call puts these values back in the
743          * table once the defaults are set */
744         ZERO_STRUCT(Globals);
745
746         Globals.ctx = talloc_new(NULL);
747
748         for (i = 0; parm_table[i].label; i++) {
749                 if ((parm_table[i].type == P_STRING ||
750                      parm_table[i].type == P_USTRING))
751                 {
752                         string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
753                 }
754         }
755
756
757         string_set(&sDefault.fstype, FSTYPE_STRING);
758         string_set(&sDefault.szPrintjobUsername, "%U");
759
760         init_printer_values(&sDefault);
761
762
763         DEBUG(3, ("Initialising global parameters\n"));
764
765         /* Must manually force to upper case here, as this does not go via the handler */
766         string_set(&Globals.szNetbiosName, myhostname_upper());
767
768         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
769         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
770
771         /* use the new 'hash2' method by default, with a prefix of 1 */
772         string_set(&Globals.szManglingMethod, "hash2");
773         Globals.mangle_prefix = 1;
774
775         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
776
777         /* using UTF8 by default allows us to support all chars */
778         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
779
780         /* Use codepage 850 as a default for the dos character set */
781         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
782
783         /*
784          * Allow the default PASSWD_CHAT to be overridden in local.h.
785          */
786         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
787
788         string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
789
790         string_set(&Globals.szPasswdProgram, "");
791         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
792         string_set(&Globals.szStateDir, get_dyn_STATEDIR());
793         string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
794         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
795         string_set(&Globals.nbt_client_socket_address, "0.0.0.0");
796         /*
797          * By default support explicit binding to broadcast
798          * addresses.
799          */
800         Globals.bNmbdBindExplicitBroadcast = true;
801
802         if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
803                 smb_panic("init_globals: ENOMEM");
804         }
805         string_set(&Globals.szServerString, s);
806         SAFE_FREE(s);
807 #ifdef DEVELOPER
808         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
809 #endif
810
811         string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
812
813         string_set(&Globals.szLogonDrive, "");
814         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
815         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
816         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
817
818         Globals.szNameResolveOrder = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
819         string_set(&Globals.szPasswordServer, "*");
820
821         Globals.AlgorithmicRidBase = BASE_RID;
822
823         Globals.bLoadPrinters = true;
824         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
825
826         Globals.ConfigBackend = config_backend;
827         Globals.server_role = ROLE_AUTO;
828
829         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
830         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
831         Globals.max_xmit = 0x4104;
832         Globals.max_mux = 50;   /* This is *needed* for profile support. */
833         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
834         Globals.bDisableSpoolss = false;
835         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
836         Globals.pwordlevel = 0;
837         Globals.unamelevel = 0;
838         Globals.deadtime = 0;
839         Globals.getwd_cache = true;
840         Globals.bLargeReadwrite = true;
841         Globals.max_log_size = 5000;
842         Globals.max_open_files = max_open_files();
843         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
844         Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
845         Globals.srv_minprotocol = PROTOCOL_LANMAN1;
846         Globals.security = SEC_USER;
847         Globals.bEncryptPasswords = true;
848         Globals.clientSchannel = Auto;
849         Globals.serverSchannel = Auto;
850         Globals.bReadRaw = true;
851         Globals.bWriteRaw = true;
852         Globals.bNullPasswords = false;
853         Globals.bObeyPamRestrictions = false;
854         Globals.syslog = 1;
855         Globals.bSyslogOnly = false;
856         Globals.bTimestampLogs = true;
857         string_set(&Globals.loglevel, "0");
858         Globals.bDebugPrefixTimestamp = false;
859         Globals.bDebugHiresTimestamp = true;
860         Globals.bDebugPid = false;
861         Globals.bDebugUid = false;
862         Globals.bDebugClass = false;
863         Globals.bEnableCoreFiles = true;
864         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
865         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
866         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
867         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
868         Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
869         Globals.lm_interval = 60;
870 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
871         Globals.bNISHomeMap = false;
872 #ifdef WITH_NISPLUS_HOME
873         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
874 #else
875         string_set(&Globals.szNISHomeMapName, "auto.home");
876 #endif
877 #endif
878         Globals.bTimeServer = false;
879         Globals.bBindInterfacesOnly = false;
880         Globals.bUnixPasswdSync = false;
881         Globals.bPamPasswordChange = false;
882         Globals.bPasswdChatDebug = false;
883         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
884         Globals.bNTPipeSupport = true;  /* Do NT pipes by default. */
885         Globals.bNTStatusSupport = true; /* Use NT status by default. */
886         Globals.bStatCache = true;      /* use stat cache by default */
887         Globals.iMaxStatCacheSize = 256; /* 256k by default */
888         Globals.restrict_anonymous = 0;
889         Globals.bClientLanManAuth = false;      /* Do NOT use the LanMan hash if it is available */
890         Globals.bClientPlaintextAuth = false;   /* Do NOT use a plaintext password even if is requested by the server */
891         Globals.bLanmanAuth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
892         Globals.bNTLMAuth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
893         Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
894         /* Note, that we will also use NTLM2 session security (which is different), if it is available */
895
896         Globals.map_to_guest = 0;       /* By Default, "Never" */
897         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
898         Globals.enhanced_browsing = true;
899         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
900 #ifdef MMAP_BLACKLIST
901         Globals.bUseMmap = false;
902 #else
903         Globals.bUseMmap = true;
904 #endif
905         Globals.bUnicode = true;
906         Globals.bUnixExtensions = true;
907         Globals.bResetOnZeroVC = false;
908         Globals.bLogWriteableFilesOnExit = false;
909         Globals.bCreateKrb5Conf = true;
910         Globals.winbindMaxDomainConnections = 1;
911
912         /* hostname lookups can be very expensive and are broken on
913            a large number of sites (tridge) */
914         Globals.bHostnameLookups = false;
915
916         string_set(&Globals.passdb_backend, "tdbsam");
917         string_set(&Globals.szLdapSuffix, "");
918         string_set(&Globals.szLdapMachineSuffix, "");
919         string_set(&Globals.szLdapUserSuffix, "");
920         string_set(&Globals.szLdapGroupSuffix, "");
921         string_set(&Globals.szLdapIdmapSuffix, "");
922
923         string_set(&Globals.szLdapAdminDn, "");
924         Globals.ldap_ssl = LDAP_SSL_START_TLS;
925         Globals.ldap_ssl_ads = false;
926         Globals.ldap_deref = -1;
927         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
928         Globals.ldap_delete_dn = false;
929         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
930         Globals.ldap_follow_referral = Auto;
931         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
932         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
933         Globals.ldap_page_size = LDAP_PAGE_SIZE;
934
935         Globals.ldap_debug_level = 0;
936         Globals.ldap_debug_threshold = 10;
937
938         /* This is what we tell the afs client. in reality we set the token 
939          * to never expire, though, when this runs out the afs client will 
940          * forget the token. Set to 0 to get NEVERDATE.*/
941         Globals.iAfsTokenLifetime = 604800;
942         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
943
944 /* these parameters are set to defaults that are more appropriate
945    for the increasing samba install base:
946
947    as a member of the workgroup, that will possibly become a
948    _local_ master browser (lm = true).  this is opposed to a forced
949    local master browser startup (pm = true).
950
951    doesn't provide WINS server service by default (wsupp = false),
952    and doesn't provide domain master browser services by default, either.
953
954 */
955
956         Globals.bMsAddPrinterWizard = true;
957         Globals.os_level = 20;
958         Globals.bLocalMaster = true;
959         Globals.domain_master = Auto;   /* depending on bDomainLogons */
960         Globals.bDomainLogons = false;
961         Globals.bBrowseList = true;
962         Globals.bWINSsupport = false;
963         Globals.bWINSproxy = false;
964
965         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
966         Globals.InitLogonDelay = 100; /* 100 ms default delay */
967
968         Globals.bWINSdnsProxy = true;
969
970         Globals.bAllowTrustedDomains = true;
971         string_set(&Globals.szIdmapBackend, "tdb");
972
973         string_set(&Globals.szTemplateShell, "/bin/false");
974         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
975         string_set(&Globals.szWinbindSeparator, "\\");
976
977         string_set(&Globals.szCupsServer, "");
978         string_set(&Globals.szIPrintServer, "");
979
980 #ifdef CLUSTER_SUPPORT
981         string_set(&Globals.ctdbdSocket, CTDB_PATH);
982 #else
983         string_set(&Globals.ctdbdSocket, "");
984 #endif
985
986         Globals.szClusterAddresses = NULL;
987         Globals.clustering = false;
988         Globals.ctdb_timeout = 0;
989         Globals.ctdb_locktime_warn_threshold = 0;
990
991         Globals.winbind_cache_time = 300;       /* 5 minutes */
992         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
993         Globals.winbind_max_clients = 200;
994         Globals.bWinbindEnumUsers = false;
995         Globals.bWinbindEnumGroups = false;
996         Globals.bWinbindUseDefaultDomain = false;
997         Globals.bWinbindTrustedDomainsOnly = false;
998         Globals.bWinbindNestedGroups = true;
999         Globals.winbind_expand_groups = 1;
1000         Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
1001         Globals.bWinbindRefreshTickets = false;
1002         Globals.bWinbindOfflineLogon = false;
1003
1004         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
1005         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1006
1007         Globals.bPassdbExpandExplicit = false;
1008
1009         Globals.name_cache_timeout = 660; /* In seconds */
1010
1011         Globals.bUseSpnego = true;
1012         Globals.bClientUseSpnego = true;
1013
1014         Globals.client_signing = SMB_SIGNING_DEFAULT;
1015         Globals.server_signing = SMB_SIGNING_DEFAULT;
1016
1017         Globals.bDeferSharingViolations = true;
1018         Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
1019
1020         Globals.bEnablePrivileges = true;
1021         Globals.bHostMSDfs        = true;
1022         Globals.bASUSupport       = false;
1023
1024         /* User defined shares. */
1025         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1026                 smb_panic("init_globals: ENOMEM");
1027         }
1028         string_set(&Globals.szUsersharePath, s);
1029         SAFE_FREE(s);
1030         string_set(&Globals.szUsershareTemplateShare, "");
1031         Globals.iUsershareMaxShares = 0;
1032         /* By default disallow sharing of directories not owned by the sharer. */
1033         Globals.bUsershareOwnerOnly = true;
1034         /* By default disallow guest access to usershares. */
1035         Globals.bUsershareAllowGuests = false;
1036
1037         Globals.iKeepalive = DEFAULT_KEEPALIVE;
1038
1039         /* By default no shares out of the registry */
1040         Globals.bRegistryShares = false;
1041
1042         Globals.iminreceivefile = 0;
1043
1044         Globals.bMapUntrustedToDomain = false;
1045         Globals.bMulticastDnsRegister = true;
1046
1047         Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
1048         Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
1049         Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
1050         Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1051
1052         string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
1053
1054         /* Now put back the settings that were set with lp_set_cmdline() */
1055         apply_lp_set_cmdline();
1056 }
1057
1058 /*******************************************************************
1059  Convenience routine to grab string parameters into talloced memory
1060  and run standard_sub_basic on them. The buffers can be written to by
1061  callers without affecting the source string.
1062 ********************************************************************/
1063
1064 static char *lp_string(TALLOC_CTX *ctx, const char *s)
1065 {
1066         char *ret;
1067
1068         /* The follow debug is useful for tracking down memory problems
1069            especially if you have an inner loop that is calling a lp_*()
1070            function that returns a string.  Perhaps this debug should be
1071            present all the time? */
1072
1073 #if 0
1074         DEBUG(10, ("lp_string(%s)\n", s));
1075 #endif
1076         if (!s) {
1077                 return NULL;
1078         }
1079
1080         ret = talloc_sub_basic(ctx,
1081                         get_current_username(),
1082                         current_user_info.domain,
1083                         s);
1084         if (trim_char(ret, '\"', '\"')) {
1085                 if (strchr(ret,'\"') != NULL) {
1086                         TALLOC_FREE(ret);
1087                         ret = talloc_sub_basic(ctx,
1088                                         get_current_username(),
1089                                         current_user_info.domain,
1090                                         s);
1091                 }
1092         }
1093         return ret;
1094 }
1095
1096 /*
1097    In this section all the functions that are used to access the
1098    parameters from the rest of the program are defined
1099 */
1100
1101 #define FN_GLOBAL_STRING(fn_name,ptr) \
1102 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1103 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1104  const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
1105 #define FN_GLOBAL_LIST(fn_name,ptr) \
1106  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1107 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1108  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1109 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1110  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1111 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1112  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1113
1114 #define FN_LOCAL_STRING(fn_name,val) \
1115 char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1116 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1117  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1118 #define FN_LOCAL_LIST(fn_name,val) \
1119  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1120 #define FN_LOCAL_BOOL(fn_name,val) \
1121  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1122 #define FN_LOCAL_INTEGER(fn_name,val) \
1123  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1124
1125 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1126  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1127 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1128  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1129 #define FN_LOCAL_CHAR(fn_name,val) \
1130  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1131
1132
1133 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
1134 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
1135
1136 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1137  * build process or in smb.conf, we use that value.  Otherwise they
1138  * default to the value of lp_lockdir(). */
1139 const char *lp_statedir(void) {
1140         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1141             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
1142                 return(*(char **)(&Globals.szStateDir) ?
1143                        *(char **)(&Globals.szStateDir) : "");
1144         else
1145                 return(*(char **)(&Globals.szLockDir) ?
1146                        *(char **)(&Globals.szLockDir) : "");
1147 }
1148 const char *lp_cachedir(void) {
1149         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1150             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
1151                 return(*(char **)(&Globals.szCacheDir) ?
1152                        *(char **)(&Globals.szCacheDir) : "");
1153         else
1154                 return(*(char **)(&Globals.szLockDir) ?
1155                        *(char **)(&Globals.szLockDir) : "");
1156 }
1157 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
1158                   winbindMaxDomainConnections)
1159
1160 int lp_winbind_max_domain_connections(void)
1161 {
1162         if (lp_winbind_offline_logon() &&
1163             lp_winbind_max_domain_connections_int() > 1) {
1164                 DEBUG(1, ("offline logons active, restricting max domain "
1165                           "connections to 1\n"));
1166                 return 1;
1167         }
1168         return MAX(1, lp_winbind_max_domain_connections_int());
1169 }
1170
1171 int lp_smb2_max_credits(void)
1172 {
1173         if (Globals.ismb2_max_credits == 0) {
1174                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
1175         }
1176         return Globals.ismb2_max_credits;
1177 }
1178 int lp_cups_encrypt(void)
1179 {
1180         int result = 0;
1181 #ifdef HAVE_HTTPCONNECTENCRYPT
1182         switch (Globals.CupsEncrypt) {
1183                 case Auto:
1184                         result = HTTP_ENCRYPT_REQUIRED;
1185                         break;
1186                 case true:
1187                         result = HTTP_ENCRYPT_ALWAYS;
1188                         break;
1189                 case false:
1190                         result = HTTP_ENCRYPT_NEVER;
1191                         break;
1192         }
1193 #endif
1194         return result;
1195 }
1196
1197 /* These functions remain in source3/param for now */
1198
1199 FN_GLOBAL_STRING(configfile, szConfigFile)
1200
1201 #include "lib/param/param_functions.c"
1202
1203 FN_LOCAL_STRING(servicename, szService)
1204 FN_LOCAL_CONST_STRING(const_servicename, szService)
1205
1206 /* local prototypes */
1207
1208 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
1209 static const char *get_boolean(bool bool_value);
1210 static int getservicebyname(const char *pszServiceName,
1211                             struct loadparm_service *pserviceDest);
1212 static void copy_service(struct loadparm_service *pserviceDest,
1213                          struct loadparm_service *pserviceSource,
1214                          struct bitmap *pcopymapDest);
1215 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
1216                          void *userdata);
1217 static bool do_section(const char *pszSectionName, void *userdata);
1218 static void init_copymap(struct loadparm_service *pservice);
1219 static bool hash_a_service(const char *name, int number);
1220 static void free_service_byindex(int iService);
1221 static void show_parameter(int parmIndex);
1222 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
1223
1224 /*
1225  * This is a helper function for parametrical options support.  It returns a
1226  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1227  * parametrical functions are quite simple
1228  */
1229 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
1230                                                            const char *option)
1231 {
1232         bool global_section = false;
1233         char* param_key;
1234         struct parmlist_entry *data;
1235
1236         if (service == NULL) {
1237                 data = Globals.param_opt;
1238                 global_section = true;
1239         } else {
1240                 data = service->param_opt;
1241         }
1242
1243         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
1244                 DEBUG(0,("asprintf failed!\n"));
1245                 return NULL;
1246         }
1247
1248         while (data) {
1249                 if (strwicmp(data->key, param_key) == 0) {
1250                         string_free(&param_key);
1251                         return data;
1252                 }
1253                 data = data->next;
1254         }
1255
1256         if (!global_section) {
1257                 /* Try to fetch the same option but from globals */
1258                 /* but only if we are not already working with Globals */
1259                 data = Globals.param_opt;
1260                 while (data) {
1261                         if (strwicmp(data->key, param_key) == 0) {
1262                                 string_free(&param_key);
1263                                 return data;
1264                         }
1265                         data = data->next;
1266                 }
1267         }
1268
1269         string_free(&param_key);
1270
1271         return NULL;
1272 }
1273
1274 /*
1275  * This is a helper function for parametrical options support.  It returns a
1276  * pointer to parametrical option value if it exists or NULL otherwise. Actual
1277  * parametrical functions are quite simple
1278  */
1279 static struct parmlist_entry *get_parametrics(int snum, const char *type,
1280                                                 const char *option)
1281 {
1282         if (snum >= iNumServices) return NULL;
1283
1284         if (snum < 0) {
1285                 return get_parametrics_by_service(NULL, type, option);
1286         } else {
1287                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
1288         }
1289 }
1290
1291
1292 #define MISSING_PARAMETER(name) \
1293     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1294
1295 /*******************************************************************
1296 convenience routine to return int parameters.
1297 ********************************************************************/
1298 static int lp_int(const char *s)
1299 {
1300
1301         if (!s || !*s) {
1302                 MISSING_PARAMETER(lp_int);
1303                 return (-1);
1304         }
1305
1306         return (int)strtol(s, NULL, 0);
1307 }
1308
1309 /*******************************************************************
1310 convenience routine to return unsigned long parameters.
1311 ********************************************************************/
1312 static unsigned long lp_ulong(const char *s)
1313 {
1314
1315         if (!s || !*s) {
1316                 MISSING_PARAMETER(lp_ulong);
1317                 return (0);
1318         }
1319
1320         return strtoul(s, NULL, 0);
1321 }
1322
1323 /*******************************************************************
1324 convenience routine to return boolean parameters.
1325 ********************************************************************/
1326 static bool lp_bool(const char *s)
1327 {
1328         bool ret = false;
1329
1330         if (!s || !*s) {
1331                 MISSING_PARAMETER(lp_bool);
1332                 return false;
1333         }
1334
1335         if (!set_boolean(s, &ret)) {
1336                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1337                 return false;
1338         }
1339
1340         return ret;
1341 }
1342
1343 /*******************************************************************
1344 convenience routine to return enum parameters.
1345 ********************************************************************/
1346 static int lp_enum(const char *s,const struct enum_list *_enum)
1347 {
1348         int i;
1349
1350         if (!s || !*s || !_enum) {
1351                 MISSING_PARAMETER(lp_enum);
1352                 return (-1);
1353         }
1354
1355         for (i=0; _enum[i].name; i++) {
1356                 if (strequal(_enum[i].name,s))
1357                         return _enum[i].value;
1358         }
1359
1360         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1361         return (-1);
1362 }
1363
1364 #undef MISSING_PARAMETER
1365
1366 /* Return parametric option from a given service. Type is a part of option before ':' */
1367 /* Parametric option has following syntax: 'Type: option = value' */
1368 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
1369 {
1370         struct parmlist_entry *data = get_parametrics(snum, type, option);
1371
1372         if (data == NULL||data->value==NULL) {
1373                 if (def) {
1374                         return lp_string(ctx, def);
1375                 } else {
1376                         return NULL;
1377                 }
1378         }
1379
1380         return lp_string(ctx, data->value);
1381 }
1382
1383 /* Return parametric option from a given service. Type is a part of option before ':' */
1384 /* Parametric option has following syntax: 'Type: option = value' */
1385 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
1386 {
1387         struct parmlist_entry *data = get_parametrics(snum, type, option);
1388
1389         if (data == NULL||data->value==NULL)
1390                 return def;
1391
1392         return data->value;
1393 }
1394
1395 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
1396 {
1397         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
1398
1399         if (data == NULL||data->value==NULL)
1400                 return NULL;
1401
1402         return data->value;
1403 }
1404
1405
1406 /* Return parametric option from a given service. Type is a part of option before ':' */
1407 /* Parametric option has following syntax: 'Type: option = value' */
1408
1409 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
1410 {
1411         struct parmlist_entry *data = get_parametrics(snum, type, option);
1412
1413         if (data == NULL||data->value==NULL)
1414                 return (const char **)def;
1415
1416         if (data->list==NULL) {
1417                 data->list = str_list_make_v3(NULL, data->value, NULL);
1418         }
1419
1420         return (const char **)data->list;
1421 }
1422
1423 /* Return parametric option from a given service. Type is a part of option before ':' */
1424 /* Parametric option has following syntax: 'Type: option = value' */
1425
1426 int lp_parm_int(int snum, const char *type, const char *option, int def)
1427 {
1428         struct parmlist_entry *data = get_parametrics(snum, type, option);
1429
1430         if (data && data->value && *data->value)
1431                 return lp_int(data->value);
1432
1433         return def;
1434 }
1435
1436 /* Return parametric option from a given service. Type is a part of option before ':' */
1437 /* Parametric option has following syntax: 'Type: option = value' */
1438
1439 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
1440 {
1441         struct parmlist_entry *data = get_parametrics(snum, type, option);
1442
1443         if (data && data->value && *data->value)
1444                 return lp_ulong(data->value);
1445
1446         return def;
1447 }
1448
1449 /* Return parametric option from a given service. Type is a part of option before ':' */
1450 /* Parametric option has following syntax: 'Type: option = value' */
1451
1452 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
1453 {
1454         struct parmlist_entry *data = get_parametrics(snum, type, option);
1455
1456         if (data && data->value && *data->value)
1457                 return lp_bool(data->value);
1458
1459         return def;
1460 }
1461
1462 /* Return parametric option from a given service. Type is a part of option before ':' */
1463 /* Parametric option has following syntax: 'Type: option = value' */
1464
1465 int lp_parm_enum(int snum, const char *type, const char *option,
1466                  const struct enum_list *_enum, int def)
1467 {
1468         struct parmlist_entry *data = get_parametrics(snum, type, option);
1469
1470         if (data && data->value && *data->value && _enum)
1471                 return lp_enum(data->value, _enum);
1472
1473         return def;
1474 }
1475
1476
1477 /***************************************************************************
1478  Initialise a service to the defaults.
1479 ***************************************************************************/
1480
1481 static void init_service(struct loadparm_service *pservice)
1482 {
1483         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
1484         copy_service(pservice, &sDefault, NULL);
1485 }
1486
1487
1488 /**
1489  * free a param_opts structure.
1490  * param_opts handling should be moved to talloc;
1491  * then this whole functions reduces to a TALLOC_FREE().
1492  */
1493
1494 static void free_param_opts(struct parmlist_entry **popts)
1495 {
1496         struct parmlist_entry *opt, *next_opt;
1497
1498         if (*popts != NULL) {
1499                 DEBUG(5, ("Freeing parametrics:\n"));
1500         }
1501         opt = *popts;
1502         while (opt != NULL) {
1503                 string_free(&opt->key);
1504                 string_free(&opt->value);
1505                 TALLOC_FREE(opt->list);
1506                 next_opt = opt->next;
1507                 SAFE_FREE(opt);
1508                 opt = next_opt;
1509         }
1510         *popts = NULL;
1511 }
1512
1513 /***************************************************************************
1514  Free the dynamically allocated parts of a service struct.
1515 ***************************************************************************/
1516
1517 static void free_service(struct loadparm_service *pservice)
1518 {
1519         if (!pservice)
1520                 return;
1521
1522         if (pservice->szService)
1523                 DEBUG(5, ("free_service: Freeing service %s\n",
1524                        pservice->szService));
1525
1526         free_parameters(pservice);
1527
1528         string_free(&pservice->szService);
1529         TALLOC_FREE(pservice->copymap);
1530
1531         free_param_opts(&pservice->param_opt);
1532
1533         ZERO_STRUCTP(pservice);
1534 }
1535
1536
1537 /***************************************************************************
1538  remove a service indexed in the ServicePtrs array from the ServiceHash
1539  and free the dynamically allocated parts
1540 ***************************************************************************/
1541
1542 static void free_service_byindex(int idx)
1543 {
1544         if ( !LP_SNUM_OK(idx) ) 
1545                 return;
1546
1547         ServicePtrs[idx]->valid = false;
1548         invalid_services[num_invalid_services++] = idx;
1549
1550         /* we have to cleanup the hash record */
1551
1552         if (ServicePtrs[idx]->szService) {
1553                 char *canon_name = canonicalize_servicename(
1554                         talloc_tos(),
1555                         ServicePtrs[idx]->szService );
1556
1557                 dbwrap_delete_bystring(ServiceHash, canon_name );
1558                 TALLOC_FREE(canon_name);
1559         }
1560
1561         free_service(ServicePtrs[idx]);
1562         talloc_free_children(ServicePtrs[idx]);
1563 }
1564
1565 /***************************************************************************
1566  Add a new service to the services array initialising it with the given 
1567  service. 
1568 ***************************************************************************/
1569
1570 static int add_a_service(const struct loadparm_service *pservice, const char *name)
1571 {
1572         int i;
1573         struct loadparm_service tservice;
1574         int num_to_alloc = iNumServices + 1;
1575
1576         tservice = *pservice;
1577
1578         /* it might already exist */
1579         if (name) {
1580                 i = getservicebyname(name, NULL);
1581                 if (i >= 0) {
1582                         return (i);
1583                 }
1584         }
1585
1586         /* find an invalid one */
1587         i = iNumServices;
1588         if (num_invalid_services > 0) {
1589                 i = invalid_services[--num_invalid_services];
1590         }
1591
1592         /* if not, then create one */
1593         if (i == iNumServices) {
1594                 struct loadparm_service **tsp;
1595                 int *tinvalid;
1596
1597                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
1598                 if (tsp == NULL) {
1599                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1600                         return (-1);
1601                 }
1602                 ServicePtrs = tsp;
1603                 ServicePtrs[iNumServices] = talloc(NULL, struct loadparm_service);
1604                 if (!ServicePtrs[iNumServices]) {
1605                         DEBUG(0,("add_a_service: out of memory!\n"));
1606                         return (-1);
1607                 }
1608                 iNumServices++;
1609
1610                 /* enlarge invalid_services here for now... */
1611                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
1612                                              num_to_alloc);
1613                 if (tinvalid == NULL) {
1614                         DEBUG(0,("add_a_service: failed to enlarge "
1615                                  "invalid_services!\n"));
1616                         return (-1);
1617                 }
1618                 invalid_services = tinvalid;
1619         } else {
1620                 free_service_byindex(i);
1621         }
1622
1623         ServicePtrs[i]->valid = true;
1624
1625         init_service(ServicePtrs[i]);
1626         copy_service(ServicePtrs[i], &tservice, NULL);
1627         if (name)
1628                 string_set(&ServicePtrs[i]->szService, name);
1629
1630         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
1631                 i, ServicePtrs[i]->szService));
1632
1633         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
1634                 return (-1);
1635         }
1636
1637         return (i);
1638 }
1639
1640 /***************************************************************************
1641   Convert a string to uppercase and remove whitespaces.
1642 ***************************************************************************/
1643
1644 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
1645 {
1646         char *result;
1647
1648         if ( !src ) {
1649                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1650                 return NULL;
1651         }
1652
1653         result = talloc_strdup(ctx, src);
1654         SMB_ASSERT(result != NULL);
1655
1656         if (!strlower_m(result)) {
1657                 TALLOC_FREE(result);
1658                 return NULL;
1659         }
1660         return result;
1661 }
1662
1663 /***************************************************************************
1664   Add a name/index pair for the services array to the hash table.
1665 ***************************************************************************/
1666
1667 static bool hash_a_service(const char *name, int idx)
1668 {
1669         char *canon_name;
1670
1671         if ( !ServiceHash ) {
1672                 DEBUG(10,("hash_a_service: creating servicehash\n"));
1673                 ServiceHash = db_open_rbt(NULL);
1674                 if ( !ServiceHash ) {
1675                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1676                         return false;
1677                 }
1678         }
1679
1680         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1681                 idx, name));
1682
1683         canon_name = canonicalize_servicename(talloc_tos(), name );
1684
1685         dbwrap_store_bystring(ServiceHash, canon_name,
1686                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
1687                               TDB_REPLACE);
1688
1689         TALLOC_FREE(canon_name);
1690
1691         return true;
1692 }
1693
1694 /***************************************************************************
1695  Add a new home service, with the specified home directory, defaults coming
1696  from service ifrom.
1697 ***************************************************************************/
1698
1699 bool lp_add_home(const char *pszHomename, int iDefaultService,
1700                  const char *user, const char *pszHomedir)
1701 {
1702         int i;
1703
1704         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
1705                         pszHomedir[0] == '\0') {
1706                 return false;
1707         }
1708
1709         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
1710
1711         if (i < 0)
1712                 return false;
1713
1714         if (!(*(ServicePtrs[iDefaultService]->szPath))
1715             || strequal(ServicePtrs[iDefaultService]->szPath,
1716                         lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
1717                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
1718         }
1719
1720         if (!(*(ServicePtrs[i]->comment))) {
1721                 char *comment = NULL;
1722                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
1723                         return false;
1724                 }
1725                 string_set(&ServicePtrs[i]->comment, comment);
1726                 SAFE_FREE(comment);
1727         }
1728
1729         /* set the browseable flag from the global default */
1730
1731         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1732         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
1733
1734         ServicePtrs[i]->autoloaded = true;
1735
1736         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
1737                user, ServicePtrs[i]->szPath ));
1738
1739         return true;
1740 }
1741
1742 /***************************************************************************
1743  Add a new service, based on an old one.
1744 ***************************************************************************/
1745
1746 int lp_add_service(const char *pszService, int iDefaultService)
1747 {
1748         if (iDefaultService < 0) {
1749                 return add_a_service(&sDefault, pszService);
1750         }
1751
1752         return (add_a_service(ServicePtrs[iDefaultService], pszService));
1753 }
1754
1755 /***************************************************************************
1756  Add the IPC service.
1757 ***************************************************************************/
1758
1759 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
1760 {
1761         char *comment = NULL;
1762         int i = add_a_service(&sDefault, ipc_name);
1763
1764         if (i < 0)
1765                 return false;
1766
1767         if (asprintf(&comment, "IPC Service (%s)",
1768                                 Globals.szServerString) < 0) {
1769                 return false;
1770         }
1771
1772         string_set(&ServicePtrs[i]->szPath, tmpdir());
1773         string_set(&ServicePtrs[i]->szUsername, "");
1774         string_set(&ServicePtrs[i]->comment, comment);
1775         string_set(&ServicePtrs[i]->fstype, "IPC");
1776         ServicePtrs[i]->iMaxConnections = 0;
1777         ServicePtrs[i]->bAvailable = true;
1778         ServicePtrs[i]->bRead_only = true;
1779         ServicePtrs[i]->bGuest_only = false;
1780         ServicePtrs[i]->bAdministrative_share = true;
1781         ServicePtrs[i]->bGuest_ok = guest_ok;
1782         ServicePtrs[i]->bPrint_ok = false;
1783         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1784
1785         DEBUG(3, ("adding IPC service\n"));
1786
1787         SAFE_FREE(comment);
1788         return true;
1789 }
1790
1791 /***************************************************************************
1792  Add a new printer service, with defaults coming from service iFrom.
1793 ***************************************************************************/
1794
1795 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
1796 {
1797         const char *comment = "From Printcap";
1798         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
1799
1800         if (i < 0)
1801                 return false;
1802
1803         /* note that we do NOT default the availability flag to true - */
1804         /* we take it from the default service passed. This allows all */
1805         /* dynamic printers to be disabled by disabling the [printers] */
1806         /* entry (if/when the 'available' keyword is implemented!).    */
1807
1808         /* the printer name is set to the service name. */
1809         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
1810         string_set(&ServicePtrs[i]->comment, comment);
1811
1812         /* set the browseable flag from the gloabl default */
1813         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
1814
1815         /* Printers cannot be read_only. */
1816         ServicePtrs[i]->bRead_only = false;
1817         /* No share modes on printer services. */
1818         ServicePtrs[i]->bShareModes = false;
1819         /* No oplocks on printer services. */
1820         ServicePtrs[i]->bOpLocks = false;
1821         /* Printer services must be printable. */
1822         ServicePtrs[i]->bPrint_ok = true;
1823
1824         DEBUG(3, ("adding printer service %s\n", pszPrintername));
1825
1826         return true;
1827 }
1828
1829
1830 /***************************************************************************
1831  Check whether the given parameter name is valid.
1832  Parametric options (names containing a colon) are considered valid.
1833 ***************************************************************************/
1834
1835 bool lp_parameter_is_valid(const char *pszParmName)
1836 {
1837         return ((map_parameter(pszParmName) != -1) ||
1838                 (strchr(pszParmName, ':') != NULL));
1839 }
1840
1841 /***************************************************************************
1842  Check whether the given name is the name of a global parameter.
1843  Returns true for strings belonging to parameters of class
1844  P_GLOBAL, false for all other strings, also for parametric options
1845  and strings not belonging to any option.
1846 ***************************************************************************/
1847
1848 bool lp_parameter_is_global(const char *pszParmName)
1849 {
1850         int num = map_parameter(pszParmName);
1851
1852         if (num >= 0) {
1853                 return (parm_table[num].p_class == P_GLOBAL);
1854         }
1855
1856         return false;
1857 }
1858
1859 /**************************************************************************
1860  Check whether the given name is the canonical name of a parameter.
1861  Returns false if it is not a valid parameter Name.
1862  For parametric options, true is returned.
1863 **************************************************************************/
1864
1865 bool lp_parameter_is_canonical(const char *parm_name)
1866 {
1867         if (!lp_parameter_is_valid(parm_name)) {
1868                 return false;
1869         }
1870
1871         return (map_parameter(parm_name) ==
1872                 map_parameter_canonical(parm_name, NULL));
1873 }
1874
1875 /**************************************************************************
1876  Determine the canonical name for a parameter.
1877  Indicate when it is an inverse (boolean) synonym instead of a
1878  "usual" synonym.
1879 **************************************************************************/
1880
1881 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
1882                                bool *inverse)
1883 {
1884         int num;
1885
1886         if (!lp_parameter_is_valid(parm_name)) {
1887                 *canon_parm = NULL;
1888                 return false;
1889         }
1890
1891         num = map_parameter_canonical(parm_name, inverse);
1892         if (num < 0) {
1893                 /* parametric option */
1894                 *canon_parm = parm_name;
1895         } else {
1896                 *canon_parm = parm_table[num].label;
1897         }
1898
1899         return true;
1900
1901 }
1902
1903 /**************************************************************************
1904  Determine the canonical name for a parameter.
1905  Turn the value given into the inverse boolean expression when
1906  the synonym is an invers boolean synonym.
1907
1908  Return true if parm_name is a valid parameter name and
1909  in case it is an invers boolean synonym, if the val string could
1910  successfully be converted to the reverse bool.
1911  Return false in all other cases.
1912 **************************************************************************/
1913
1914 bool lp_canonicalize_parameter_with_value(const char *parm_name,
1915                                           const char *val,
1916                                           const char **canon_parm,
1917                                           const char **canon_val)
1918 {
1919         int num;
1920         bool inverse;
1921
1922         if (!lp_parameter_is_valid(parm_name)) {
1923                 *canon_parm = NULL;
1924                 *canon_val = NULL;
1925                 return false;
1926         }
1927
1928         num = map_parameter_canonical(parm_name, &inverse);
1929         if (num < 0) {
1930                 /* parametric option */
1931                 *canon_parm = parm_name;
1932                 *canon_val = val;
1933         } else {
1934                 *canon_parm = parm_table[num].label;
1935                 if (inverse) {
1936                         if (!lp_invert_boolean(val, canon_val)) {
1937                                 *canon_val = NULL;
1938                                 return false;
1939                         }
1940                 } else {
1941                         *canon_val = val;
1942                 }
1943         }
1944
1945         return true;
1946 }
1947
1948 /***************************************************************************
1949  Map a parameter's string representation to something we can use. 
1950  Returns false if the parameter string is not recognised, else TRUE.
1951 ***************************************************************************/
1952
1953 static int map_parameter(const char *pszParmName)
1954 {
1955         int iIndex;
1956
1957         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
1958                 return (-1);
1959
1960         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1961                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1962                         return (iIndex);
1963
1964         /* Warn only if it isn't parametric option */
1965         if (strchr(pszParmName, ':') == NULL)
1966                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
1967         /* We do return 'fail' for parametric options as well because they are
1968            stored in different storage
1969          */
1970         return (-1);
1971 }
1972
1973 /***************************************************************************
1974  Map a parameter's string representation to the index of the canonical
1975  form of the parameter (it might be a synonym).
1976  Returns -1 if the parameter string is not recognised.
1977 ***************************************************************************/
1978
1979 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
1980 {
1981         int parm_num, canon_num;
1982         bool loc_inverse = false;
1983
1984         parm_num = map_parameter(pszParmName);
1985         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
1986                 /* invalid, parametric or no canidate for synonyms ... */
1987                 goto done;
1988         }
1989
1990         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
1991                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
1992                         parm_num = canon_num;
1993                         goto done;
1994                 }
1995         }
1996
1997 done:
1998         if (inverse != NULL) {
1999                 *inverse = loc_inverse;
2000         }
2001         return parm_num;
2002 }
2003
2004 /***************************************************************************
2005  return true if parameter number parm1 is a synonym of parameter
2006  number parm2 (parm2 being the principal name).
2007  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
2008  false otherwise.
2009 ***************************************************************************/
2010
2011 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2012 {
2013         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
2014             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
2015             (parm_table[parm1].flags & FLAG_HIDE) &&
2016             !(parm_table[parm2].flags & FLAG_HIDE))
2017         {
2018                 if (inverse != NULL) {
2019                         if ((parm_table[parm1].type == P_BOOLREV) &&
2020                             (parm_table[parm2].type == P_BOOL))
2021                         {
2022                                 *inverse = true;
2023                         } else {
2024                                 *inverse = false;
2025                         }
2026                 }
2027                 return true;
2028         }
2029         return false;
2030 }
2031
2032 /***************************************************************************
2033  Show one parameter's name, type, [values,] and flags.
2034  (helper functions for show_parameter_list)
2035 ***************************************************************************/
2036
2037 static void show_parameter(int parmIndex)
2038 {
2039         int enumIndex, flagIndex;
2040         int parmIndex2;
2041         bool hadFlag;
2042         bool hadSyn;
2043         bool inverse;
2044         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2045                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
2046                 "P_ENUM", "P_SEP"};
2047         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2048                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2049                 FLAG_HIDE};
2050         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2051                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2052                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
2053
2054         printf("%s=%s", parm_table[parmIndex].label,
2055                type[parm_table[parmIndex].type]);
2056         if (parm_table[parmIndex].type == P_ENUM) {
2057                 printf(",");
2058                 for (enumIndex=0;
2059                      parm_table[parmIndex].enum_list[enumIndex].name;
2060                      enumIndex++)
2061                 {
2062                         printf("%s%s",
2063                                enumIndex ? "|" : "",
2064                                parm_table[parmIndex].enum_list[enumIndex].name);
2065                 }
2066         }
2067         printf(",");
2068         hadFlag = false;
2069         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
2070                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
2071                         printf("%s%s",
2072                                 hadFlag ? "|" : "",
2073                                 flag_names[flagIndex]);
2074                         hadFlag = true;
2075                 }
2076         }
2077
2078         /* output synonyms */
2079         hadSyn = false;
2080         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
2081                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
2082                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
2083                                parm_table[parmIndex2].label);
2084                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
2085                         if (!hadSyn) {
2086                                 printf(" (synonyms: ");
2087                                 hadSyn = true;
2088                         } else {
2089                                 printf(", ");
2090                         }
2091                         printf("%s%s", parm_table[parmIndex2].label,
2092                                inverse ? "[i]" : "");
2093                 }
2094         }
2095         if (hadSyn) {
2096                 printf(")");
2097         }
2098
2099         printf("\n");
2100 }
2101
2102 /***************************************************************************
2103  Show all parameter's name, type, [values,] and flags.
2104 ***************************************************************************/
2105
2106 void show_parameter_list(void)
2107 {
2108         int classIndex, parmIndex;
2109         const char *section_names[] = { "local", "global", NULL};
2110
2111         for (classIndex=0; section_names[classIndex]; classIndex++) {
2112                 printf("[%s]\n", section_names[classIndex]);
2113                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2114                         if (parm_table[parmIndex].p_class == classIndex) {
2115                                 show_parameter(parmIndex);
2116                         }
2117                 }
2118         }
2119 }
2120
2121 /***************************************************************************
2122  Check if a given string correctly represents a boolean value.
2123 ***************************************************************************/
2124
2125 bool lp_string_is_valid_boolean(const char *parm_value)
2126 {
2127         return set_boolean(parm_value, NULL);
2128 }
2129
2130 /***************************************************************************
2131  Get the standard string representation of a boolean value ("yes" or "no")
2132 ***************************************************************************/
2133
2134 static const char *get_boolean(bool bool_value)
2135 {
2136         static const char *yes_str = "yes";
2137         static const char *no_str = "no";
2138
2139         return (bool_value ? yes_str : no_str);
2140 }
2141
2142 /***************************************************************************
2143  Provide the string of the negated boolean value associated to the boolean
2144  given as a string. Returns false if the passed string does not correctly
2145  represent a boolean.
2146 ***************************************************************************/
2147
2148 bool lp_invert_boolean(const char *str, const char **inverse_str)
2149 {
2150         bool val;
2151
2152         if (!set_boolean(str, &val)) {
2153                 return false;
2154         }
2155
2156         *inverse_str = get_boolean(!val);
2157         return true;
2158 }
2159
2160 /***************************************************************************
2161  Provide the canonical string representation of a boolean value given
2162  as a string. Return true on success, false if the string given does
2163  not correctly represent a boolean.
2164 ***************************************************************************/
2165
2166 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
2167 {
2168         bool val;
2169
2170         if (!set_boolean(str, &val)) {
2171                 return false;
2172         }
2173
2174         *canon_str = get_boolean(val);
2175         return true;
2176 }
2177
2178 /***************************************************************************
2179 Find a service by name. Otherwise works like get_service.
2180 ***************************************************************************/
2181
2182 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
2183 {
2184         int iService = -1;
2185         char *canon_name;
2186         TDB_DATA data;
2187         NTSTATUS status;
2188
2189         if (ServiceHash == NULL) {
2190                 return -1;
2191         }
2192
2193         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
2194
2195         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
2196                                        &data);
2197
2198         if (NT_STATUS_IS_OK(status) &&
2199             (data.dptr != NULL) &&
2200             (data.dsize == sizeof(iService)))
2201         {
2202                 iService = *(int *)data.dptr;
2203         }
2204
2205         TALLOC_FREE(canon_name);
2206
2207         if ((iService != -1) && (LP_SNUM_OK(iService))
2208             && (pserviceDest != NULL)) {
2209                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2210         }
2211
2212         return (iService);
2213 }
2214
2215 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
2216 struct loadparm_service *lp_service(const char *pszServiceName)
2217 {
2218         int iService = getservicebyname(pszServiceName, NULL);
2219         if (iService == -1 || !LP_SNUM_OK(iService)) {
2220                 return NULL;
2221         }
2222         return ServicePtrs[iService];
2223 }
2224
2225 struct loadparm_service *lp_servicebynum(int snum)
2226 {
2227         if ((snum == -1) || !LP_SNUM_OK(snum)) {
2228                 return NULL;
2229         }
2230         return ServicePtrs[snum];
2231 }
2232
2233 struct loadparm_service *lp_default_loadparm_service()
2234 {
2235         return &sDefault;
2236 }
2237
2238
2239 /***************************************************************************
2240  Copy a service structure to another.
2241  If pcopymapDest is NULL then copy all fields
2242 ***************************************************************************/
2243
2244 /**
2245  * Add a parametric option to a parmlist_entry,
2246  * replacing old value, if already present.
2247  */
2248 static void set_param_opt(struct parmlist_entry **opt_list,
2249                           const char *opt_name,
2250                           const char *opt_value,
2251                           unsigned priority)
2252 {
2253         struct parmlist_entry *new_opt, *opt;
2254         bool not_added;
2255
2256         opt = *opt_list;
2257         not_added = true;
2258
2259         /* Traverse destination */
2260         while (opt) {
2261                 /* If we already have same option, override it */
2262                 if (strwicmp(opt->key, opt_name) == 0) {
2263                         if ((opt->priority & FLAG_CMDLINE) &&
2264                             !(priority & FLAG_CMDLINE)) {
2265                                 /* it's been marked as not to be
2266                                    overridden */
2267                                 return;
2268                         }
2269                         string_free(&opt->value);
2270                         TALLOC_FREE(opt->list);
2271                         opt->value = SMB_STRDUP(opt_value);
2272                         opt->priority = priority;
2273                         not_added = false;
2274                         break;
2275                 }
2276                 opt = opt->next;
2277         }
2278         if (not_added) {
2279             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
2280             new_opt->key = SMB_STRDUP(opt_name);
2281             new_opt->value = SMB_STRDUP(opt_value);
2282             new_opt->list = NULL;
2283             new_opt->priority = priority;
2284             DLIST_ADD(*opt_list, new_opt);
2285         }
2286 }
2287
2288 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
2289                          struct bitmap *pcopymapDest)
2290 {
2291         int i;
2292         bool bcopyall = (pcopymapDest == NULL);
2293         struct parmlist_entry *data;
2294
2295         for (i = 0; parm_table[i].label; i++)
2296                 if (parm_table[i].p_class == P_LOCAL &&
2297                     (bcopyall || bitmap_query(pcopymapDest,i))) {
2298                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
2299                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
2300
2301                         switch (parm_table[i].type) {
2302                                 case P_BOOL:
2303                                 case P_BOOLREV:
2304                                         *(bool *)dest_ptr = *(bool *)src_ptr;
2305                                         break;
2306
2307                                 case P_INTEGER:
2308                                 case P_ENUM:
2309                                 case P_OCTAL:
2310                                 case P_BYTES:
2311                                         *(int *)dest_ptr = *(int *)src_ptr;
2312                                         break;
2313
2314                                 case P_CHAR:
2315                                         *(char *)dest_ptr = *(char *)src_ptr;
2316                                         break;
2317
2318                                 case P_STRING:
2319                                         string_set((char **)dest_ptr,
2320                                                    *(char **)src_ptr);
2321                                         break;
2322
2323                                 case P_USTRING:
2324                                 {
2325                                         char *upper_string = strupper_talloc(talloc_tos(), 
2326                                                                              *(char **)src_ptr);
2327                                         string_set((char **)dest_ptr,
2328                                                    upper_string);
2329                                         TALLOC_FREE(upper_string);
2330                                         break;
2331                                 }
2332                                 case P_LIST:
2333                                         TALLOC_FREE(*((char ***)dest_ptr));
2334                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
2335                                                       *(const char ***)src_ptr);
2336                                         break;
2337                                 default:
2338                                         break;
2339                         }
2340                 }
2341
2342         if (bcopyall) {
2343                 init_copymap(pserviceDest);
2344                 if (pserviceSource->copymap)
2345                         bitmap_copy(pserviceDest->copymap,
2346                                     pserviceSource->copymap);
2347         }
2348
2349         data = pserviceSource->param_opt;
2350         while (data) {
2351                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
2352                 data = data->next;
2353         }
2354 }
2355
2356 /***************************************************************************
2357 Check a service for consistency. Return false if the service is in any way
2358 incomplete or faulty, else true.
2359 ***************************************************************************/
2360
2361 bool service_ok(int iService)
2362 {
2363         bool bRetval;
2364
2365         bRetval = true;
2366         if (ServicePtrs[iService]->szService[0] == '\0') {
2367                 DEBUG(0, ("The following message indicates an internal error:\n"));
2368                 DEBUG(0, ("No service name in service entry.\n"));
2369                 bRetval = false;
2370         }
2371
2372         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2373         /* I can't see why you'd want a non-printable printer service...        */
2374         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2375                 if (!ServicePtrs[iService]->bPrint_ok) {
2376                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2377                                ServicePtrs[iService]->szService));
2378                         ServicePtrs[iService]->bPrint_ok = true;
2379                 }
2380                 /* [printers] service must also be non-browsable. */
2381                 if (ServicePtrs[iService]->bBrowseable)
2382                         ServicePtrs[iService]->bBrowseable = false;
2383         }
2384
2385         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2386             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2387             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2388             ) {
2389                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2390                         ServicePtrs[iService]->szService));
2391                 ServicePtrs[iService]->bAvailable = false;
2392         }
2393
2394         /* If a service is flagged unavailable, log the fact at level 1. */
2395         if (!ServicePtrs[iService]->bAvailable)
2396                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2397                           ServicePtrs[iService]->szService));
2398
2399         return (bRetval);
2400 }
2401
2402 static struct smbconf_ctx *lp_smbconf_ctx(void)
2403 {
2404         sbcErr err;
2405         static struct smbconf_ctx *conf_ctx = NULL;
2406
2407         if (conf_ctx == NULL) {
2408                 err = smbconf_init(NULL, &conf_ctx, "registry:");
2409                 if (!SBC_ERROR_IS_OK(err)) {
2410                         DEBUG(1, ("error initializing registry configuration: "
2411                                   "%s\n", sbcErrorString(err)));
2412                         conf_ctx = NULL;
2413                 }
2414         }
2415
2416         return conf_ctx;
2417 }
2418
2419 static bool process_smbconf_service(struct smbconf_service *service)
2420 {
2421         uint32_t count;
2422         bool ret;
2423
2424         if (service == NULL) {
2425                 return false;
2426         }
2427
2428         ret = do_section(service->name, NULL);
2429         if (ret != true) {
2430                 return false;
2431         }
2432         for (count = 0; count < service->num_params; count++) {
2433                 ret = do_parameter(service->param_names[count],
2434                                    service->param_values[count],
2435                                    NULL);
2436                 if (ret != true) {
2437                         return false;
2438                 }
2439         }
2440         if (iServiceIndex >= 0) {
2441                 return service_ok(iServiceIndex);
2442         }
2443         return true;
2444 }
2445
2446 /**
2447  * load a service from registry and activate it
2448  */
2449 bool process_registry_service(const char *service_name)
2450 {
2451         sbcErr err;
2452         struct smbconf_service *service = NULL;
2453         TALLOC_CTX *mem_ctx = talloc_stackframe();
2454         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2455         bool ret = false;
2456
2457         if (conf_ctx == NULL) {
2458                 goto done;
2459         }
2460
2461         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
2462
2463         if (!smbconf_share_exists(conf_ctx, service_name)) {
2464                 /*
2465                  * Registry does not contain data for this service (yet),
2466                  * but make sure lp_load doesn't return false.
2467                  */
2468                 ret = true;
2469                 goto done;
2470         }
2471
2472         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
2473         if (!SBC_ERROR_IS_OK(err)) {
2474                 goto done;
2475         }
2476
2477         ret = process_smbconf_service(service);
2478         if (!ret) {
2479                 goto done;
2480         }
2481
2482         /* store the csn */
2483         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2484
2485 done:
2486         TALLOC_FREE(mem_ctx);
2487         return ret;
2488 }
2489
2490 /*
2491  * process_registry_globals
2492  */
2493 static bool process_registry_globals(void)
2494 {
2495         bool ret;
2496
2497         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
2498
2499         ret = do_parameter("registry shares", "yes", NULL);
2500         if (!ret) {
2501                 return ret;
2502         }
2503
2504         return process_registry_service(GLOBAL_NAME);
2505 }
2506
2507 bool process_registry_shares(void)
2508 {
2509         sbcErr err;
2510         uint32_t count;
2511         struct smbconf_service **service = NULL;
2512         uint32_t num_shares = 0;
2513         TALLOC_CTX *mem_ctx = talloc_stackframe();
2514         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2515         bool ret = false;
2516
2517         if (conf_ctx == NULL) {
2518                 goto done;
2519         }
2520
2521         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
2522         if (!SBC_ERROR_IS_OK(err)) {
2523                 goto done;
2524         }
2525
2526         ret = true;
2527
2528         for (count = 0; count < num_shares; count++) {
2529                 if (strequal(service[count]->name, GLOBAL_NAME)) {
2530                         continue;
2531                 }
2532                 ret = process_smbconf_service(service[count]);
2533                 if (!ret) {
2534                         goto done;
2535                 }
2536         }
2537
2538         /* store the csn */
2539         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
2540
2541 done:
2542         TALLOC_FREE(mem_ctx);
2543         return ret;
2544 }
2545
2546 /**
2547  * reload those shares from registry that are already
2548  * activated in the services array.
2549  */
2550 static bool reload_registry_shares(void)
2551 {
2552         int i;
2553         bool ret = true;
2554
2555         for (i = 0; i < iNumServices; i++) {
2556                 if (!VALID(i)) {
2557                         continue;
2558                 }
2559
2560                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
2561                         continue;
2562                 }
2563
2564                 ret = process_registry_service(ServicePtrs[i]->szService);
2565                 if (!ret) {
2566                         goto done;
2567                 }
2568         }
2569
2570 done:
2571         return ret;
2572 }
2573
2574
2575 #define MAX_INCLUDE_DEPTH 100
2576
2577 static uint8_t include_depth;
2578
2579 static struct file_lists {
2580         struct file_lists *next;
2581         char *name;
2582         char *subfname;
2583         time_t modtime;
2584 } *file_lists = NULL;
2585
2586 /*******************************************************************
2587  Keep a linked list of all config files so we know when one has changed 
2588  it's date and needs to be reloaded.
2589 ********************************************************************/
2590
2591 static void add_to_file_list(const char *fname, const char *subfname)
2592 {
2593         struct file_lists *f = file_lists;
2594
2595         while (f) {
2596                 if (f->name && !strcmp(f->name, fname))
2597                         break;
2598                 f = f->next;
2599         }
2600
2601         if (!f) {
2602                 f = SMB_MALLOC_P(struct file_lists);
2603                 if (!f)
2604                         return;
2605                 f->next = file_lists;
2606                 f->name = SMB_STRDUP(fname);
2607                 if (!f->name) {
2608                         SAFE_FREE(f);
2609                         return;
2610                 }
2611                 f->subfname = SMB_STRDUP(subfname);
2612                 if (!f->subfname) {
2613                         SAFE_FREE(f->name);
2614                         SAFE_FREE(f);
2615                         return;
2616                 }
2617                 file_lists = f;
2618                 f->modtime = file_modtime(subfname);
2619         } else {
2620                 time_t t = file_modtime(subfname);
2621                 if (t)
2622                         f->modtime = t;
2623         }
2624         return;
2625 }
2626
2627 /**
2628  * Free the file lists
2629  */
2630 static void free_file_list(void)
2631 {
2632         struct file_lists *f;
2633         struct file_lists *next;
2634
2635         f = file_lists;
2636         while( f ) {
2637                 next = f->next;
2638                 SAFE_FREE( f->name );
2639                 SAFE_FREE( f->subfname );
2640                 SAFE_FREE( f );
2641                 f = next;
2642         }
2643         file_lists = NULL;
2644 }
2645
2646
2647 /**
2648  * Utility function for outsiders to check if we're running on registry.
2649  */
2650 bool lp_config_backend_is_registry(void)
2651 {
2652         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
2653 }
2654
2655 /**
2656  * Utility function to check if the config backend is FILE.
2657  */
2658 bool lp_config_backend_is_file(void)
2659 {
2660         return (lp_config_backend() == CONFIG_BACKEND_FILE);
2661 }
2662
2663 /*******************************************************************
2664  Check if a config file has changed date.
2665 ********************************************************************/
2666
2667 bool lp_file_list_changed(void)
2668 {
2669         struct file_lists *f = file_lists;
2670
2671         DEBUG(6, ("lp_file_list_changed()\n"));
2672
2673         while (f) {
2674                 time_t mod_time;
2675
2676                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
2677                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
2678
2679                         if (conf_ctx == NULL) {
2680                                 return false;
2681                         }
2682                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
2683                                             NULL))
2684                         {
2685                                 DEBUGADD(6, ("registry config changed\n"));
2686                                 return true;
2687                         }
2688                 } else {
2689                         char *n2 = NULL;
2690                         n2 = talloc_sub_basic(talloc_tos(),
2691                                               get_current_username(),
2692                                               current_user_info.domain,
2693                                               f->name);
2694                         if (!n2) {
2695                                 return false;
2696                         }
2697                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2698                                      f->name, n2, ctime(&f->modtime)));
2699
2700                         mod_time = file_modtime(n2);
2701
2702                         if (mod_time &&
2703                             ((f->modtime != mod_time) ||
2704                              (f->subfname == NULL) ||
2705                              (strcmp(n2, f->subfname) != 0)))
2706                         {
2707                                 DEBUGADD(6,
2708                                          ("file %s modified: %s\n", n2,
2709                                           ctime(&mod_time)));
2710                                 f->modtime = mod_time;
2711                                 SAFE_FREE(f->subfname);
2712                                 f->subfname = SMB_STRDUP(n2);
2713                                 TALLOC_FREE(n2);
2714                                 return true;
2715                         }
2716                         TALLOC_FREE(n2);
2717                 }
2718                 f = f->next;
2719         }
2720         return false;
2721 }
2722
2723
2724 /**
2725  * Initialize iconv conversion descriptors.
2726  *
2727  * This is called the first time it is needed, and also called again
2728  * every time the configuration is reloaded, because the charset or
2729  * codepage might have changed.
2730  **/
2731 static void init_iconv(void)
2732 {
2733         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
2734                                                       lp_unix_charset(),
2735                                                       true, global_iconv_handle);
2736 }
2737
2738 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2739 {
2740         if (strcmp(*ptr, pszParmValue) != 0) {
2741                 string_set(ptr, pszParmValue);
2742                 init_iconv();
2743         }
2744         return true;
2745 }
2746
2747 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2748 {
2749         bool is_utf8 = false;
2750         size_t len = strlen(pszParmValue);
2751
2752         if (len == 4 || len == 5) {
2753                 /* Don't use StrCaseCmp here as we don't want to
2754                    initialize iconv. */
2755                 if ((toupper_m(pszParmValue[0]) == 'U') &&
2756                     (toupper_m(pszParmValue[1]) == 'T') &&
2757                     (toupper_m(pszParmValue[2]) == 'F')) {
2758                         if (len == 4) {
2759                                 if (pszParmValue[3] == '8') {
2760                                         is_utf8 = true;
2761                                 }
2762                         } else {
2763                                 if (pszParmValue[3] == '-' &&
2764                                     pszParmValue[4] == '8') {
2765                                         is_utf8 = true;
2766                                 }
2767                         }
2768                 }
2769         }
2770
2771         if (strcmp(*ptr, pszParmValue) != 0) {
2772                 if (is_utf8) {
2773                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2774                                 "be UTF8, using (default value) %s instead.\n",
2775                                 DEFAULT_DOS_CHARSET));
2776                         pszParmValue = DEFAULT_DOS_CHARSET;
2777                 }
2778                 string_set(ptr, pszParmValue);
2779                 init_iconv();
2780         }
2781         return true;
2782 }
2783
2784 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2785 {
2786         bool ret = true;
2787         char *realm = strupper_talloc(talloc_tos(), pszParmValue);
2788         char *dnsdomain = strlower_talloc(realm, pszParmValue);
2789
2790         ret &= string_set(&Globals.szRealm, pszParmValue);
2791         ret &= string_set(&Globals.szRealm_upper, realm);
2792         ret &= string_set(&Globals.szRealm_lower, dnsdomain);
2793         TALLOC_FREE(realm);
2794
2795         return ret;
2796 }
2797
2798 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2799 {
2800         TALLOC_FREE(Globals.szNetbiosAliases);
2801         Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
2802         return set_netbios_aliases(Globals.szNetbiosAliases);
2803 }
2804
2805 /***************************************************************************
2806  Handle the include operation.
2807 ***************************************************************************/
2808 static bool bAllowIncludeRegistry = true;
2809
2810 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2811 {
2812         char *fname;
2813
2814         if (include_depth >= MAX_INCLUDE_DEPTH) {
2815                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2816                           include_depth));
2817                 return false;
2818         }
2819
2820         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
2821                 if (!bAllowIncludeRegistry) {
2822                         return true;
2823                 }
2824                 if (bInGlobalSection) {
2825                         bool ret;
2826                         include_depth++;
2827                         ret = process_registry_globals();
2828                         include_depth--;
2829                         return ret;
2830                 } else {
2831                         DEBUG(1, ("\"include = registry\" only effective "
2832                                   "in %s section\n", GLOBAL_NAME));
2833                         return false;
2834                 }
2835         }
2836
2837         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
2838                                  current_user_info.domain,
2839                                  pszParmValue);
2840
2841         add_to_file_list(pszParmValue, fname);
2842
2843         string_set(ptr, fname);
2844
2845         if (file_exist(fname)) {
2846                 bool ret;
2847                 include_depth++;
2848                 ret = pm_process(fname, do_section, do_parameter, NULL);
2849                 include_depth--;
2850                 TALLOC_FREE(fname);
2851                 return ret;
2852         }
2853
2854         DEBUG(2, ("Can't find include file %s\n", fname));
2855         TALLOC_FREE(fname);
2856         return true;
2857 }
2858
2859 /***************************************************************************
2860  Handle the interpretation of the copy parameter.
2861 ***************************************************************************/
2862
2863 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2864 {
2865         bool bRetval;
2866         int iTemp;
2867         struct loadparm_service serviceTemp;
2868
2869         string_set(ptr, pszParmValue);
2870
2871         init_service(&serviceTemp);
2872
2873         bRetval = false;
2874
2875         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2876
2877         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2878                 if (iTemp == iServiceIndex) {
2879                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2880                 } else {
2881                         copy_service(ServicePtrs[iServiceIndex],
2882                                      &serviceTemp,
2883                                      ServicePtrs[iServiceIndex]->copymap);
2884                         bRetval = true;
2885                 }
2886         } else {
2887                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2888                 bRetval = false;
2889         }
2890
2891         free_service(&serviceTemp);
2892         return (bRetval);
2893 }
2894
2895 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2896 {
2897         Globals.ldap_debug_level = lp_int(pszParmValue);
2898         init_ldap_debugging();
2899         return true;
2900 }
2901
2902 /***************************************************************************
2903  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
2904  parameters is:
2905
2906  [global]
2907
2908         idmap uid = 1000-1999
2909         idmap gid = 700-899
2910
2911  We only do simple parsing checks here.  The strings are parsed into useful
2912  structures in the idmap daemon code.
2913
2914 ***************************************************************************/
2915
2916 /* Some lp_ routines to return idmap [ug]id information */
2917
2918 static uid_t idmap_uid_low, idmap_uid_high;
2919 static gid_t idmap_gid_low, idmap_gid_high;
2920
2921 bool lp_idmap_uid(uid_t *low, uid_t *high)
2922 {
2923         if (idmap_uid_low == 0 || idmap_uid_high == 0)
2924                 return false;
2925
2926         if (low)
2927                 *low = idmap_uid_low;
2928
2929         if (high)
2930                 *high = idmap_uid_high;
2931
2932         return true;
2933 }
2934
2935 bool lp_idmap_gid(gid_t *low, gid_t *high)
2936 {
2937         if (idmap_gid_low == 0 || idmap_gid_high == 0)
2938                 return false;
2939
2940         if (low)
2941                 *low = idmap_gid_low;
2942
2943         if (high)
2944                 *high = idmap_gid_high;
2945
2946         return true;
2947 }
2948
2949 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2950 {
2951         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
2952
2953         return true;
2954 }
2955
2956 /* Do some simple checks on "idmap [ug]id" parameter values */
2957
2958 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2959 {
2960         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2961
2962         return true;
2963 }
2964
2965 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
2966 {
2967         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
2968
2969         return true;
2970 }
2971
2972 /***************************************************************************
2973  Handle the DEBUG level list.
2974 ***************************************************************************/
2975
2976 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
2977 {
2978         string_set(ptr, pszParmValueIn);
2979         return debug_parse_levels(pszParmValueIn);
2980 }
2981
2982 /***************************************************************************
2983  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2984 ***************************************************************************/
2985
2986 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
2987 {
2988         const char *suffix_string;
2989
2990         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
2991                                         Globals.szLdapSuffix );
2992         if ( !suffix_string ) {
2993                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2994                 return "";
2995         }
2996
2997         return suffix_string;
2998 }
2999
3000 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
3001 {
3002         if (Globals.szLdapMachineSuffix[0])
3003                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
3004
3005         return lp_string(ctx, Globals.szLdapSuffix);
3006 }
3007
3008 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
3009 {
3010         if (Globals.szLdapUserSuffix[0])
3011                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
3012
3013         return lp_string(ctx, Globals.szLdapSuffix);
3014 }
3015
3016 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
3017 {
3018         if (Globals.szLdapGroupSuffix[0])
3019                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
3020
3021         return lp_string(ctx, Globals.szLdapSuffix);
3022 }
3023
3024 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
3025 {
3026         if (Globals.szLdapIdmapSuffix[0])
3027                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
3028
3029         return lp_string(ctx, Globals.szLdapSuffix);
3030 }
3031
3032 /****************************************************************************
3033  set the value for a P_ENUM
3034  ***************************************************************************/
3035
3036 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3037                               int *ptr )
3038 {
3039         int i;
3040
3041         for (i = 0; parm->enum_list[i].name; i++) {
3042                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3043                         *ptr = parm->enum_list[i].value;
3044                         return;
3045                 }
3046         }
3047         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3048                   pszParmValue, parm->label));
3049 }
3050
3051 /***************************************************************************
3052 ***************************************************************************/
3053
3054 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
3055 {
3056         static int parm_num = -1;
3057         struct loadparm_service *s;
3058
3059         if ( parm_num == -1 )
3060                 parm_num = map_parameter( "printing" );
3061
3062         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3063
3064         if ( snum < 0 )
3065                 s = &sDefault;
3066         else
3067                 s = ServicePtrs[snum];
3068
3069         init_printer_values( s );
3070
3071         return true;
3072 }
3073
3074
3075 /***************************************************************************
3076  Initialise a copymap.
3077 ***************************************************************************/
3078
3079 static void init_copymap(struct loadparm_service *pservice)
3080 {
3081         int i;
3082
3083         TALLOC_FREE(pservice->copymap);
3084
3085         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
3086         if (!pservice->copymap)
3087                 DEBUG(0,
3088                       ("Couldn't allocate copymap!! (size %d)\n",
3089                        (int)NUMPARAMETERS));
3090         else
3091                 for (i = 0; i < NUMPARAMETERS; i++)
3092                         bitmap_set(pservice->copymap, i);
3093 }
3094
3095 /**
3096   return the parameter pointer for a parameter
3097 */
3098 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
3099 {
3100         if (service == NULL) {
3101                 if (parm->p_class == P_LOCAL)
3102                         return (void *)(((char *)&sDefault)+parm->offset);
3103                 else if (parm->p_class == P_GLOBAL)
3104                         return (void *)(((char *)&Globals)+parm->offset);
3105                 else return NULL;
3106         } else {
3107                 return (void *)(((char *)service) + parm->offset);
3108         }
3109 }
3110
3111 /***************************************************************************
3112  Return the local pointer to a parameter given the service number and parameter
3113 ***************************************************************************/
3114
3115 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
3116 {
3117         return lp_parm_ptr(ServicePtrs[snum], parm);
3118 }
3119
3120 /***************************************************************************
3121  Process a parameter for a particular service number. If snum < 0
3122  then assume we are in the globals.
3123 ***************************************************************************/
3124
3125 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3126 {
3127         int parmnum, i;
3128         void *parm_ptr = NULL;  /* where we are going to store the result */
3129         struct parmlist_entry **opt_list;
3130
3131         parmnum = map_parameter(pszParmName);
3132
3133         if (parmnum < 0) {
3134                 if (strchr(pszParmName, ':') == NULL) {
3135                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3136                                   pszParmName));
3137                         return true;
3138                 }
3139
3140                 /*
3141                  * We've got a parametric option
3142                  */
3143
3144                 opt_list = (snum < 0)
3145                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
3146                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
3147
3148                 return true;
3149         }
3150
3151         /* if it's already been set by the command line, then we don't
3152            override here */
3153         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
3154                 return true;
3155         }
3156
3157         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3158                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3159                           pszParmName));
3160         }
3161
3162         /* we might point at a service, the default service or a global */
3163         if (snum < 0) {
3164                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
3165         } else {
3166                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3167                         DEBUG(0,
3168                               ("Global parameter %s found in service section!\n",
3169                                pszParmName));
3170                         return true;
3171                 }
3172                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
3173         }
3174
3175         if (snum >= 0) {
3176                 if (!ServicePtrs[snum]->copymap)
3177                         init_copymap(ServicePtrs[snum]);
3178
3179                 /* this handles the aliases - set the copymap for other entries with
3180                    the same data pointer */
3181                 for (i = 0; parm_table[i].label; i++) {
3182                         if ((parm_table[i].offset == parm_table[parmnum].offset)
3183                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
3184                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3185                         }
3186                 }
3187         }
3188
3189         /* if it is a special case then go ahead */
3190         if (parm_table[parmnum].special) {
3191                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
3192                                                    (char **)parm_ptr);
3193         }
3194
3195         /* now switch on the type of variable it is */
3196         switch (parm_table[parmnum].type)
3197         {
3198                 case P_BOOL:
3199                         *(bool *)parm_ptr = lp_bool(pszParmValue);
3200                         break;
3201
3202                 case P_BOOLREV:
3203                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
3204                         break;
3205
3206                 case P_INTEGER:
3207                         *(int *)parm_ptr = lp_int(pszParmValue);
3208                         break;
3209
3210                 case P_CHAR:
3211                         *(char *)parm_ptr = *pszParmValue;
3212                         break;
3213
3214                 case P_OCTAL:
3215                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3216                         if ( i != 1 ) {
3217                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3218                         }
3219                         break;
3220
3221                 case P_BYTES:
3222                 {
3223                         uint64_t val;
3224                         if (conv_str_size_error(pszParmValue, &val)) {
3225                                 if (val <= INT_MAX) {
3226                                         *(int *)parm_ptr = (int)val;
3227                                         break;
3228                                 }
3229                         }
3230
3231                         DEBUG(0,("lp_do_parameter(%s): value is not "
3232                             "a valid size specifier!\n", pszParmValue));
3233                         return false;
3234                 }
3235
3236                 case P_LIST:
3237                 case P_CMDLIST:
3238                         TALLOC_FREE(*((char ***)parm_ptr));
3239                         *(char ***)parm_ptr = str_list_make_v3(
3240                                 NULL, pszParmValue, NULL);
3241                         break;
3242
3243                 case P_STRING:
3244                         string_set((char **)parm_ptr, pszParmValue);
3245                         break;
3246
3247                 case P_USTRING:
3248                 {
3249                         char *upper_string = strupper_talloc(talloc_tos(), 
3250                                                              pszParmValue);
3251                         string_set((char **)parm_ptr, upper_string);
3252                         TALLOC_FREE(upper_string);
3253                         break;
3254                 }
3255                 case P_ENUM:
3256                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3257                         break;
3258                 case P_SEP:
3259                         break;
3260         }
3261
3262         return true;
3263 }
3264
3265 /***************************************************************************
3266 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3267 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3268 ***************************************************************************/
3269
3270 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
3271 {
3272         int parmnum, i;
3273         parmnum = map_parameter(pszParmName);
3274         if (parmnum >= 0) {
3275                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
3276                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
3277                         return false;
3278                 }
3279                 parm_table[parmnum].flags |= FLAG_CMDLINE;
3280
3281                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
3282                  * be grouped in the table, so we don't have to search the
3283                  * whole table */
3284                 for (i=parmnum-1;
3285                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
3286                              && parm_table[i].p_class == parm_table[parmnum].p_class;
3287                      i--) {
3288                         parm_table[i].flags |= FLAG_CMDLINE;
3289                 }
3290                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
3291                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
3292                         parm_table[i].flags |= FLAG_CMDLINE;
3293                 }
3294
3295                 if (store_values) {
3296                         store_lp_set_cmdline(pszParmName, pszParmValue);
3297                 }
3298                 return true;
3299         }
3300
3301         /* it might be parametric */
3302         if (strchr(pszParmName, ':') != NULL) {
3303                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
3304                 if (store_values) {
3305                         store_lp_set_cmdline(pszParmName, pszParmValue);
3306                 }
3307                 return true;
3308         }
3309
3310         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
3311         return true;
3312 }
3313
3314 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
3315 {
3316         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
3317 }
3318
3319 /***************************************************************************
3320  Process a parameter.
3321 ***************************************************************************/
3322
3323 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
3324                          void *userdata)
3325 {
3326         if (!bInGlobalSection && bGlobalOnly)
3327                 return true;
3328
3329         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3330
3331         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3332                                 pszParmName, pszParmValue));
3333 }
3334
3335 /*
3336   set a option from the commandline in 'a=b' format. Use to support --option
3337 */
3338 bool lp_set_option(const char *option)
3339 {
3340         char *p, *s;
3341         bool ret;
3342
3343         s = talloc_strdup(NULL, option);
3344         if (!s) {
3345                 return false;
3346         }
3347
3348         p = strchr(s, '=');
3349         if (!p) {
3350                 talloc_free(s);
3351                 return false;
3352         }
3353
3354         *p = 0;
3355
3356         /* skip white spaces after the = sign */
3357         do {
3358                 p++;
3359         } while (*p == ' ');
3360
3361         ret = lp_set_cmdline(s, p);
3362         talloc_free(s);
3363         return ret;
3364 }
3365
3366 /**************************************************************************
3367  Print a parameter of the specified type.
3368 ***************************************************************************/
3369
3370 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3371 {
3372         /* For the seperation of lists values that we print below */
3373         const char *list_sep = ", ";
3374         int i;
3375         switch (p->type)
3376         {
3377                 case P_ENUM:
3378                         for (i = 0; p->enum_list[i].name; i++) {
3379                                 if (*(int *)ptr == p->enum_list[i].value) {
3380                                         fprintf(f, "%s",
3381                                                 p->enum_list[i].name);
3382                                         break;
3383                                 }
3384                         }
3385                         break;
3386
3387                 case P_BOOL:
3388                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
3389                         break;
3390
3391                 case P_BOOLREV:
3392                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
3393                         break;
3394
3395                 case P_INTEGER:
3396                 case P_BYTES:
3397                         fprintf(f, "%d", *(int *)ptr);
3398                         break;
3399
3400                 case P_CHAR:
3401                         fprintf(f, "%c", *(char *)ptr);
3402                         break;
3403
3404                 case P_OCTAL: {
3405                         int val = *(int *)ptr; 
3406                         if (val == -1) {
3407                                 fprintf(f, "-1");
3408                         } else {
3409                                 fprintf(f, "0%o", val);
3410                         }
3411                         break;
3412                 }
3413
3414                 case P_CMDLIST:
3415                         list_sep = " ";
3416                         /* fall through */
3417                 case P_LIST:
3418                         if ((char ***)ptr && *(char ***)ptr) {
3419                                 char **list = *(char ***)ptr;
3420                                 for (; *list; list++) {
3421                                         /* surround strings with whitespace in double quotes */
3422                                         if (*(list+1) == NULL) {
3423                                                 /* last item, no extra separator */
3424                                                 list_sep = "";
3425                                         }
3426                                         if ( strchr_m( *list, ' ' ) ) {
3427                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
3428                                         } else {
3429                                                 fprintf(f, "%s%s", *list, list_sep);
3430                                         }
3431                                 }
3432                         }
3433                         break;
3434
3435                 case P_STRING:
3436                 case P_USTRING:
3437                         if (*(char **)ptr) {
3438                                 fprintf(f, "%s", *(char **)ptr);
3439                         }
3440                         break;
3441                 case P_SEP:
3442                         break;
3443         }
3444 }
3445
3446 /***************************************************************************
3447  Check if two parameters are equal.
3448 ***************************************************************************/
3449
3450 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
3451 {
3452         switch (type) {
3453                 case P_BOOL:
3454                 case P_BOOLREV:
3455                         return (*((bool *)ptr1) == *((bool *)ptr2));
3456
3457                 case P_INTEGER:
3458                 case P_ENUM:
3459                 case P_OCTAL:
3460                 case P_BYTES:
3461                         return (*((int *)ptr1) == *((int *)ptr2));
3462
3463                 case P_CHAR:
3464                         return (*((char *)ptr1) == *((char *)ptr2));
3465
3466                 case P_LIST:
3467                 case P_CMDLIST:
3468                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
3469
3470                 case P_STRING:
3471                 case P_USTRING:
3472                 {
3473                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3474                         if (p1 && !*p1)
3475                                 p1 = NULL;
3476                         if (p2 && !*p2