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