param: Sort global param functions macros to ease the s3/s4 merge
[gd/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 "printing.h"
60 #include "lib/smbconf/smbconf.h"
61 #include "lib/smbconf/smbconf_init.h"
62 #include "lib/param/loadparm.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 #include "../source4/dns_server/dns_update.h"
72
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
75 #endif
76
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
79 #endif
80
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
83 #endif
84
85 bool bLoaded = false;
86
87 extern userdom_struct current_user_info;
88
89 /* the special value for the include parameter
90  * to be interpreted not as a file name but to
91  * trigger loading of the global smb.conf options
92  * from registry. */
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
95 #endif
96
97 static bool in_client = false;          /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn;
99
100 #define CONFIG_BACKEND_FILE 0
101 #define CONFIG_BACKEND_REGISTRY 1
102
103 static int config_backend = CONFIG_BACKEND_FILE;
104
105 /* some helpful bits */
106 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
107 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
108
109 #define USERSHARE_VALID 1
110 #define USERSHARE_PENDING_DELETE 2
111
112 static bool defaults_saved = false;
113
114 #define LOADPARM_EXTRA_GLOBALS \
115         struct parmlist_entry *param_opt;                               \
116         char *szRealm;                                                  \
117         char *szLogLevel;                                               \
118         int iminreceivefile;                                            \
119         char *szPrintcapname;                                           \
120         int CupsEncrypt;                                                \
121         int  iPreferredMaster;                                          \
122         int iDomainMaster;                                              \
123         char *szLdapMachineSuffix;                                      \
124         char *szLdapUserSuffix;                                         \
125         char *szLdapIdmapSuffix;                                        \
126         char *szLdapGroupSuffix;                                        \
127         char *szStateDir;                                               \
128         char *szCacheDir;                                               \
129         char *szSocketAddress;                                          \
130         char *szUsershareTemplateShare;                                 \
131         char *szIdmapUID;                                               \
132         char *szIdmapGID;                                               \
133         int winbindMaxDomainConnections;                                \
134         int ismb2_max_credits;
135
136 #include "param/param_global.h"
137
138 static struct loadparm_global Globals;
139
140 /* This is a default service used to prime a services structure */
141 static struct loadparm_service sDefault =
142 {
143         .valid = true,
144         .autoloaded = false,
145         .usershare = 0,
146         .usershare_last_mod = {0, 0},
147         .szService = NULL,
148         .szPath = NULL,
149         .szUsername = NULL,
150         .szInvalidUsers = NULL,
151         .szValidUsers = NULL,
152         .szAdminUsers = NULL,
153         .szCopy = NULL,
154         .szInclude = NULL,
155         .szPreExec = NULL,
156         .szPostExec = NULL,
157         .szRootPreExec = NULL,
158         .szRootPostExec = NULL,
159         .szCupsOptions = NULL,
160         .szPrintcommand = NULL,
161         .szLpqcommand = NULL,
162         .szLprmcommand = NULL,
163         .szLppausecommand = NULL,
164         .szLpresumecommand = NULL,
165         .szQueuepausecommand = NULL,
166         .szQueueresumecommand = NULL,
167         .szPrintername = NULL,
168         .szPrintjobUsername = NULL,
169         .szDontdescend = NULL,
170         .szHostsallow = NULL,
171         .szHostsdeny = NULL,
172         .szMagicScript = NULL,
173         .szMagicOutput = NULL,
174         .szVetoFiles = NULL,
175         .szHideFiles = NULL,
176         .szVetoOplockFiles = NULL,
177         .comment = NULL,
178         .force_user = NULL,
179         .force_group = NULL,
180         .readlist = NULL,
181         .writelist = NULL,
182         .printer_admin = NULL,
183         .volume = NULL,
184         .fstype = NULL,
185         .szVfsObjects = NULL,
186         .szMSDfsProxy = NULL,
187         .szAioWriteBehind = NULL,
188         .szDfree = NULL,
189         .iMinPrintSpace = 0,
190         .iMaxPrintJobs = 1000,
191         .iMaxReportedPrintJobs = 0,
192         .iWriteCacheSize = 0,
193         .iCreate_mask = 0744,
194         .iCreate_force_mode = 0,
195         .iSecurity_mask = 0777,
196         .iSecurity_force_mode = 0,
197         .iDir_mask = 0755,
198         .iDir_force_mode = 0,
199         .iDir_Security_mask = 0777,
200         .iDir_Security_force_mode = 0,
201         .iMaxConnections = 0,
202         .iDefaultCase = CASE_LOWER,
203         .iPrinting = DEFAULT_PRINTING,
204         .iOplockContentionLimit = 2,
205         .iCSCPolicy = 0,
206         .iBlock_size = 1024,
207         .iDfreeCacheTime = 0,
208         .bPreexecClose = false,
209         .bRootpreexecClose = false,
210         .iCaseSensitive = Auto,
211         .bCasePreserve = true,
212         .bShortCasePreserve = true,
213         .bHideDotFiles = true,
214         .bHideSpecialFiles = false,
215         .bHideUnReadable = false,
216         .bHideUnWriteableFiles = false,
217         .bBrowseable = true,
218         .bAccessBasedShareEnum = false,
219         .bAvailable = true,
220         .bRead_only = true,
221         .bNo_set_dir = true,
222         .bGuest_only = false,
223         .bAdministrative_share = false,
224         .bGuest_ok = false,
225         .bPrint_ok = false,
226         .bPrintNotifyBackchannel = true,
227         .bMap_system = false,
228         .bMap_hidden = false,
229         .bMap_archive = true,
230         .bStoreDosAttributes = false,
231         .bDmapiSupport = false,
232         .bLocking = true,
233         .iStrictLocking = Auto,
234         .bPosixLocking = true,
235         .bShareModes = true,
236         .bOpLocks = true,
237         .bKernelOplocks = false,
238         .bLevel2OpLocks = true,
239         .bOnlyUser = false,
240         .bMangledNames = true,
241         .bWidelinks = false,
242         .bSymlinks = true,
243         .bSyncAlways = false,
244         .bStrictAllocate = false,
245         .bStrictSync = false,
246         .magic_char = '~',
247         .copymap = NULL,
248         .bDeleteReadonly = false,
249         .bFakeOplocks = false,
250         .bDeleteVetoFiles = false,
251         .bDosFilemode = false,
252         .bDosFiletimes = true,
253         .bDosFiletimeResolution = false,
254         .bFakeDirCreateTimes = false,
255         .bBlockingLocks = true,
256         .bInheritPerms = false,
257         .bInheritACLS = false,
258         .bInheritOwner = false,
259         .bMSDfsRoot = false,
260         .bUseClientDriver = false,
261         .bDefaultDevmode = true,
262         .bForcePrintername = false,
263         .bNTAclSupport = true,
264         .bForceUnknownAclUser = false,
265         .bUseSendfile = false,
266         .bProfileAcls = false,
267         .bMap_acl_inherit = false,
268         .bAfs_Share = false,
269         .bEASupport = false,
270         .bAclCheckPermissions = true,
271         .bAclMapFullControl = true,
272         .bAclGroupControl = false,
273         .bChangeNotify = true,
274         .bKernelChangeNotify = true,
275         .iallocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
276         .iAioReadSize = 0,
277         .iAioWriteSize = 0,
278         .iMap_readonly = MAP_READONLY_YES,
279 #ifdef BROKEN_DIRECTORY_HANDLING
280         .iDirectoryNameCacheSize = 0,
281 #else
282         .iDirectoryNameCacheSize = 100,
283 #endif
284         .ismb_encrypt = Auto,
285         .param_opt = NULL,
286         .dummy = ""
287 };
288
289 /* local variables */
290 static struct loadparm_service **ServicePtrs = NULL;
291 static int iNumServices = 0;
292 static int iServiceIndex = 0;
293 static struct db_context *ServiceHash;
294 static int *invalid_services = NULL;
295 static int num_invalid_services = 0;
296 static bool bInGlobalSection = true;
297 static bool bGlobalOnly = false;
298
299 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
300
301 /* prototypes for the special type handlers */
302 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
303 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
304 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
305 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
306 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
307 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
308 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
309 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
310 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
311 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr );
312 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
313 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr);
314
315 static void set_allowed_client_auth(void);
316
317 static void add_to_file_list(const char *fname, const char *subfname);
318 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values);
319 static void free_param_opts(struct parmlist_entry **popts);
320
321 #include "lib/param/param_enums.c"
322
323 static const struct enum_list enum_printing[] = {
324         {PRINT_SYSV, "sysv"},
325         {PRINT_AIX, "aix"},
326         {PRINT_HPUX, "hpux"},
327         {PRINT_BSD, "bsd"},
328         {PRINT_QNX, "qnx"},
329         {PRINT_PLP, "plp"},
330         {PRINT_LPRNG, "lprng"},
331         {PRINT_CUPS, "cups"},
332         {PRINT_IPRINT, "iprint"},
333         {PRINT_LPRNT, "nt"},
334         {PRINT_LPROS2, "os2"},
335 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
336         {PRINT_TEST, "test"},
337         {PRINT_VLP, "vlp"},
338 #endif /* DEVELOPER */
339         {-1, NULL}
340 };
341
342 static const struct enum_list enum_ldap_sasl_wrapping[] = {
343         {0, "plain"},
344         {ADS_AUTH_SASL_SIGN, "sign"},
345         {ADS_AUTH_SASL_SEAL, "seal"},
346         {-1, NULL}
347 };
348
349 static const struct enum_list enum_ldap_ssl[] = {
350         {LDAP_SSL_OFF, "no"},
351         {LDAP_SSL_OFF, "off"},
352         {LDAP_SSL_START_TLS, "start tls"},
353         {LDAP_SSL_START_TLS, "start_tls"},
354         {-1, NULL}
355 };
356
357 /* LDAP Dereferencing Alias types */
358 #define SAMBA_LDAP_DEREF_NEVER          0
359 #define SAMBA_LDAP_DEREF_SEARCHING      1
360 #define SAMBA_LDAP_DEREF_FINDING        2
361 #define SAMBA_LDAP_DEREF_ALWAYS         3
362
363 static const struct enum_list enum_ldap_deref[] = {
364         {SAMBA_LDAP_DEREF_NEVER, "never"},
365         {SAMBA_LDAP_DEREF_SEARCHING, "searching"},
366         {SAMBA_LDAP_DEREF_FINDING, "finding"},
367         {SAMBA_LDAP_DEREF_ALWAYS, "always"},
368         {-1, "auto"}
369 };
370
371 static const struct enum_list enum_ldap_passwd_sync[] = {
372         {LDAP_PASSWD_SYNC_OFF, "no"},
373         {LDAP_PASSWD_SYNC_OFF, "off"},
374         {LDAP_PASSWD_SYNC_ON, "yes"},
375         {LDAP_PASSWD_SYNC_ON, "on"},
376         {LDAP_PASSWD_SYNC_ONLY, "only"},
377         {-1, NULL}
378 };
379
380 static const struct enum_list enum_map_readonly[] = {
381         {MAP_READONLY_NO, "no"},
382         {MAP_READONLY_NO, "false"},
383         {MAP_READONLY_NO, "0"},
384         {MAP_READONLY_YES, "yes"},
385         {MAP_READONLY_YES, "true"},
386         {MAP_READONLY_YES, "1"},
387         {MAP_READONLY_PERMISSIONS, "permissions"},
388         {MAP_READONLY_PERMISSIONS, "perms"},
389         {-1, NULL}
390 };
391
392 static const struct enum_list enum_case[] = {
393         {CASE_LOWER, "lower"},
394         {CASE_UPPER, "upper"},
395         {-1, NULL}
396 };
397
398
399 /* ACL compatibility options. */
400 static const struct enum_list enum_acl_compat_vals[] = {
401     { ACL_COMPAT_AUTO, "auto" },
402     { ACL_COMPAT_WINNT, "winnt" },
403     { ACL_COMPAT_WIN2K, "win2k" },
404     { -1, NULL}
405 };
406
407 /* 
408    Do you want session setups at user level security with a invalid
409    password to be rejected or allowed in as guest? WinNT rejects them
410    but it can be a pain as it means "net view" needs to use a password
411
412    You have 3 choices in the setting of map_to_guest:
413
414    "Never" means session setups with an invalid password
415    are rejected. This is the default.
416
417    "Bad User" means session setups with an invalid password
418    are rejected, unless the username does not exist, in which case it
419    is treated as a guest login
420
421    "Bad Password" means session setups with an invalid password
422    are treated as a guest login
423
424    Note that map_to_guest only has an effect in user or server
425    level security.
426 */
427
428 static const struct enum_list enum_map_to_guest[] = {
429         {NEVER_MAP_TO_GUEST, "Never"},
430         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
431         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
432         {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
433         {-1, NULL}
434 };
435
436 /* Config backend options */
437
438 static const struct enum_list enum_config_backend[] = {
439         {CONFIG_BACKEND_FILE, "file"},
440         {CONFIG_BACKEND_REGISTRY, "registry"},
441         {-1, NULL}
442 };
443
444 /* ADS kerberos ticket verification options */
445
446 static const struct enum_list enum_kerberos_method[] = {
447         {KERBEROS_VERIFY_SECRETS, "default"},
448         {KERBEROS_VERIFY_SECRETS, "secrets only"},
449         {KERBEROS_VERIFY_SYSTEM_KEYTAB, "system keytab"},
450         {KERBEROS_VERIFY_DEDICATED_KEYTAB, "dedicated keytab"},
451         {KERBEROS_VERIFY_SECRETS_AND_KEYTAB, "secrets and keytab"},
452         {-1, NULL}
453 };
454
455 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
456  *
457  * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit
458  * screen in SWAT. This is used to exclude parameters as well as to squash all
459  * parameters that have been duplicated by pseudonyms.
460  *
461  * NOTE: To display a parameter in BASIC view set FLAG_BASIC
462  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
463  *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
464  *        respective views.
465  *
466  * NOTE2: Handling of duplicated (synonym) parameters:
467  *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
468  *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
469  *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
470  *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
471  */
472
473 #define GLOBAL_VAR(name) offsetof(struct loadparm_global, name)
474 #define LOCAL_VAR(name) offsetof(struct loadparm_service, name)
475
476 static struct parm_struct parm_table[] = {
477         {N_("Base Options"), P_SEP, P_SEPARATOR},
478
479         {
480                 .label          = "dos charset",
481                 .type           = P_STRING,
482                 .p_class        = P_GLOBAL,
483                 .offset         = GLOBAL_VAR(dos_charset),
484                 .special        = handle_dos_charset,
485                 .enum_list      = NULL,
486                 .flags          = FLAG_ADVANCED
487         },
488         {
489                 .label          = "unix charset",
490                 .type           = P_STRING,
491                 .p_class        = P_GLOBAL,
492                 .offset         = GLOBAL_VAR(unix_charset),
493                 .special        = handle_charset,
494                 .enum_list      = NULL,
495                 .flags          = FLAG_ADVANCED
496         },
497         {
498                 .label          = "comment",
499                 .type           = P_STRING,
500                 .p_class        = P_LOCAL,
501                 .offset         = LOCAL_VAR(comment),
502                 .special        = NULL,
503                 .enum_list      = NULL,
504                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT
505         },
506         {
507                 .label          = "path",
508                 .type           = P_STRING,
509                 .p_class        = P_LOCAL,
510                 .offset         = LOCAL_VAR(szPath),
511                 .special        = NULL,
512                 .enum_list      = NULL,
513                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
514         },
515         {
516                 .label          = "directory",
517                 .type           = P_STRING,
518                 .p_class        = P_LOCAL,
519                 .offset         = LOCAL_VAR(szPath),
520                 .special        = NULL,
521                 .enum_list      = NULL,
522                 .flags          = FLAG_HIDE,
523         },
524         {
525                 .label          = "workgroup",
526                 .type           = P_USTRING,
527                 .p_class        = P_GLOBAL,
528                 .offset         = GLOBAL_VAR(szWorkgroup),
529                 .special        = NULL,
530                 .enum_list      = NULL,
531                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
532         },
533         {
534                 .label          = "realm",
535                 .type           = P_STRING,
536                 .p_class        = P_GLOBAL,
537                 .offset         = GLOBAL_VAR(szRealm),
538                 .special        = handle_realm,
539                 .enum_list      = NULL,
540                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
541         },
542         {
543                 .label          = "netbios name",
544                 .type           = P_USTRING,
545                 .p_class        = P_GLOBAL,
546                 .offset         = GLOBAL_VAR(szNetbiosName),
547                 .special        = NULL,
548                 .enum_list      = NULL,
549                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
550         },
551         {
552                 .label          = "netbios aliases",
553                 .type           = P_LIST,
554                 .p_class        = P_GLOBAL,
555                 .offset         = GLOBAL_VAR(szNetbiosAliases),
556                 .special        = handle_netbios_aliases,
557                 .enum_list      = NULL,
558                 .flags          = FLAG_ADVANCED,
559         },
560         {
561                 .label          = "netbios scope",
562                 .type           = P_USTRING,
563                 .p_class        = P_GLOBAL,
564                 .offset         = GLOBAL_VAR(szNetbiosScope),
565                 .special        = NULL,
566                 .enum_list      = NULL,
567                 .flags          = FLAG_ADVANCED,
568         },
569         {
570                 .label          = "server string",
571                 .type           = P_STRING,
572                 .p_class        = P_GLOBAL,
573                 .offset         = GLOBAL_VAR(szServerString),
574                 .special        = NULL,
575                 .enum_list      = NULL,
576                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
577         },
578         {
579                 .label          = "interfaces",
580                 .type           = P_LIST,
581                 .p_class        = P_GLOBAL,
582                 .offset         = GLOBAL_VAR(szInterfaces),
583                 .special        = NULL,
584                 .enum_list      = NULL,
585                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
586         },
587         {
588                 .label          = "bind interfaces only",
589                 .type           = P_BOOL,
590                 .p_class        = P_GLOBAL,
591                 .offset         = GLOBAL_VAR(bBindInterfacesOnly),
592                 .special        = NULL,
593                 .enum_list      = NULL,
594                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
595         },
596         {
597                 .label          = "config backend",
598                 .type           = P_ENUM,
599                 .p_class        = P_GLOBAL,
600                 .offset         = GLOBAL_VAR(ConfigBackend),
601                 .special        = NULL,
602                 .enum_list      = enum_config_backend,
603                 .flags          = FLAG_HIDE|FLAG_ADVANCED|FLAG_META,
604         },
605         {
606                 .label          = "server role",
607                 .type           = P_ENUM,
608                 .p_class        = P_GLOBAL,
609                 .offset         = GLOBAL_VAR(ServerRole),
610                 .special        = NULL,
611                 .enum_list      = enum_server_role,
612                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
613         },
614
615         {N_("Security Options"), P_SEP, P_SEPARATOR},
616
617         {
618                 .label          = "security",
619                 .type           = P_ENUM,
620                 .p_class        = P_GLOBAL,
621                 .offset         = GLOBAL_VAR(security),
622                 .special        = NULL,
623                 .enum_list      = enum_security,
624                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
625         },
626         {
627                 .label          = "auth methods",
628                 .type           = P_LIST,
629                 .p_class        = P_GLOBAL,
630                 .offset         = GLOBAL_VAR(AuthMethods),
631                 .special        = NULL,
632                 .enum_list      = NULL,
633                 .flags          = FLAG_ADVANCED,
634         },
635         {
636                 .label          = "encrypt passwords",
637                 .type           = P_BOOL,
638                 .p_class        = P_GLOBAL,
639                 .offset         = GLOBAL_VAR(bEncryptPasswords),
640                 .special        = NULL,
641                 .enum_list      = NULL,
642                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
643         },
644         {
645                 .label          = "client schannel",
646                 .type           = P_ENUM,
647                 .p_class        = P_GLOBAL,
648                 .offset         = GLOBAL_VAR(clientSchannel),
649                 .special        = NULL,
650                 .enum_list      = enum_bool_auto,
651                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
652         },
653         {
654                 .label          = "server schannel",
655                 .type           = P_ENUM,
656                 .p_class        = P_GLOBAL,
657                 .offset         = GLOBAL_VAR(serverSchannel),
658                 .special        = NULL,
659                 .enum_list      = enum_bool_auto,
660                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
661         },
662         {
663                 .label          = "allow trusted domains",
664                 .type           = P_BOOL,
665                 .p_class        = P_GLOBAL,
666                 .offset         = GLOBAL_VAR(bAllowTrustedDomains),
667                 .special        = NULL,
668                 .enum_list      = NULL,
669                 .flags          = FLAG_ADVANCED,
670         },
671         {
672                 .label          = "map to guest",
673                 .type           = P_ENUM,
674                 .p_class        = P_GLOBAL,
675                 .offset         = GLOBAL_VAR(map_to_guest),
676                 .special        = NULL,
677                 .enum_list      = enum_map_to_guest,
678                 .flags          = FLAG_ADVANCED,
679         },
680         {
681                 .label          = "null passwords",
682                 .type           = P_BOOL,
683                 .p_class        = P_GLOBAL,
684                 .offset         = GLOBAL_VAR(bNullPasswords),
685                 .special        = NULL,
686                 .enum_list      = NULL,
687                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
688         },
689         {
690                 .label          = "obey pam restrictions",
691                 .type           = P_BOOL,
692                 .p_class        = P_GLOBAL,
693                 .offset         = GLOBAL_VAR(bObeyPamRestrictions),
694                 .special        = NULL,
695                 .enum_list      = NULL,
696                 .flags          = FLAG_ADVANCED,
697         },
698         {
699                 .label          = "password server",
700                 .type           = P_STRING,
701                 .p_class        = P_GLOBAL,
702                 .offset         = GLOBAL_VAR(szPasswordServer),
703                 .special        = NULL,
704                 .enum_list      = NULL,
705                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
706         },
707         {
708                 .label          = "smb passwd file",
709                 .type           = P_STRING,
710                 .p_class        = P_GLOBAL,
711                 .offset         = GLOBAL_VAR(szSMBPasswdFile),
712                 .special        = NULL,
713                 .enum_list      = NULL,
714                 .flags          = FLAG_ADVANCED,
715         },
716         {
717                 .label          = "private dir",
718                 .type           = P_STRING,
719                 .p_class        = P_GLOBAL,
720                 .offset         = GLOBAL_VAR(szPrivateDir),
721                 .special        = NULL,
722                 .enum_list      = NULL,
723                 .flags          = FLAG_ADVANCED,
724         },
725         {
726                 .label          = "private directory",
727                 .type           = P_STRING,
728                 .p_class        = P_GLOBAL,
729                 .offset         = GLOBAL_VAR(szPrivateDir),
730                 .special        = NULL,
731                 .enum_list      = NULL,
732                 .flags          = FLAG_HIDE,
733         },
734         {
735                 .label          = "passdb backend",
736                 .type           = P_STRING,
737                 .p_class        = P_GLOBAL,
738                 .offset         = GLOBAL_VAR(szPassdbBackend),
739                 .special        = NULL,
740                 .enum_list      = NULL,
741                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
742         },
743         {
744                 .label          = "algorithmic rid base",
745                 .type           = P_INTEGER,
746                 .p_class        = P_GLOBAL,
747                 .offset         = GLOBAL_VAR(AlgorithmicRidBase),
748                 .special        = NULL,
749                 .enum_list      = NULL,
750                 .flags          = FLAG_ADVANCED,
751         },
752         {
753                 .label          = "root directory",
754                 .type           = P_STRING,
755                 .p_class        = P_GLOBAL,
756                 .offset         = GLOBAL_VAR(szRootdir),
757                 .special        = NULL,
758                 .enum_list      = NULL,
759                 .flags          = FLAG_ADVANCED,
760         },
761         {
762                 .label          = "root dir",
763                 .type           = P_STRING,
764                 .p_class        = P_GLOBAL,
765                 .offset         = GLOBAL_VAR(szRootdir),
766                 .special        = NULL,
767                 .enum_list      = NULL,
768                 .flags          = FLAG_HIDE,
769         },
770         {
771                 .label          = "root",
772                 .type           = P_STRING,
773                 .p_class        = P_GLOBAL,
774                 .offset         = GLOBAL_VAR(szRootdir),
775                 .special        = NULL,
776                 .enum_list      = NULL,
777                 .flags          = FLAG_HIDE,
778         },
779         {
780                 .label          = "guest account",
781                 .type           = P_STRING,
782                 .p_class        = P_GLOBAL,
783                 .offset         = GLOBAL_VAR(szGuestaccount),
784                 .special        = NULL,
785                 .enum_list      = NULL,
786                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
787         },
788         {
789                 .label          = "enable privileges",
790                 .type           = P_BOOL,
791                 .p_class        = P_GLOBAL,
792                 .offset         = GLOBAL_VAR(bEnablePrivileges),
793                 .special        = NULL,
794                 .enum_list      = NULL,
795                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
796         },
797
798         {
799                 .label          = "pam password change",
800                 .type           = P_BOOL,
801                 .p_class        = P_GLOBAL,
802                 .offset         = GLOBAL_VAR(bPamPasswordChange),
803                 .special        = NULL,
804                 .enum_list      = NULL,
805                 .flags          = FLAG_ADVANCED,
806         },
807         {
808                 .label          = "passwd program",
809                 .type           = P_STRING,
810                 .p_class        = P_GLOBAL,
811                 .offset         = GLOBAL_VAR(szPasswdProgram),
812                 .special        = NULL,
813                 .enum_list      = NULL,
814                 .flags          = FLAG_ADVANCED,
815         },
816         {
817                 .label          = "passwd chat",
818                 .type           = P_STRING,
819                 .p_class        = P_GLOBAL,
820                 .offset         = GLOBAL_VAR(szPasswdChat),
821                 .special        = NULL,
822                 .enum_list      = NULL,
823                 .flags          = FLAG_ADVANCED,
824         },
825         {
826                 .label          = "passwd chat debug",
827                 .type           = P_BOOL,
828                 .p_class        = P_GLOBAL,
829                 .offset         = GLOBAL_VAR(bPasswdChatDebug),
830                 .special        = NULL,
831                 .enum_list      = NULL,
832                 .flags          = FLAG_ADVANCED,
833         },
834         {
835                 .label          = "passwd chat timeout",
836                 .type           = P_INTEGER,
837                 .p_class        = P_GLOBAL,
838                 .offset         = GLOBAL_VAR(iPasswdChatTimeout),
839                 .special        = NULL,
840                 .enum_list      = NULL,
841                 .flags          = FLAG_ADVANCED,
842         },
843         {
844                 .label          = "check password script",
845                 .type           = P_STRING,
846                 .p_class        = P_GLOBAL,
847                 .offset         = GLOBAL_VAR(szCheckPasswordScript),
848                 .special        = NULL,
849                 .enum_list      = NULL,
850                 .flags          = FLAG_ADVANCED,
851         },
852         {
853                 .label          = "username map",
854                 .type           = P_STRING,
855                 .p_class        = P_GLOBAL,
856                 .offset         = GLOBAL_VAR(szUsernameMap),
857                 .special        = NULL,
858                 .enum_list      = NULL,
859                 .flags          = FLAG_ADVANCED,
860         },
861         {
862                 .label          = "password level",
863                 .type           = P_INTEGER,
864                 .p_class        = P_GLOBAL,
865                 .offset         = GLOBAL_VAR(pwordlevel),
866                 .special        = NULL,
867                 .enum_list      = NULL,
868                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
869         },
870         {
871                 .label          = "username level",
872                 .type           = P_INTEGER,
873                 .p_class        = P_GLOBAL,
874                 .offset         = GLOBAL_VAR(unamelevel),
875                 .special        = NULL,
876                 .enum_list      = NULL,
877                 .flags          = FLAG_ADVANCED,
878         },
879         {
880                 .label          = "unix password sync",
881                 .type           = P_BOOL,
882                 .p_class        = P_GLOBAL,
883                 .offset         = GLOBAL_VAR(bUnixPasswdSync),
884                 .special        = NULL,
885                 .enum_list      = NULL,
886                 .flags          = FLAG_ADVANCED,
887         },
888         {
889                 .label          = "restrict anonymous",
890                 .type           = P_INTEGER,
891                 .p_class        = P_GLOBAL,
892                 .offset         = GLOBAL_VAR(restrict_anonymous),
893                 .special        = NULL,
894                 .enum_list      = NULL,
895                 .flags          = FLAG_ADVANCED,
896         },
897         {
898                 .label          = "lanman auth",
899                 .type           = P_BOOL,
900                 .p_class        = P_GLOBAL,
901                 .offset         = GLOBAL_VAR(bLanmanAuth),
902                 .special        = NULL,
903                 .enum_list      = NULL,
904                 .flags          = FLAG_ADVANCED,
905         },
906         {
907                 .label          = "ntlm auth",
908                 .type           = P_BOOL,
909                 .p_class        = P_GLOBAL,
910                 .offset         = GLOBAL_VAR(bNTLMAuth),
911                 .special        = NULL,
912                 .enum_list      = NULL,
913                 .flags          = FLAG_ADVANCED,
914         },
915         {
916                 .label          = "client NTLMv2 auth",
917                 .type           = P_BOOL,
918                 .p_class        = P_GLOBAL,
919                 .offset         = GLOBAL_VAR(bClientNTLMv2Auth),
920                 .special        = NULL,
921                 .enum_list      = NULL,
922                 .flags          = FLAG_ADVANCED,
923         },
924         {
925                 .label          = "client lanman auth",
926                 .type           = P_BOOL,
927                 .p_class        = P_GLOBAL,
928                 .offset         = GLOBAL_VAR(bClientLanManAuth),
929                 .special        = NULL,
930                 .enum_list      = NULL,
931                 .flags          = FLAG_ADVANCED,
932         },
933         {
934                 .label          = "client plaintext auth",
935                 .type           = P_BOOL,
936                 .p_class        = P_GLOBAL,
937                 .offset         = GLOBAL_VAR(bClientPlaintextAuth),
938                 .special        = NULL,
939                 .enum_list      = NULL,
940                 .flags          = FLAG_ADVANCED,
941         },
942         {
943                 .label          = "client use spnego principal",
944                 .type           = P_BOOL,
945                 .p_class        = P_GLOBAL,
946                 .offset         = GLOBAL_VAR(client_use_spnego_principal),
947                 .special        = NULL,
948                 .enum_list      = NULL,
949                 .flags          = FLAG_ADVANCED,
950         },
951         {
952                 .label          = "username",
953                 .type           = P_STRING,
954                 .p_class        = P_LOCAL,
955                 .offset         = LOCAL_VAR(szUsername),
956                 .special        = NULL,
957                 .enum_list      = NULL,
958                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED,
959         },
960         {
961                 .label          = "user",
962                 .type           = P_STRING,
963                 .p_class        = P_LOCAL,
964                 .offset         = LOCAL_VAR(szUsername),
965                 .special        = NULL,
966                 .enum_list      = NULL,
967                 .flags          = FLAG_HIDE,
968         },
969         {
970                 .label          = "users",
971                 .type           = P_STRING,
972                 .p_class        = P_LOCAL,
973                 .offset         = LOCAL_VAR(szUsername),
974                 .special        = NULL,
975                 .enum_list      = NULL,
976                 .flags          = FLAG_HIDE,
977         },
978         {
979                 .label          = "invalid users",
980                 .type           = P_LIST,
981                 .p_class        = P_LOCAL,
982                 .offset         = LOCAL_VAR(szInvalidUsers),
983                 .special        = NULL,
984                 .enum_list      = NULL,
985                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
986         },
987         {
988                 .label          = "valid users",
989                 .type           = P_LIST,
990                 .p_class        = P_LOCAL,
991                 .offset         = LOCAL_VAR(szValidUsers),
992                 .special        = NULL,
993                 .enum_list      = NULL,
994                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
995         },
996         {
997                 .label          = "admin users",
998                 .type           = P_LIST,
999                 .p_class        = P_LOCAL,
1000                 .offset         = LOCAL_VAR(szAdminUsers),
1001                 .special        = NULL,
1002                 .enum_list      = NULL,
1003                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1004         },
1005         {
1006                 .label          = "read list",
1007                 .type           = P_LIST,
1008                 .p_class        = P_LOCAL,
1009                 .offset         = LOCAL_VAR(readlist),
1010                 .special        = NULL,
1011                 .enum_list      = NULL,
1012                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1013         },
1014         {
1015                 .label          = "write list",
1016                 .type           = P_LIST,
1017                 .p_class        = P_LOCAL,
1018                 .offset         = LOCAL_VAR(writelist),
1019                 .special        = NULL,
1020                 .enum_list      = NULL,
1021                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1022         },
1023         {
1024                 .label          = "printer admin",
1025                 .type           = P_LIST,
1026                 .p_class        = P_LOCAL,
1027                 .offset         = LOCAL_VAR(printer_admin),
1028                 .special        = NULL,
1029                 .enum_list      = NULL,
1030                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED,
1031         },
1032         {
1033                 .label          = "force user",
1034                 .type           = P_STRING,
1035                 .p_class        = P_LOCAL,
1036                 .offset         = LOCAL_VAR(force_user),
1037                 .special        = NULL,
1038                 .enum_list      = NULL,
1039                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1040         },
1041         {
1042                 .label          = "force group",
1043                 .type           = P_STRING,
1044                 .p_class        = P_LOCAL,
1045                 .offset         = LOCAL_VAR(force_group),
1046                 .special        = NULL,
1047                 .enum_list      = NULL,
1048                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1049         },
1050         {
1051                 .label          = "group",
1052                 .type           = P_STRING,
1053                 .p_class        = P_LOCAL,
1054                 .offset         = LOCAL_VAR(force_group),
1055                 .special        = NULL,
1056                 .enum_list      = NULL,
1057                 .flags          = FLAG_ADVANCED,
1058         },
1059         {
1060                 .label          = "read only",
1061                 .type           = P_BOOL,
1062                 .p_class        = P_LOCAL,
1063                 .offset         = LOCAL_VAR(bRead_only),
1064                 .special        = NULL,
1065                 .enum_list      = NULL,
1066                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE,
1067         },
1068         {
1069                 .label          = "write ok",
1070                 .type           = P_BOOLREV,
1071                 .p_class        = P_LOCAL,
1072                 .offset         = LOCAL_VAR(bRead_only),
1073                 .special        = NULL,
1074                 .enum_list      = NULL,
1075                 .flags          = FLAG_HIDE,
1076         },
1077         {
1078                 .label          = "writeable",
1079                 .type           = P_BOOLREV,
1080                 .p_class        = P_LOCAL,
1081                 .offset         = LOCAL_VAR(bRead_only),
1082                 .special        = NULL,
1083                 .enum_list      = NULL,
1084                 .flags          = FLAG_HIDE,
1085         },
1086         {
1087                 .label          = "writable",
1088                 .type           = P_BOOLREV,
1089                 .p_class        = P_LOCAL,
1090                 .offset         = LOCAL_VAR(bRead_only),
1091                 .special        = NULL,
1092                 .enum_list      = NULL,
1093                 .flags          = FLAG_HIDE,
1094         },
1095         {
1096                 .label          = "acl check permissions",
1097                 .type           = P_BOOL,
1098                 .p_class        = P_LOCAL,
1099                 .offset         = LOCAL_VAR(bAclCheckPermissions),
1100                 .special        = NULL,
1101                 .enum_list      = NULL,
1102                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED,
1103         },
1104         {
1105                 .label          = "acl group control",
1106                 .type           = P_BOOL,
1107                 .p_class        = P_LOCAL,
1108                 .offset         = LOCAL_VAR(bAclGroupControl),
1109                 .special        = NULL,
1110                 .enum_list      = NULL,
1111                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1112         },
1113         {
1114                 .label          = "acl map full control",
1115                 .type           = P_BOOL,
1116                 .p_class        = P_LOCAL,
1117                 .offset         = LOCAL_VAR(bAclMapFullControl),
1118                 .special        = NULL,
1119                 .enum_list      = NULL,
1120                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1121         },
1122         {
1123                 .label          = "create mask",
1124                 .type           = P_OCTAL,
1125                 .p_class        = P_LOCAL,
1126                 .offset         = LOCAL_VAR(iCreate_mask),
1127                 .special        = NULL,
1128                 .enum_list      = NULL,
1129                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1130         },
1131         {
1132                 .label          = "create mode",
1133                 .type           = P_OCTAL,
1134                 .p_class        = P_LOCAL,
1135                 .offset         = LOCAL_VAR(iCreate_mask),
1136                 .special        = NULL,
1137                 .enum_list      = NULL,
1138                 .flags          = FLAG_HIDE,
1139         },
1140         {
1141                 .label          = "force create mode",
1142                 .type           = P_OCTAL,
1143                 .p_class        = P_LOCAL,
1144                 .offset         = LOCAL_VAR(iCreate_force_mode),
1145                 .special        = NULL,
1146                 .enum_list      = NULL,
1147                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1148         },
1149         {
1150                 .label          = "security mask",
1151                 .type           = P_OCTAL,
1152                 .p_class        = P_LOCAL,
1153                 .offset         = LOCAL_VAR(iSecurity_mask),
1154                 .special        = NULL,
1155                 .enum_list      = NULL,
1156                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1157         },
1158         {
1159                 .label          = "force security mode",
1160                 .type           = P_OCTAL,
1161                 .p_class        = P_LOCAL,
1162                 .offset         = LOCAL_VAR(iSecurity_force_mode),
1163                 .special        = NULL,
1164                 .enum_list      = NULL,
1165                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1166         },
1167         {
1168                 .label          = "directory mask",
1169                 .type           = P_OCTAL,
1170                 .p_class        = P_LOCAL,
1171                 .offset         = LOCAL_VAR(iDir_mask),
1172                 .special        = NULL,
1173                 .enum_list      = NULL,
1174                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1175         },
1176         {
1177                 .label          = "directory mode",
1178                 .type           = P_OCTAL,
1179                 .p_class        = P_LOCAL,
1180                 .offset         = LOCAL_VAR(iDir_mask),
1181                 .special        = NULL,
1182                 .enum_list      = NULL,
1183                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1184         },
1185         {
1186                 .label          = "force directory mode",
1187                 .type           = P_OCTAL,
1188                 .p_class        = P_LOCAL,
1189                 .offset         = LOCAL_VAR(iDir_force_mode),
1190                 .special        = NULL,
1191                 .enum_list      = NULL,
1192                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1193         },
1194         {
1195                 .label          = "directory security mask",
1196                 .type           = P_OCTAL,
1197                 .p_class        = P_LOCAL,
1198                 .offset         = LOCAL_VAR(iDir_Security_mask),
1199                 .special        = NULL,
1200                 .enum_list      = NULL,
1201                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1202         },
1203         {
1204                 .label          = "force directory security mode",
1205                 .type           = P_OCTAL,
1206                 .p_class        = P_LOCAL,
1207                 .offset         = LOCAL_VAR(iDir_Security_force_mode),
1208                 .special        = NULL,
1209                 .enum_list      = NULL,
1210                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1211         },
1212         {
1213                 .label          = "force unknown acl user",
1214                 .type           = P_BOOL,
1215                 .p_class        = P_LOCAL,
1216                 .offset         = LOCAL_VAR(bForceUnknownAclUser),
1217                 .special        = NULL,
1218                 .enum_list      = NULL,
1219                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1220         },
1221         {
1222                 .label          = "inherit permissions",
1223                 .type           = P_BOOL,
1224                 .p_class        = P_LOCAL,
1225                 .offset         = LOCAL_VAR(bInheritPerms),
1226                 .special        = NULL,
1227                 .enum_list      = NULL,
1228                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1229         },
1230         {
1231                 .label          = "inherit acls",
1232                 .type           = P_BOOL,
1233                 .p_class        = P_LOCAL,
1234                 .offset         = LOCAL_VAR(bInheritACLS),
1235                 .special        = NULL,
1236                 .enum_list      = NULL,
1237                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1238         },
1239         {
1240                 .label          = "inherit owner",
1241                 .type           = P_BOOL,
1242                 .p_class        = P_LOCAL,
1243                 .offset         = LOCAL_VAR(bInheritOwner),
1244                 .special        = NULL,
1245                 .enum_list      = NULL,
1246                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1247         },
1248         {
1249                 .label          = "guest only",
1250                 .type           = P_BOOL,
1251                 .p_class        = P_LOCAL,
1252                 .offset         = LOCAL_VAR(bGuest_only),
1253                 .special        = NULL,
1254                 .enum_list      = NULL,
1255                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1256         },
1257         {
1258                 .label          = "only guest",
1259                 .type           = P_BOOL,
1260                 .p_class        = P_LOCAL,
1261                 .offset         = LOCAL_VAR(bGuest_only),
1262                 .special        = NULL,
1263                 .enum_list      = NULL,
1264                 .flags          = FLAG_HIDE,
1265         },
1266         {
1267                 .label          = "administrative share",
1268                 .type           = P_BOOL,
1269                 .p_class        = P_LOCAL,
1270                 .offset         = LOCAL_VAR(bAdministrative_share),
1271                 .special        = NULL,
1272                 .enum_list      = NULL,
1273                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1274         },
1275
1276         {
1277                 .label          = "guest ok",
1278                 .type           = P_BOOL,
1279                 .p_class        = P_LOCAL,
1280                 .offset         = LOCAL_VAR(bGuest_ok),
1281                 .special        = NULL,
1282                 .enum_list      = NULL,
1283                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1284         },
1285         {
1286                 .label          = "public",
1287                 .type           = P_BOOL,
1288                 .p_class        = P_LOCAL,
1289                 .offset         = LOCAL_VAR(bGuest_ok),
1290                 .special        = NULL,
1291                 .enum_list      = NULL,
1292                 .flags          = FLAG_HIDE,
1293         },
1294         {
1295                 .label          = "only user",
1296                 .type           = P_BOOL,
1297                 .p_class        = P_LOCAL,
1298                 .offset         = LOCAL_VAR(bOnlyUser),
1299                 .special        = NULL,
1300                 .enum_list      = NULL,
1301                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED,
1302         },
1303         {
1304                 .label          = "hosts allow",
1305                 .type           = P_LIST,
1306                 .p_class        = P_LOCAL,
1307                 .offset         = LOCAL_VAR(szHostsallow),
1308                 .special        = NULL,
1309                 .enum_list      = NULL,
1310                 .flags          = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1311         },
1312         {
1313                 .label          = "allow hosts",
1314                 .type           = P_LIST,
1315                 .p_class        = P_LOCAL,
1316                 .offset         = LOCAL_VAR(szHostsallow),
1317                 .special        = NULL,
1318                 .enum_list      = NULL,
1319                 .flags          = FLAG_HIDE,
1320         },
1321         {
1322                 .label          = "hosts deny",
1323                 .type           = P_LIST,
1324                 .p_class        = P_LOCAL,
1325                 .offset         = LOCAL_VAR(szHostsdeny),
1326                 .special        = NULL,
1327                 .enum_list      = NULL,
1328                 .flags          = FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
1329         },
1330         {
1331                 .label          = "deny hosts",
1332                 .type           = P_LIST,
1333                 .p_class        = P_LOCAL,
1334                 .offset         = LOCAL_VAR(szHostsdeny),
1335                 .special        = NULL,
1336                 .enum_list      = NULL,
1337                 .flags          = FLAG_HIDE,
1338         },
1339         {
1340                 .label          = "preload modules",
1341                 .type           = P_LIST,
1342                 .p_class        = P_GLOBAL,
1343                 .offset         = GLOBAL_VAR(szPreloadModules),
1344                 .special        = NULL,
1345                 .enum_list      = NULL,
1346                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1347         },
1348         {
1349                 .label          = "dedicated keytab file",
1350                 .type           = P_STRING,
1351                 .p_class        = P_GLOBAL,
1352                 .offset         = GLOBAL_VAR(szDedicatedKeytabFile),
1353                 .special        = NULL,
1354                 .enum_list      = NULL,
1355                 .flags          = FLAG_ADVANCED,
1356         },
1357         {
1358                 .label          = "kerberos method",
1359                 .type           = P_ENUM,
1360                 .p_class        = P_GLOBAL,
1361                 .offset         = GLOBAL_VAR(iKerberosMethod),
1362                 .special        = NULL,
1363                 .enum_list      = enum_kerberos_method,
1364                 .flags          = FLAG_ADVANCED,
1365         },
1366         {
1367                 .label          = "map untrusted to domain",
1368                 .type           = P_BOOL,
1369                 .p_class        = P_GLOBAL,
1370                 .offset         = GLOBAL_VAR(bMapUntrustedToDomain),
1371                 .special        = NULL,
1372                 .enum_list      = NULL,
1373                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1374         },
1375
1376
1377         {N_("Logging Options"), P_SEP, P_SEPARATOR},
1378
1379         {
1380                 .label          = "log level",
1381                 .type           = P_STRING,
1382                 .p_class        = P_GLOBAL,
1383                 .offset         = GLOBAL_VAR(szLogLevel),
1384                 .special        = handle_debug_list,
1385                 .enum_list      = NULL,
1386                 .flags          = FLAG_ADVANCED,
1387         },
1388         {
1389                 .label          = "debuglevel",
1390                 .type           = P_STRING,
1391                 .p_class        = P_GLOBAL,
1392                 .offset         = GLOBAL_VAR(szLogLevel),
1393                 .special        = handle_debug_list,
1394                 .enum_list      = NULL,
1395                 .flags          = FLAG_HIDE,
1396         },
1397         {
1398                 .label          = "syslog",
1399                 .type           = P_INTEGER,
1400                 .p_class        = P_GLOBAL,
1401                 .offset         = GLOBAL_VAR(syslog),
1402                 .special        = NULL,
1403                 .enum_list      = NULL,
1404                 .flags          = FLAG_ADVANCED,
1405         },
1406         {
1407                 .label          = "syslog only",
1408                 .type           = P_BOOL,
1409                 .p_class        = P_GLOBAL,
1410                 .offset         = GLOBAL_VAR(bSyslogOnly),
1411                 .special        = NULL,
1412                 .enum_list      = NULL,
1413                 .flags          = FLAG_ADVANCED,
1414         },
1415         {
1416                 .label          = "log file",
1417                 .type           = P_STRING,
1418                 .p_class        = P_GLOBAL,
1419                 .offset         = GLOBAL_VAR(logfile),
1420                 .special        = NULL,
1421                 .enum_list      = NULL,
1422                 .flags          = FLAG_ADVANCED,
1423         },
1424         {
1425                 .label          = "max log size",
1426                 .type           = P_BYTES,
1427                 .p_class        = P_GLOBAL,
1428                 .offset         = GLOBAL_VAR(max_log_size),
1429                 .special        = NULL,
1430                 .enum_list      = NULL,
1431                 .flags          = FLAG_ADVANCED,
1432         },
1433         {
1434                 .label          = "debug timestamp",
1435                 .type           = P_BOOL,
1436                 .p_class        = P_GLOBAL,
1437                 .offset         = GLOBAL_VAR(bTimestampLogs),
1438                 .special        = NULL,
1439                 .enum_list      = NULL,
1440                 .flags          = FLAG_ADVANCED,
1441         },
1442         {
1443                 .label          = "timestamp logs",
1444                 .type           = P_BOOL,
1445                 .p_class        = P_GLOBAL,
1446                 .offset         = GLOBAL_VAR(bTimestampLogs),
1447                 .special        = NULL,
1448                 .enum_list      = NULL,
1449                 .flags          = FLAG_ADVANCED,
1450         },
1451         {
1452                 .label          = "debug prefix timestamp",
1453                 .type           = P_BOOL,
1454                 .p_class        = P_GLOBAL,
1455                 .offset         = GLOBAL_VAR(bDebugPrefixTimestamp),
1456                 .special        = NULL,
1457                 .enum_list      = NULL,
1458                 .flags          = FLAG_ADVANCED,
1459         },
1460         {
1461                 .label          = "debug hires timestamp",
1462                 .type           = P_BOOL,
1463                 .p_class        = P_GLOBAL,
1464                 .offset         = GLOBAL_VAR(bDebugHiresTimestamp),
1465                 .special        = NULL,
1466                 .enum_list      = NULL,
1467                 .flags          = FLAG_ADVANCED,
1468         },
1469         {
1470                 .label          = "debug pid",
1471                 .type           = P_BOOL,
1472                 .p_class        = P_GLOBAL,
1473                 .offset         = GLOBAL_VAR(bDebugPid),
1474                 .special        = NULL,
1475                 .enum_list      = NULL,
1476                 .flags          = FLAG_ADVANCED,
1477         },
1478         {
1479                 .label          = "debug uid",
1480                 .type           = P_BOOL,
1481                 .p_class        = P_GLOBAL,
1482                 .offset         = GLOBAL_VAR(bDebugUid),
1483                 .special        = NULL,
1484                 .enum_list      = NULL,
1485                 .flags          = FLAG_ADVANCED,
1486         },
1487         {
1488                 .label          = "debug class",
1489                 .type           = P_BOOL,
1490                 .p_class        = P_GLOBAL,
1491                 .offset         = GLOBAL_VAR(bDebugClass),
1492                 .special        = NULL,
1493                 .enum_list      = NULL,
1494                 .flags          = FLAG_ADVANCED,
1495         },
1496         {
1497                 .label          = "enable core files",
1498                 .type           = P_BOOL,
1499                 .p_class        = P_GLOBAL,
1500                 .offset         = GLOBAL_VAR(bEnableCoreFiles),
1501                 .special        = NULL,
1502                 .enum_list      = NULL,
1503                 .flags          = FLAG_ADVANCED,
1504         },
1505
1506         {N_("Protocol Options"), P_SEP, P_SEPARATOR},
1507
1508         {
1509                 .label          = "allocation roundup size",
1510                 .type           = P_BYTES,
1511                 .p_class        = P_LOCAL,
1512                 .offset         = LOCAL_VAR(iallocation_roundup_size),
1513                 .special        = NULL,
1514                 .enum_list      = NULL,
1515                 .flags          = FLAG_ADVANCED,
1516         },
1517         {
1518                 .label          = "aio read size",
1519                 .type           = P_BYTES,
1520                 .p_class        = P_LOCAL,
1521                 .offset         = LOCAL_VAR(iAioReadSize),
1522                 .special        = NULL,
1523                 .enum_list      = NULL,
1524                 .flags          = FLAG_ADVANCED,
1525         },
1526         {
1527                 .label          = "aio write size",
1528                 .type           = P_BYTES,
1529                 .p_class        = P_LOCAL,
1530                 .offset         = LOCAL_VAR(iAioWriteSize),
1531                 .special        = NULL,
1532                 .enum_list      = NULL,
1533                 .flags          = FLAG_ADVANCED,
1534         },
1535         {
1536                 .label          = "aio write behind",
1537                 .type           = P_STRING,
1538                 .p_class        = P_LOCAL,
1539                 .offset         = LOCAL_VAR(szAioWriteBehind),
1540                 .special        = NULL,
1541                 .enum_list      = NULL,
1542                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1543         },
1544         {
1545                 .label          = "smb ports",
1546                 .type           = P_STRING,
1547                 .p_class        = P_GLOBAL,
1548                 .offset         = GLOBAL_VAR(smb_ports),
1549                 .special        = NULL,
1550                 .enum_list      = NULL,
1551                 .flags          = FLAG_ADVANCED,
1552         },
1553         {
1554                 .label          = "large readwrite",
1555                 .type           = P_BOOL,
1556                 .p_class        = P_GLOBAL,
1557                 .offset         = GLOBAL_VAR(bLargeReadwrite),
1558                 .special        = NULL,
1559                 .enum_list      = NULL,
1560                 .flags          = FLAG_ADVANCED,
1561         },
1562         {
1563                 .label          = "max protocol",
1564                 .type           = P_ENUM,
1565                 .p_class        = P_GLOBAL,
1566                 .offset         = GLOBAL_VAR(srv_maxprotocol),
1567                 .special        = NULL,
1568                 .enum_list      = enum_protocol,
1569                 .flags          = FLAG_ADVANCED,
1570         },
1571         {
1572                 .label          = "server max protocol",
1573                 .type           = P_ENUM,
1574                 .p_class        = P_GLOBAL,
1575                 .offset         = GLOBAL_VAR(srv_maxprotocol),
1576                 .special        = NULL,
1577                 .enum_list      = enum_protocol,
1578                 .flags          = FLAG_ADVANCED,
1579         },
1580         {
1581                 .label          = "protocol",
1582                 .type           = P_ENUM,
1583                 .p_class        = P_GLOBAL,
1584                 .offset         = GLOBAL_VAR(srv_maxprotocol),
1585                 .special        = NULL,
1586                 .enum_list      = enum_protocol,
1587                 .flags          = FLAG_ADVANCED,
1588         },
1589         {
1590                 .label          = "min protocol",
1591                 .type           = P_ENUM,
1592                 .p_class        = P_GLOBAL,
1593                 .offset         = GLOBAL_VAR(srv_minprotocol),
1594                 .special        = NULL,
1595                 .enum_list      = enum_protocol,
1596                 .flags          = FLAG_ADVANCED,
1597         },
1598         {
1599                 .label          = "server min protocol",
1600                 .type           = P_ENUM,
1601                 .p_class        = P_GLOBAL,
1602                 .offset         = GLOBAL_VAR(srv_minprotocol),
1603                 .special        = NULL,
1604                 .enum_list      = enum_protocol,
1605                 .flags          = FLAG_ADVANCED,
1606         },
1607         {
1608                 .label          = "min receivefile size",
1609                 .type           = P_BYTES,
1610                 .p_class        = P_GLOBAL,
1611                 .offset         = GLOBAL_VAR(iminreceivefile),
1612                 .special        = NULL,
1613                 .enum_list      = NULL,
1614                 .flags          = FLAG_ADVANCED,
1615         },
1616         {
1617                 .label          = "read raw",
1618                 .type           = P_BOOL,
1619                 .p_class        = P_GLOBAL,
1620                 .offset         = GLOBAL_VAR(bReadRaw),
1621                 .special        = NULL,
1622                 .enum_list      = NULL,
1623                 .flags          = FLAG_ADVANCED,
1624         },
1625         {
1626                 .label          = "write raw",
1627                 .type           = P_BOOL,
1628                 .p_class        = P_GLOBAL,
1629                 .offset         = GLOBAL_VAR(bWriteRaw),
1630                 .special        = NULL,
1631                 .enum_list      = NULL,
1632                 .flags          = FLAG_ADVANCED,
1633         },
1634         {
1635                 .label          = "disable netbios",
1636                 .type           = P_BOOL,
1637                 .p_class        = P_GLOBAL,
1638                 .offset         = GLOBAL_VAR(bDisableNetbios),
1639                 .special        = NULL,
1640                 .enum_list      = NULL,
1641                 .flags          = FLAG_ADVANCED,
1642         },
1643         {
1644                 .label          = "reset on zero vc",
1645                 .type           = P_BOOL,
1646                 .p_class        = P_GLOBAL,
1647                 .offset         = GLOBAL_VAR(bResetOnZeroVC),
1648                 .special        = NULL,
1649                 .enum_list      = NULL,
1650                 .flags          = FLAG_ADVANCED,
1651         },
1652         {
1653                 .label          = "log writeable files on exit",
1654                 .type           = P_BOOL,
1655                 .p_class        = P_GLOBAL,
1656                 .offset         = GLOBAL_VAR(bLogWriteableFilesOnExit),
1657                 .special        = NULL,
1658                 .enum_list      = NULL,
1659                 .flags          = FLAG_ADVANCED,
1660         },
1661         {
1662                 .label          = "acl compatibility",
1663                 .type           = P_ENUM,
1664                 .p_class        = P_GLOBAL,
1665                 .offset         = GLOBAL_VAR(iAclCompat),
1666                 .special        = NULL,
1667                 .enum_list      = enum_acl_compat_vals,
1668                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1669         },
1670         {
1671                 .label          = "defer sharing violations",
1672                 .type           = P_BOOL,
1673                 .p_class        = P_GLOBAL,
1674                 .offset         = GLOBAL_VAR(bDeferSharingViolations),
1675                 .special        = NULL,
1676                 .enum_list      = NULL,
1677                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
1678         },
1679         {
1680                 .label          = "ea support",
1681                 .type           = P_BOOL,
1682                 .p_class        = P_LOCAL,
1683                 .offset         = LOCAL_VAR(bEASupport),
1684                 .special        = NULL,
1685                 .enum_list      = NULL,
1686                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1687         },
1688         {
1689                 .label          = "nt acl support",
1690                 .type           = P_BOOL,
1691                 .p_class        = P_LOCAL,
1692                 .offset         = LOCAL_VAR(bNTAclSupport),
1693                 .special        = NULL,
1694                 .enum_list      = NULL,
1695                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1696         },
1697         {
1698                 .label          = "nt pipe support",
1699                 .type           = P_BOOL,
1700                 .p_class        = P_GLOBAL,
1701                 .offset         = GLOBAL_VAR(bNTPipeSupport),
1702                 .special        = NULL,
1703                 .enum_list      = NULL,
1704                 .flags          = FLAG_ADVANCED,
1705         },
1706         {
1707                 .label          = "nt status support",
1708                 .type           = P_BOOL,
1709                 .p_class        = P_GLOBAL,
1710                 .offset         = GLOBAL_VAR(bNTStatusSupport),
1711                 .special        = NULL,
1712                 .enum_list      = NULL,
1713                 .flags          = FLAG_ADVANCED,
1714         },
1715         {
1716                 .label          = "profile acls",
1717                 .type           = P_BOOL,
1718                 .p_class        = P_LOCAL,
1719                 .offset         = LOCAL_VAR(bProfileAcls),
1720                 .special        = NULL,
1721                 .enum_list      = NULL,
1722                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
1723         },
1724         {
1725                 .label          = "map acl inherit",
1726                 .type           = P_BOOL,
1727                 .p_class        = P_LOCAL,
1728                 .offset         = LOCAL_VAR(bMap_acl_inherit),
1729                 .special        = NULL,
1730                 .enum_list      = NULL,
1731                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1732         },
1733         {
1734                 .label          = "afs share",
1735                 .type           = P_BOOL,
1736                 .p_class        = P_LOCAL,
1737                 .offset         = LOCAL_VAR(bAfs_Share),
1738                 .special        = NULL,
1739                 .enum_list      = NULL,
1740                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1741         },
1742         {
1743                 .label          = "max mux",
1744                 .type           = P_INTEGER,
1745                 .p_class        = P_GLOBAL,
1746                 .offset         = GLOBAL_VAR(max_mux),
1747                 .special        = NULL,
1748                 .enum_list      = NULL,
1749                 .flags          = FLAG_ADVANCED,
1750         },
1751         {
1752                 .label          = "max xmit",
1753                 .type           = P_BYTES,
1754                 .p_class        = P_GLOBAL,
1755                 .offset         = GLOBAL_VAR(max_xmit),
1756                 .special        = NULL,
1757                 .enum_list      = NULL,
1758                 .flags          = FLAG_ADVANCED,
1759         },
1760         {
1761                 .label          = "name resolve order",
1762                 .type           = P_STRING,
1763                 .p_class        = P_GLOBAL,
1764                 .offset         = GLOBAL_VAR(szNameResolveOrder),
1765                 .special        = NULL,
1766                 .enum_list      = NULL,
1767                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
1768         },
1769         {
1770                 .label          = "max ttl",
1771                 .type           = P_INTEGER,
1772                 .p_class        = P_GLOBAL,
1773                 .offset         = GLOBAL_VAR(max_ttl),
1774                 .special        = NULL,
1775                 .enum_list      = NULL,
1776                 .flags          = FLAG_ADVANCED,
1777         },
1778         {
1779                 .label          = "max wins ttl",
1780                 .type           = P_INTEGER,
1781                 .p_class        = P_GLOBAL,
1782                 .offset         = GLOBAL_VAR(max_wins_ttl),
1783                 .special        = NULL,
1784                 .enum_list      = NULL,
1785                 .flags          = FLAG_ADVANCED,
1786         },
1787         {
1788                 .label          = "min wins ttl",
1789                 .type           = P_INTEGER,
1790                 .p_class        = P_GLOBAL,
1791                 .offset         = GLOBAL_VAR(min_wins_ttl),
1792                 .special        = NULL,
1793                 .enum_list      = NULL,
1794                 .flags          = FLAG_ADVANCED,
1795         },
1796         {
1797                 .label          = "time server",
1798                 .type           = P_BOOL,
1799                 .p_class        = P_GLOBAL,
1800                 .offset         = GLOBAL_VAR(bTimeServer),
1801                 .special        = NULL,
1802                 .enum_list      = NULL,
1803                 .flags          = FLAG_ADVANCED,
1804         },
1805         {
1806                 .label          = "unix extensions",
1807                 .type           = P_BOOL,
1808                 .p_class        = P_GLOBAL,
1809                 .offset         = GLOBAL_VAR(bUnixExtensions),
1810                 .special        = NULL,
1811                 .enum_list      = NULL,
1812                 .flags          = FLAG_ADVANCED,
1813         },
1814         {
1815                 .label          = "use spnego",
1816                 .type           = P_BOOL,
1817                 .p_class        = P_GLOBAL,
1818                 .offset         = GLOBAL_VAR(bUseSpnego),
1819                 .special        = NULL,
1820                 .enum_list      = NULL,
1821                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
1822         },
1823         {
1824                 .label          = "client signing",
1825                 .type           = P_ENUM,
1826                 .p_class        = P_GLOBAL,
1827                 .offset         = GLOBAL_VAR(client_signing),
1828                 .special        = NULL,
1829                 .enum_list      = enum_smb_signing_vals,
1830                 .flags          = FLAG_ADVANCED,
1831         },
1832         {
1833                 .label          = "server signing",
1834                 .type           = P_ENUM,
1835                 .p_class        = P_GLOBAL,
1836                 .offset         = GLOBAL_VAR(server_signing),
1837                 .special        = NULL,
1838                 .enum_list      = enum_smb_signing_vals,
1839                 .flags          = FLAG_ADVANCED,
1840         },
1841         {
1842                 .label          = "smb encrypt",
1843                 .type           = P_ENUM,
1844                 .p_class        = P_LOCAL,
1845                 .offset         = LOCAL_VAR(ismb_encrypt),
1846                 .special        = NULL,
1847                 .enum_list      = enum_smb_signing_vals,
1848                 .flags          = FLAG_ADVANCED,
1849         },
1850         {
1851                 .label          = "client use spnego",
1852                 .type           = P_BOOL,
1853                 .p_class        = P_GLOBAL,
1854                 .offset         = GLOBAL_VAR(bClientUseSpnego),
1855                 .special        = NULL,
1856                 .enum_list      = NULL,
1857                 .flags          = FLAG_ADVANCED,
1858         },
1859         {
1860                 .label          = "client ldap sasl wrapping",
1861                 .type           = P_ENUM,
1862                 .p_class        = P_GLOBAL,
1863                 .offset         = GLOBAL_VAR(client_ldap_sasl_wrapping),
1864                 .special        = NULL,
1865                 .enum_list      = enum_ldap_sasl_wrapping,
1866                 .flags          = FLAG_ADVANCED,
1867         },
1868         {
1869                 .label          = "enable asu support",
1870                 .type           = P_BOOL,
1871                 .p_class        = P_GLOBAL,
1872                 .offset         = GLOBAL_VAR(bASUSupport),
1873                 .special        = NULL,
1874                 .enum_list      = NULL,
1875                 .flags          = FLAG_ADVANCED,
1876         },
1877         {
1878                 .label          = "svcctl list",
1879                 .type           = P_LIST,
1880                 .p_class        = P_GLOBAL,
1881                 .offset         = GLOBAL_VAR(szServicesList),
1882                 .special        = NULL,
1883                 .enum_list      = NULL,
1884                 .flags          = FLAG_ADVANCED,
1885         },
1886
1887         {N_("Tuning Options"), P_SEP, P_SEPARATOR},
1888
1889         {
1890                 .label          = "block size",
1891                 .type           = P_BYTES,
1892                 .p_class        = P_LOCAL,
1893                 .offset         = LOCAL_VAR(iBlock_size),
1894                 .special        = NULL,
1895                 .enum_list      = NULL,
1896                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
1897         },
1898         {
1899                 .label          = "deadtime",
1900                 .type           = P_INTEGER,
1901                 .p_class        = P_GLOBAL,
1902                 .offset         = GLOBAL_VAR(deadtime),
1903                 .special        = NULL,
1904                 .enum_list      = NULL,
1905                 .flags          = FLAG_ADVANCED,
1906         },
1907         {
1908                 .label          = "getwd cache",
1909                 .type           = P_BOOL,
1910                 .p_class        = P_GLOBAL,
1911                 .offset         = GLOBAL_VAR(getwd_cache),
1912                 .special        = NULL,
1913                 .enum_list      = NULL,
1914                 .flags          = FLAG_ADVANCED,
1915         },
1916         {
1917                 .label          = "keepalive",
1918                 .type           = P_INTEGER,
1919                 .p_class        = P_GLOBAL,
1920                 .offset         = GLOBAL_VAR(iKeepalive),
1921                 .special        = NULL,
1922                 .enum_list      = NULL,
1923                 .flags          = FLAG_ADVANCED,
1924         },
1925         {
1926                 .label          = "change notify",
1927                 .type           = P_BOOL,
1928                 .p_class        = P_LOCAL,
1929                 .offset         = LOCAL_VAR(bChangeNotify),
1930                 .special        = NULL,
1931                 .enum_list      = NULL,
1932                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1933         },
1934         {
1935                 .label          = "directory name cache size",
1936                 .type           = P_INTEGER,
1937                 .p_class        = P_LOCAL,
1938                 .offset         = LOCAL_VAR(iDirectoryNameCacheSize),
1939                 .special        = NULL,
1940                 .enum_list      = NULL,
1941                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1942         },
1943         {
1944                 .label          = "kernel change notify",
1945                 .type           = P_BOOL,
1946                 .p_class        = P_LOCAL,
1947                 .offset         = LOCAL_VAR(bKernelChangeNotify),
1948                 .special        = NULL,
1949                 .enum_list      = NULL,
1950                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1951         },
1952         {
1953                 .label          = "lpq cache time",
1954                 .type           = P_INTEGER,
1955                 .p_class        = P_GLOBAL,
1956                 .offset         = GLOBAL_VAR(lpqcachetime),
1957                 .special        = NULL,
1958                 .enum_list      = NULL,
1959                 .flags          = FLAG_ADVANCED,
1960         },
1961         {
1962                 .label          = "max smbd processes",
1963                 .type           = P_INTEGER,
1964                 .p_class        = P_GLOBAL,
1965                 .offset         = GLOBAL_VAR(iMaxSmbdProcesses),
1966                 .special        = NULL,
1967                 .enum_list      = NULL,
1968                 .flags          = FLAG_ADVANCED,
1969         },
1970         {
1971                 .label          = "max connections",
1972                 .type           = P_INTEGER,
1973                 .p_class        = P_LOCAL,
1974                 .offset         = LOCAL_VAR(iMaxConnections),
1975                 .special        = NULL,
1976                 .enum_list      = NULL,
1977                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
1978         },
1979         {
1980                 .label          = "paranoid server security",
1981                 .type           = P_BOOL,
1982                 .p_class        = P_GLOBAL,
1983                 .offset         = GLOBAL_VAR(paranoid_server_security),
1984                 .special        = NULL,
1985                 .enum_list      = NULL,
1986                 .flags          = FLAG_ADVANCED,
1987         },
1988         {
1989                 .label          = "max disk size",
1990                 .type           = P_BYTES,
1991                 .p_class        = P_GLOBAL,
1992                 .offset         = GLOBAL_VAR(maxdisksize),
1993                 .special        = NULL,
1994                 .enum_list      = NULL,
1995                 .flags          = FLAG_ADVANCED,
1996         },
1997         {
1998                 .label          = "max open files",
1999                 .type           = P_INTEGER,
2000                 .p_class        = P_GLOBAL,
2001                 .offset         = GLOBAL_VAR(max_open_files),
2002                 .special        = NULL,
2003                 .enum_list      = NULL,
2004                 .flags          = FLAG_ADVANCED,
2005         },
2006         {
2007                 .label          = "min print space",
2008                 .type           = P_INTEGER,
2009                 .p_class        = P_LOCAL,
2010                 .offset         = LOCAL_VAR(iMinPrintSpace),
2011                 .special        = NULL,
2012                 .enum_list      = NULL,
2013                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2014         },
2015         {
2016                 .label          = "socket options",
2017                 .type           = P_STRING,
2018                 .p_class        = P_GLOBAL,
2019                 .offset         = GLOBAL_VAR(szSocketOptions),
2020                 .special        = NULL,
2021                 .enum_list      = NULL,
2022                 .flags          = FLAG_ADVANCED,
2023         },
2024         {
2025                 .label          = "strict allocate",
2026                 .type           = P_BOOL,
2027                 .p_class        = P_LOCAL,
2028                 .offset         = LOCAL_VAR(bStrictAllocate),
2029                 .special        = NULL,
2030                 .enum_list      = NULL,
2031                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2032         },
2033         {
2034                 .label          = "strict sync",
2035                 .type           = P_BOOL,
2036                 .p_class        = P_LOCAL,
2037                 .offset         = LOCAL_VAR(bStrictSync),
2038                 .special        = NULL,
2039                 .enum_list      = NULL,
2040                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2041         },
2042         {
2043                 .label          = "sync always",
2044                 .type           = P_BOOL,
2045                 .p_class        = P_LOCAL,
2046                 .offset         = LOCAL_VAR(bSyncAlways),
2047                 .special        = NULL,
2048                 .enum_list      = NULL,
2049                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2050         },
2051         {
2052                 .label          = "use mmap",
2053                 .type           = P_BOOL,
2054                 .p_class        = P_GLOBAL,
2055                 .offset         = GLOBAL_VAR(bUseMmap),
2056                 .special        = NULL,
2057                 .enum_list      = NULL,
2058                 .flags          = FLAG_ADVANCED,
2059         },
2060         {
2061                 .label          = "use sendfile",
2062                 .type           = P_BOOL,
2063                 .p_class        = P_LOCAL,
2064                 .offset         = LOCAL_VAR(bUseSendfile),
2065                 .special        = NULL,
2066                 .enum_list      = NULL,
2067                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2068         },
2069         {
2070                 .label          = "hostname lookups",
2071                 .type           = P_BOOL,
2072                 .p_class        = P_GLOBAL,
2073                 .offset         = GLOBAL_VAR(bHostnameLookups),
2074                 .special        = NULL,
2075                 .enum_list      = NULL,
2076                 .flags          = FLAG_ADVANCED,
2077         },
2078         {
2079                 .label          = "write cache size",
2080                 .type           = P_BYTES,
2081                 .p_class        = P_LOCAL,
2082                 .offset         = LOCAL_VAR(iWriteCacheSize),
2083                 .special        = NULL,
2084                 .enum_list      = NULL,
2085                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2086         },
2087         {
2088                 .label          = "name cache timeout",
2089                 .type           = P_INTEGER,
2090                 .p_class        = P_GLOBAL,
2091                 .offset         = GLOBAL_VAR(name_cache_timeout),
2092                 .special        = NULL,
2093                 .enum_list      = NULL,
2094                 .flags          = FLAG_ADVANCED,
2095         },
2096         {
2097                 .label          = "ctdbd socket",
2098                 .type           = P_STRING,
2099                 .p_class        = P_GLOBAL,
2100                 .offset         = GLOBAL_VAR(ctdbdSocket),
2101                 .special        = NULL,
2102                 .enum_list      = NULL,
2103                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2104         },
2105         {
2106                 .label          = "cluster addresses",
2107                 .type           = P_LIST,
2108                 .p_class        = P_GLOBAL,
2109                 .offset         = GLOBAL_VAR(szClusterAddresses),
2110                 .special        = NULL,
2111                 .enum_list      = NULL,
2112                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2113         },
2114         {
2115                 .label          = "clustering",
2116                 .type           = P_BOOL,
2117                 .p_class        = P_GLOBAL,
2118                 .offset         = GLOBAL_VAR(clustering),
2119                 .special        = NULL,
2120                 .enum_list      = NULL,
2121                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2122         },
2123         {
2124                 .label          = "ctdb timeout",
2125                 .type           = P_INTEGER,
2126                 .p_class        = P_GLOBAL,
2127                 .offset         = GLOBAL_VAR(ctdb_timeout),
2128                 .special        = NULL,
2129                 .enum_list      = NULL,
2130                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2131         },
2132         {
2133                 .label          = "ctdb locktime warn threshold",
2134                 .type           = P_INTEGER,
2135                 .p_class        = P_GLOBAL,
2136                 .offset         = GLOBAL_VAR(ctdb_locktime_warn_threshold),
2137                 .special        = NULL,
2138                 .enum_list      = NULL,
2139                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
2140         },
2141         {
2142                 .label          = "smb2 max read",
2143                 .type           = P_BYTES,
2144                 .p_class        = P_GLOBAL,
2145                 .offset         = GLOBAL_VAR(ismb2_max_read),
2146                 .special        = NULL,
2147                 .enum_list      = NULL,
2148                 .flags          = FLAG_ADVANCED,
2149         },
2150         {
2151                 .label          = "smb2 max write",
2152                 .type           = P_BYTES,
2153                 .p_class        = P_GLOBAL,
2154                 .offset         = GLOBAL_VAR(ismb2_max_write),
2155                 .special        = NULL,
2156                 .enum_list      = NULL,
2157                 .flags          = FLAG_ADVANCED,
2158         },
2159         {
2160                 .label          = "smb2 max trans",
2161                 .type           = P_BYTES,
2162                 .p_class        = P_GLOBAL,
2163                 .offset         = GLOBAL_VAR(ismb2_max_trans),
2164                 .special        = NULL,
2165                 .enum_list      = NULL,
2166                 .flags          = FLAG_ADVANCED,
2167         },
2168         {
2169                 .label          = "smb2 max credits",
2170                 .type           = P_INTEGER,
2171                 .p_class        = P_GLOBAL,
2172                 .offset         = GLOBAL_VAR(ismb2_max_credits),
2173                 .special        = NULL,
2174                 .enum_list      = NULL,
2175                 .flags          = FLAG_ADVANCED,
2176         },
2177
2178         {N_("Printing Options"), P_SEP, P_SEPARATOR},
2179
2180         {
2181                 .label          = "max reported print jobs",
2182                 .type           = P_INTEGER,
2183                 .p_class        = P_LOCAL,
2184                 .offset         = LOCAL_VAR(iMaxReportedPrintJobs),
2185                 .special        = NULL,
2186                 .enum_list      = NULL,
2187                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2188         },
2189         {
2190                 .label          = "max print jobs",
2191                 .type           = P_INTEGER,
2192                 .p_class        = P_LOCAL,
2193                 .offset         = LOCAL_VAR(iMaxPrintJobs),
2194                 .special        = NULL,
2195                 .enum_list      = NULL,
2196                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2197         },
2198         {
2199                 .label          = "load printers",
2200                 .type           = P_BOOL,
2201                 .p_class        = P_GLOBAL,
2202                 .offset         = GLOBAL_VAR(bLoadPrinters),
2203                 .special        = NULL,
2204                 .enum_list      = NULL,
2205                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2206         },
2207         {
2208                 .label          = "printcap cache time",
2209                 .type           = P_INTEGER,
2210                 .p_class        = P_GLOBAL,
2211                 .offset         = GLOBAL_VAR(PrintcapCacheTime),
2212                 .special        = NULL,
2213                 .enum_list      = NULL,
2214                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2215         },
2216         {
2217                 .label          = "printcap name",
2218                 .type           = P_STRING,
2219                 .p_class        = P_GLOBAL,
2220                 .offset         = GLOBAL_VAR(szPrintcapname),
2221                 .special        = NULL,
2222                 .enum_list      = NULL,
2223                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2224         },
2225         {
2226                 .label          = "printcap",
2227                 .type           = P_STRING,
2228                 .p_class        = P_GLOBAL,
2229                 .offset         = GLOBAL_VAR(szPrintcapname),
2230                 .special        = NULL,
2231                 .enum_list      = NULL,
2232                 .flags          = FLAG_HIDE,
2233         },
2234         {
2235                 .label          = "printable",
2236                 .type           = P_BOOL,
2237                 .p_class        = P_LOCAL,
2238                 .offset         = LOCAL_VAR(bPrint_ok),
2239                 .special        = NULL,
2240                 .enum_list      = NULL,
2241                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2242         },
2243         {
2244                 .label          = "print notify backchannel",
2245                 .type           = P_BOOL,
2246                 .p_class        = P_LOCAL,
2247                 .offset         = LOCAL_VAR(bPrintNotifyBackchannel),
2248                 .special        = NULL,
2249                 .enum_list      = NULL,
2250                 .flags          = FLAG_ADVANCED,
2251         },
2252         {
2253                 .label          = "print ok",
2254                 .type           = P_BOOL,
2255                 .p_class        = P_LOCAL,
2256                 .offset         = LOCAL_VAR(bPrint_ok),
2257                 .special        = NULL,
2258                 .enum_list      = NULL,
2259                 .flags          = FLAG_HIDE,
2260         },
2261         {
2262                 .label          = "printing",
2263                 .type           = P_ENUM,
2264                 .p_class        = P_LOCAL,
2265                 .offset         = LOCAL_VAR(iPrinting),
2266                 .special        = handle_printing,
2267                 .enum_list      = enum_printing,
2268                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2269         },
2270         {
2271                 .label          = "cups options",
2272                 .type           = P_STRING,
2273                 .p_class        = P_LOCAL,
2274                 .offset         = LOCAL_VAR(szCupsOptions),
2275                 .special        = NULL,
2276                 .enum_list      = NULL,
2277                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2278         },
2279         {
2280                 .label          = "cups server",
2281                 .type           = P_STRING,
2282                 .p_class        = P_GLOBAL,
2283                 .offset         = GLOBAL_VAR(szCupsServer),
2284                 .special        = NULL,
2285                 .enum_list      = NULL,
2286                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2287         },
2288         {
2289                 .label          = "cups encrypt",
2290                 .type           = P_ENUM,
2291                 .p_class        = P_GLOBAL,
2292                 .offset            = GLOBAL_VAR(CupsEncrypt),
2293                 .special        = NULL,
2294                 .enum_list      = enum_bool_auto,
2295                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2296         },
2297         {
2298
2299                 .label          = "cups connection timeout",
2300                 .type           = P_INTEGER,
2301                 .p_class        = P_GLOBAL,
2302                 .offset         = GLOBAL_VAR(cups_connection_timeout),
2303                 .special        = NULL,
2304                 .enum_list      = NULL,
2305                 .flags          = FLAG_ADVANCED,
2306         },
2307         {
2308                 .label          = "iprint server",
2309                 .type           = P_STRING,
2310                 .p_class        = P_GLOBAL,
2311                 .offset         = GLOBAL_VAR(szIPrintServer),
2312                 .special        = NULL,
2313                 .enum_list      = NULL,
2314                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2315         },
2316         {
2317                 .label          = "print command",
2318                 .type           = P_STRING,
2319                 .p_class        = P_LOCAL,
2320                 .offset         = LOCAL_VAR(szPrintcommand),
2321                 .special        = NULL,
2322                 .enum_list      = NULL,
2323                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2324         },
2325         {
2326                 .label          = "disable spoolss",
2327                 .type           = P_BOOL,
2328                 .p_class        = P_GLOBAL,
2329                 .offset         = GLOBAL_VAR(bDisableSpoolss),
2330                 .special        = NULL,
2331                 .enum_list      = NULL,
2332                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2333         },
2334         {
2335                 .label          = "enable spoolss",
2336                 .type           = P_BOOLREV,
2337                 .p_class        = P_GLOBAL,
2338                 .offset         = GLOBAL_VAR(bDisableSpoolss),
2339                 .special        = NULL,
2340                 .enum_list      = NULL,
2341                 .flags          = FLAG_HIDE,
2342         },
2343         {
2344                 .label          = "lpq command",
2345                 .type           = P_STRING,
2346                 .p_class        = P_LOCAL,
2347                 .offset         = LOCAL_VAR(szLpqcommand),
2348                 .special        = NULL,
2349                 .enum_list      = NULL,
2350                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2351         },
2352         {
2353                 .label          = "lprm command",
2354                 .type           = P_STRING,
2355                 .p_class        = P_LOCAL,
2356                 .offset         = LOCAL_VAR(szLprmcommand),
2357                 .special        = NULL,
2358                 .enum_list      = NULL,
2359                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2360         },
2361         {
2362                 .label          = "lppause command",
2363                 .type           = P_STRING,
2364                 .p_class        = P_LOCAL,
2365                 .offset         = LOCAL_VAR(szLppausecommand),
2366                 .special        = NULL,
2367                 .enum_list      = NULL,
2368                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2369         },
2370         {
2371                 .label          = "lpresume command",
2372                 .type           = P_STRING,
2373                 .p_class        = P_LOCAL,
2374                 .offset         = LOCAL_VAR(szLpresumecommand),
2375                 .special        = NULL,
2376                 .enum_list      = NULL,
2377                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2378         },
2379         {
2380                 .label          = "queuepause command",
2381                 .type           = P_STRING,
2382                 .p_class        = P_LOCAL,
2383                 .offset         = LOCAL_VAR(szQueuepausecommand),
2384                 .special        = NULL,
2385                 .enum_list      = NULL,
2386                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2387         },
2388         {
2389                 .label          = "queueresume command",
2390                 .type           = P_STRING,
2391                 .p_class        = P_LOCAL,
2392                 .offset         = LOCAL_VAR(szQueueresumecommand),
2393                 .special        = NULL,
2394                 .enum_list      = NULL,
2395                 .flags          = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL,
2396         },
2397         {
2398                 .label          = "addport command",
2399                 .type           = P_STRING,
2400                 .p_class        = P_GLOBAL,
2401                 .offset         = GLOBAL_VAR(szAddPortCommand),
2402                 .special        = NULL,
2403                 .enum_list      = NULL,
2404                 .flags          = FLAG_ADVANCED,
2405         },
2406         {
2407                 .label          = "enumports command",
2408                 .type           = P_STRING,
2409                 .p_class        = P_GLOBAL,
2410                 .offset         = GLOBAL_VAR(szEnumPortsCommand),
2411                 .special        = NULL,
2412                 .enum_list      = NULL,
2413                 .flags          = FLAG_ADVANCED,
2414         },
2415         {
2416                 .label          = "addprinter command",
2417                 .type           = P_STRING,
2418                 .p_class        = P_GLOBAL,
2419                 .offset         = GLOBAL_VAR(szAddPrinterCommand),
2420                 .special        = NULL,
2421                 .enum_list      = NULL,
2422                 .flags          = FLAG_ADVANCED,
2423         },
2424         {
2425                 .label          = "deleteprinter command",
2426                 .type           = P_STRING,
2427                 .p_class        = P_GLOBAL,
2428                 .offset         = GLOBAL_VAR(szDeletePrinterCommand),
2429                 .special        = NULL,
2430                 .enum_list      = NULL,
2431                 .flags          = FLAG_ADVANCED,
2432         },
2433         {
2434                 .label          = "show add printer wizard",
2435                 .type           = P_BOOL,
2436                 .p_class        = P_GLOBAL,
2437                 .offset         = GLOBAL_VAR(bMsAddPrinterWizard),
2438                 .special        = NULL,
2439                 .enum_list      = NULL,
2440                 .flags          = FLAG_ADVANCED,
2441         },
2442         {
2443                 .label          = "os2 driver map",
2444                 .type           = P_STRING,
2445                 .p_class        = P_GLOBAL,
2446                 .offset         = GLOBAL_VAR(szOs2DriverMap),
2447                 .special        = NULL,
2448                 .enum_list      = NULL,
2449                 .flags          = FLAG_ADVANCED,
2450         },
2451
2452         {
2453                 .label          = "printer name",
2454                 .type           = P_STRING,
2455                 .p_class        = P_LOCAL,
2456                 .offset         = LOCAL_VAR(szPrintername),
2457                 .special        = NULL,
2458                 .enum_list      = NULL,
2459                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2460         },
2461         {
2462                 .label          = "printer",
2463                 .type           = P_STRING,
2464                 .p_class        = P_LOCAL,
2465                 .offset         = LOCAL_VAR(szPrintername),
2466                 .special        = NULL,
2467                 .enum_list      = NULL,
2468                 .flags          = FLAG_HIDE,
2469         },
2470         {
2471                 .label          = "use client driver",
2472                 .type           = P_BOOL,
2473                 .p_class        = P_LOCAL,
2474                 .offset         = LOCAL_VAR(bUseClientDriver),
2475                 .special        = NULL,
2476                 .enum_list      = NULL,
2477                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2478         },
2479         {
2480                 .label          = "default devmode",
2481                 .type           = P_BOOL,
2482                 .p_class        = P_LOCAL,
2483                 .offset         = LOCAL_VAR(bDefaultDevmode),
2484                 .special        = NULL,
2485                 .enum_list      = NULL,
2486                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2487         },
2488         {
2489                 .label          = "force printername",
2490                 .type           = P_BOOL,
2491                 .p_class        = P_LOCAL,
2492                 .offset         = LOCAL_VAR(bForcePrintername),
2493                 .special        = NULL,
2494                 .enum_list      = NULL,
2495                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2496         },
2497         {
2498                 .label          = "printjob username",
2499                 .type           = P_STRING,
2500                 .p_class        = P_LOCAL,
2501                 .offset         = LOCAL_VAR(szPrintjobUsername),
2502                 .special        = NULL,
2503                 .enum_list      = NULL,
2504                 .flags          = FLAG_ADVANCED | FLAG_PRINT,
2505         },
2506
2507         {N_("Filename Handling"), P_SEP, P_SEPARATOR},
2508
2509         {
2510                 .label          = "mangling method",
2511                 .type           = P_STRING,
2512                 .p_class        = P_GLOBAL,
2513                 .offset         = GLOBAL_VAR(szManglingMethod),
2514                 .special        = NULL,
2515                 .enum_list      = NULL,
2516                 .flags          = FLAG_ADVANCED,
2517         },
2518         {
2519                 .label          = "mangle prefix",
2520                 .type           = P_INTEGER,
2521                 .p_class        = P_GLOBAL,
2522                 .offset         = GLOBAL_VAR(mangle_prefix),
2523                 .special        = NULL,
2524                 .enum_list      = NULL,
2525                 .flags          = FLAG_ADVANCED,
2526         },
2527
2528         {
2529                 .label          = "default case",
2530                 .type           = P_ENUM,
2531                 .p_class        = P_LOCAL,
2532                 .offset         = LOCAL_VAR(iDefaultCase),
2533                 .special        = NULL,
2534                 .enum_list      = enum_case,
2535                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
2536         },
2537         {
2538                 .label          = "case sensitive",
2539                 .type           = P_ENUM,
2540                 .p_class        = P_LOCAL,
2541                 .offset         = LOCAL_VAR(iCaseSensitive),
2542                 .special        = NULL,
2543                 .enum_list      = enum_bool_auto,
2544                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2545         },
2546         {
2547                 .label          = "casesignames",
2548                 .type           = P_ENUM,
2549                 .p_class        = P_LOCAL,
2550                 .offset         = LOCAL_VAR(iCaseSensitive),
2551                 .special        = NULL,
2552                 .enum_list      = enum_bool_auto,
2553                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE,
2554         },
2555         {
2556                 .label          = "preserve case",
2557                 .type           = P_BOOL,
2558                 .p_class        = P_LOCAL,
2559                 .offset         = LOCAL_VAR(bCasePreserve),
2560                 .special        = NULL,
2561                 .enum_list      = NULL,
2562                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2563         },
2564         {
2565                 .label          = "short preserve case",
2566                 .type           = P_BOOL,
2567                 .p_class        = P_LOCAL,
2568                 .offset         = LOCAL_VAR(bShortCasePreserve),
2569                 .special        = NULL,
2570                 .enum_list      = NULL,
2571                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2572         },
2573         {
2574                 .label          = "mangling char",
2575                 .type           = P_CHAR,
2576                 .p_class        = P_LOCAL,
2577                 .offset         = LOCAL_VAR(magic_char),
2578                 .special        = NULL,
2579                 .enum_list      = NULL,
2580                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2581         },
2582         {
2583                 .label          = "hide dot files",
2584                 .type           = P_BOOL,
2585                 .p_class        = P_LOCAL,
2586                 .offset         = LOCAL_VAR(bHideDotFiles),
2587                 .special        = NULL,
2588                 .enum_list      = NULL,
2589                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2590         },
2591         {
2592                 .label          = "hide special files",
2593                 .type           = P_BOOL,
2594                 .p_class        = P_LOCAL,
2595                 .offset         = LOCAL_VAR(bHideSpecialFiles),
2596                 .special        = NULL,
2597                 .enum_list      = NULL,
2598                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2599         },
2600         {
2601                 .label          = "hide unreadable",
2602                 .type           = P_BOOL,
2603                 .p_class        = P_LOCAL,
2604                 .offset         = LOCAL_VAR(bHideUnReadable),
2605                 .special        = NULL,
2606                 .enum_list      = NULL,
2607                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2608         },
2609         {
2610                 .label          = "hide unwriteable files",
2611                 .type           = P_BOOL,
2612                 .p_class        = P_LOCAL,
2613                 .offset         = LOCAL_VAR(bHideUnWriteableFiles),
2614                 .special        = NULL,
2615                 .enum_list      = NULL,
2616                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2617         },
2618         {
2619                 .label          = "delete veto files",
2620                 .type           = P_BOOL,
2621                 .p_class        = P_LOCAL,
2622                 .offset         = LOCAL_VAR(bDeleteVetoFiles),
2623                 .special        = NULL,
2624                 .enum_list      = NULL,
2625                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2626         },
2627         {
2628                 .label          = "veto files",
2629                 .type           = P_STRING,
2630                 .p_class        = P_LOCAL,
2631                 .offset         = LOCAL_VAR(szVetoFiles),
2632                 .special        = NULL,
2633                 .enum_list      = NULL,
2634                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2635         },
2636         {
2637                 .label          = "hide files",
2638                 .type           = P_STRING,
2639                 .p_class        = P_LOCAL,
2640                 .offset         = LOCAL_VAR(szHideFiles),
2641                 .special        = NULL,
2642                 .enum_list      = NULL,
2643                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2644         },
2645         {
2646                 .label          = "veto oplock files",
2647                 .type           = P_STRING,
2648                 .p_class        = P_LOCAL,
2649                 .offset         = LOCAL_VAR(szVetoOplockFiles),
2650                 .special        = NULL,
2651                 .enum_list      = NULL,
2652                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2653         },
2654         {
2655                 .label          = "map archive",
2656                 .type           = P_BOOL,
2657                 .p_class        = P_LOCAL,
2658                 .offset         = LOCAL_VAR(bMap_archive),
2659                 .special        = NULL,
2660                 .enum_list      = NULL,
2661                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2662         },
2663         {
2664                 .label          = "map hidden",
2665                 .type           = P_BOOL,
2666                 .p_class        = P_LOCAL,
2667                 .offset         = LOCAL_VAR(bMap_hidden),
2668                 .special        = NULL,
2669                 .enum_list      = NULL,
2670                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2671         },
2672         {
2673                 .label          = "map system",
2674                 .type           = P_BOOL,
2675                 .p_class        = P_LOCAL,
2676                 .offset         = LOCAL_VAR(bMap_system),
2677                 .special        = NULL,
2678                 .enum_list      = NULL,
2679                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2680         },
2681         {
2682                 .label          = "map readonly",
2683                 .type           = P_ENUM,
2684                 .p_class        = P_LOCAL,
2685                 .offset         = LOCAL_VAR(iMap_readonly),
2686                 .special        = NULL,
2687                 .enum_list      = enum_map_readonly,
2688                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2689         },
2690         {
2691                 .label          = "mangled names",
2692                 .type           = P_BOOL,
2693                 .p_class        = P_LOCAL,
2694                 .offset         = LOCAL_VAR(bMangledNames),
2695                 .special        = NULL,
2696                 .enum_list      = NULL,
2697                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2698         },
2699         {
2700                 .label          = "max stat cache size",
2701                 .type           = P_INTEGER,
2702                 .p_class        = P_GLOBAL,
2703                 .offset         = GLOBAL_VAR(iMaxStatCacheSize),
2704                 .special        = NULL,
2705                 .enum_list      = NULL,
2706                 .flags          = FLAG_ADVANCED,
2707         },
2708         {
2709                 .label          = "stat cache",
2710                 .type           = P_BOOL,
2711                 .p_class        = P_GLOBAL,
2712                 .offset         = GLOBAL_VAR(bStatCache),
2713                 .special        = NULL,
2714                 .enum_list      = NULL,
2715                 .flags          = FLAG_ADVANCED,
2716         },
2717         {
2718                 .label          = "store dos attributes",
2719                 .type           = P_BOOL,
2720                 .p_class        = P_LOCAL,
2721                 .offset         = LOCAL_VAR(bStoreDosAttributes),
2722                 .special        = NULL,
2723                 .enum_list      = NULL,
2724                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2725         },
2726         {
2727                 .label          = "dmapi support",
2728                 .type           = P_BOOL,
2729                 .p_class        = P_LOCAL,
2730                 .offset         = LOCAL_VAR(bDmapiSupport),
2731                 .special        = NULL,
2732                 .enum_list      = NULL,
2733                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
2734         },
2735
2736
2737         {N_("Domain Options"), P_SEP, P_SEPARATOR},
2738
2739         {
2740                 .label          = "machine password timeout",
2741                 .type           = P_INTEGER,
2742                 .p_class        = P_GLOBAL,
2743                 .offset         = GLOBAL_VAR(machine_password_timeout),
2744                 .special        = NULL,
2745                 .enum_list      = NULL,
2746                 .flags          = FLAG_ADVANCED | FLAG_WIZARD,
2747         },
2748
2749         {N_("Logon Options"), P_SEP, P_SEPARATOR},
2750
2751         {
2752                 .label          = "add user script",
2753                 .type           = P_STRING,
2754                 .p_class        = P_GLOBAL,
2755                 .offset         = GLOBAL_VAR(szAddUserScript),
2756                 .special        = NULL,
2757                 .enum_list      = NULL,
2758                 .flags          = FLAG_ADVANCED,
2759         },
2760         {
2761                 .label          = "rename user script",
2762                 .type           = P_STRING,
2763                 .p_class        = P_GLOBAL,
2764                 .offset         = GLOBAL_VAR(szRenameUserScript),
2765                 .special        = NULL,
2766                 .enum_list      = NULL,
2767                 .flags          = FLAG_ADVANCED,
2768         },
2769         {
2770                 .label          = "delete user script",
2771                 .type           = P_STRING,
2772                 .p_class        = P_GLOBAL,
2773                 .offset         = GLOBAL_VAR(szDelUserScript),
2774                 .special        = NULL,
2775                 .enum_list      = NULL,
2776                 .flags          = FLAG_ADVANCED,
2777         },
2778         {
2779                 .label          = "add group script",
2780                 .type           = P_STRING,
2781                 .p_class        = P_GLOBAL,
2782                 .offset         = GLOBAL_VAR(szAddGroupScript),
2783                 .special        = NULL,
2784                 .enum_list      = NULL,
2785                 .flags          = FLAG_ADVANCED,
2786         },
2787         {
2788                 .label          = "delete group script",
2789                 .type           = P_STRING,
2790                 .p_class        = P_GLOBAL,
2791                 .offset         = GLOBAL_VAR(szDelGroupScript),
2792                 .special        = NULL,
2793                 .enum_list      = NULL,
2794                 .flags          = FLAG_ADVANCED,
2795         },
2796         {
2797                 .label          = "add user to group script",
2798                 .type           = P_STRING,
2799                 .p_class        = P_GLOBAL,
2800                 .offset         = GLOBAL_VAR(szAddUserToGroupScript),
2801                 .special        = NULL,
2802                 .enum_list      = NULL,
2803                 .flags          = FLAG_ADVANCED,
2804         },
2805         {
2806                 .label          = "delete user from group script",
2807                 .type           = P_STRING,
2808                 .p_class        = P_GLOBAL,
2809                 .offset         = GLOBAL_VAR(szDelUserFromGroupScript),
2810                 .special        = NULL,
2811                 .enum_list      = NULL,
2812                 .flags          = FLAG_ADVANCED,
2813         },
2814         {
2815                 .label          = "set primary group script",
2816                 .type           = P_STRING,
2817                 .p_class        = P_GLOBAL,
2818                 .offset         = GLOBAL_VAR(szSetPrimaryGroupScript),
2819                 .special        = NULL,
2820                 .enum_list      = NULL,
2821                 .flags          = FLAG_ADVANCED,
2822         },
2823         {
2824                 .label          = "add machine script",
2825                 .type           = P_STRING,
2826                 .p_class        = P_GLOBAL,
2827                 .offset         = GLOBAL_VAR(szAddMachineScript),
2828                 .special        = NULL,
2829                 .enum_list      = NULL,
2830                 .flags          = FLAG_ADVANCED,
2831         },
2832         {
2833                 .label          = "shutdown script",
2834                 .type           = P_STRING,
2835                 .p_class        = P_GLOBAL,
2836                 .offset         = GLOBAL_VAR(szShutdownScript),
2837                 .special        = NULL,
2838                 .enum_list      = NULL,
2839                 .flags          = FLAG_ADVANCED,
2840         },
2841         {
2842                 .label          = "abort shutdown script",
2843                 .type           = P_STRING,
2844                 .p_class        = P_GLOBAL,
2845                 .offset         = GLOBAL_VAR(szAbortShutdownScript),
2846                 .special        = NULL,
2847                 .enum_list      = NULL,
2848                 .flags          = FLAG_ADVANCED,
2849         },
2850         {
2851                 .label          = "username map script",
2852                 .type           = P_STRING,
2853                 .p_class        = P_GLOBAL,
2854                 .offset         = GLOBAL_VAR(szUsernameMapScript),
2855                 .special        = NULL,
2856                 .enum_list      = NULL,
2857                 .flags          = FLAG_ADVANCED,
2858         },
2859         {
2860                 .label          = "username map cache time",
2861                 .type           = P_INTEGER,
2862                 .p_class        = P_GLOBAL,
2863                 .offset         = GLOBAL_VAR(iUsernameMapCacheTime),
2864                 .special        = NULL,
2865                 .enum_list      = NULL,
2866                 .flags          = FLAG_ADVANCED,
2867         },
2868         {
2869                 .label          = "logon script",
2870                 .type           = P_STRING,
2871                 .p_class        = P_GLOBAL,
2872                 .offset         = GLOBAL_VAR(szLogonScript),
2873                 .special        = NULL,
2874                 .enum_list      = NULL,
2875                 .flags          = FLAG_ADVANCED,
2876         },
2877         {
2878                 .label          = "logon path",
2879                 .type           = P_STRING,
2880                 .p_class        = P_GLOBAL,
2881                 .offset         = GLOBAL_VAR(szLogonPath),
2882                 .special        = NULL,
2883                 .enum_list      = NULL,
2884                 .flags          = FLAG_ADVANCED,
2885         },
2886         {
2887                 .label          = "logon drive",
2888                 .type           = P_STRING,
2889                 .p_class        = P_GLOBAL,
2890                 .offset         = GLOBAL_VAR(szLogonDrive),
2891                 .special        = NULL,
2892                 .enum_list      = NULL,
2893                 .flags          = FLAG_ADVANCED,
2894         },
2895         {
2896                 .label          = "logon home",
2897                 .type           = P_STRING,
2898                 .p_class        = P_GLOBAL,
2899                 .offset         = GLOBAL_VAR(szLogonHome),
2900                 .special        = NULL,
2901                 .enum_list      = NULL,
2902                 .flags          = FLAG_ADVANCED,
2903         },
2904         {
2905                 .label          = "domain logons",
2906                 .type           = P_BOOL,
2907                 .p_class        = P_GLOBAL,
2908                 .offset         = GLOBAL_VAR(bDomainLogons),
2909                 .special        = NULL,
2910                 .enum_list      = NULL,
2911                 .flags          = FLAG_ADVANCED,
2912         },
2913
2914         {
2915                 .label          = "init logon delayed hosts",
2916                 .type           = P_LIST,
2917                 .p_class        = P_GLOBAL,
2918                 .offset         = GLOBAL_VAR(szInitLogonDelayedHosts),
2919                 .special        = NULL,
2920                 .enum_list      = NULL,
2921                 .flags          = FLAG_ADVANCED,
2922         },
2923
2924         {
2925                 .label          = "init logon delay",
2926                 .type           = P_INTEGER,
2927                 .p_class        = P_GLOBAL,
2928                 .offset         = GLOBAL_VAR(InitLogonDelay),
2929                 .special        = NULL,
2930                 .enum_list      = NULL,
2931                 .flags          = FLAG_ADVANCED,
2932
2933         },
2934
2935         {N_("Browse Options"), P_SEP, P_SEPARATOR},
2936
2937         {
2938                 .label          = "os level",
2939                 .type           = P_INTEGER,
2940                 .p_class        = P_GLOBAL,
2941                 .offset         = GLOBAL_VAR(os_level),
2942                 .special        = NULL,
2943                 .enum_list      = NULL,
2944                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
2945         },
2946         {
2947                 .label          = "lm announce",
2948                 .type           = P_ENUM,
2949                 .p_class        = P_GLOBAL,
2950                 .offset         = GLOBAL_VAR(lm_announce),
2951                 .special        = NULL,
2952                 .enum_list      = enum_bool_auto,
2953                 .flags          = FLAG_ADVANCED,
2954         },
2955         {
2956                 .label          = "lm interval",
2957                 .type           = P_INTEGER,
2958                 .p_class        = P_GLOBAL,
2959                 .offset         = GLOBAL_VAR(lm_interval),
2960                 .special        = NULL,
2961                 .enum_list      = NULL,
2962                 .flags          = FLAG_ADVANCED,
2963         },
2964         {
2965                 .label          = "preferred master",
2966                 .type           = P_ENUM,
2967                 .p_class        = P_GLOBAL,
2968                 .offset         = GLOBAL_VAR(iPreferredMaster),
2969                 .special        = NULL,
2970                 .enum_list      = enum_bool_auto,
2971                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
2972         },
2973         {
2974                 .label          = "prefered master",
2975                 .type           = P_ENUM,
2976                 .p_class        = P_GLOBAL,
2977                 .offset         = GLOBAL_VAR(iPreferredMaster),
2978                 .special        = NULL,
2979                 .enum_list      = enum_bool_auto,
2980                 .flags          = FLAG_HIDE,
2981         },
2982         {
2983                 .label          = "local master",
2984                 .type           = P_BOOL,
2985                 .p_class        = P_GLOBAL,
2986                 .offset         = GLOBAL_VAR(bLocalMaster),
2987                 .special        = NULL,
2988                 .enum_list      = NULL,
2989                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
2990         },
2991         {
2992                 .label          = "domain master",
2993                 .type           = P_ENUM,
2994                 .p_class        = P_GLOBAL,
2995                 .offset         = GLOBAL_VAR(iDomainMaster),
2996                 .special        = NULL,
2997                 .enum_list      = enum_bool_auto,
2998                 .flags          = FLAG_BASIC | FLAG_ADVANCED,
2999         },
3000         {
3001                 .label          = "browse list",
3002                 .type           = P_BOOL,
3003                 .p_class        = P_GLOBAL,
3004                 .offset         = GLOBAL_VAR(bBrowseList),
3005                 .special        = NULL,
3006                 .enum_list      = NULL,
3007                 .flags          = FLAG_ADVANCED,
3008         },
3009         {
3010                 .label          = "browseable",
3011                 .type           = P_BOOL,
3012                 .p_class        = P_LOCAL,
3013                 .offset         = LOCAL_VAR(bBrowseable),
3014                 .special        = NULL,
3015                 .enum_list      = NULL,
3016                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3017         },
3018         {
3019                 .label          = "browsable",
3020                 .type           = P_BOOL,
3021                 .p_class        = P_LOCAL,
3022                 .offset         = LOCAL_VAR(bBrowseable),
3023                 .special        = NULL,
3024                 .enum_list      = NULL,
3025                 .flags          = FLAG_HIDE,
3026         },
3027         {
3028                 .label          = "access based share enum",
3029                 .type           = P_BOOL,
3030                 .p_class        = P_LOCAL,
3031                 .offset         = LOCAL_VAR(bAccessBasedShareEnum),
3032                 .special        = NULL,
3033                 .enum_list      = NULL,
3034                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE
3035         },
3036         {
3037                 .label          = "enhanced browsing",
3038                 .type           = P_BOOL,
3039                 .p_class        = P_GLOBAL,
3040                 .offset         = GLOBAL_VAR(enhanced_browsing),
3041                 .special        = NULL,
3042                 .enum_list      = NULL,
3043                 .flags          = FLAG_ADVANCED,
3044         },
3045
3046         {N_("WINS Options"), P_SEP, P_SEPARATOR},
3047
3048         {
3049                 .label          = "dns proxy",
3050                 .type           = P_BOOL,
3051                 .p_class        = P_GLOBAL,
3052                 .offset         = GLOBAL_VAR(bWINSdnsProxy),
3053                 .special        = NULL,
3054                 .enum_list      = NULL,
3055                 .flags          = FLAG_ADVANCED,
3056         },
3057         {
3058                 .label          = "wins proxy",
3059                 .type           = P_BOOL,
3060                 .p_class        = P_GLOBAL,
3061                 .offset         = GLOBAL_VAR(bWINSproxy),
3062                 .special        = NULL,
3063                 .enum_list      = NULL,
3064                 .flags          = FLAG_ADVANCED,
3065         },
3066         {
3067                 .label          = "wins server",
3068                 .type           = P_LIST,
3069                 .p_class        = P_GLOBAL,
3070                 .offset         = GLOBAL_VAR(szWINSservers),
3071                 .special        = NULL,
3072                 .enum_list      = NULL,
3073                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3074         },
3075         {
3076                 .label          = "wins support",
3077                 .type           = P_BOOL,
3078                 .p_class        = P_GLOBAL,
3079                 .offset         = GLOBAL_VAR(bWINSsupport),
3080                 .special        = NULL,
3081                 .enum_list      = NULL,
3082                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD,
3083         },
3084         {
3085                 .label          = "wins hook",
3086                 .type           = P_STRING,
3087                 .p_class        = P_GLOBAL,
3088                 .offset         = GLOBAL_VAR(szWINSHook),
3089                 .special        = NULL,
3090                 .enum_list      = NULL,
3091                 .flags          = FLAG_ADVANCED,
3092         },
3093
3094         {N_("Locking Options"), P_SEP, P_SEPARATOR},
3095
3096         {
3097                 .label          = "blocking locks",
3098                 .type           = P_BOOL,
3099                 .p_class        = P_LOCAL,
3100                 .offset         = LOCAL_VAR(bBlockingLocks),
3101                 .special        = NULL,
3102                 .enum_list      = NULL,
3103                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3104         },
3105         {
3106                 .label          = "csc policy",
3107                 .type           = P_ENUM,
3108                 .p_class        = P_LOCAL,
3109                 .offset         = LOCAL_VAR(iCSCPolicy),
3110                 .special        = NULL,
3111                 .enum_list      = enum_csc_policy,
3112                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3113         },
3114         {
3115                 .label          = "fake oplocks",
3116                 .type           = P_BOOL,
3117                 .p_class        = P_LOCAL,
3118                 .offset         = LOCAL_VAR(bFakeOplocks),
3119                 .special        = NULL,
3120                 .enum_list      = NULL,
3121                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3122         },
3123         {
3124                 .label          = "kernel oplocks",
3125                 .type           = P_BOOL,
3126                 .p_class        = P_LOCAL,
3127                 .offset         = LOCAL_VAR(bKernelOplocks),
3128                 .special        = NULL,
3129                 .enum_list      = NULL,
3130                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3131         },
3132         {
3133                 .label          = "locking",
3134                 .type           = P_BOOL,
3135                 .p_class        = P_LOCAL,
3136                 .offset         = LOCAL_VAR(bLocking),
3137                 .special        = NULL,
3138                 .enum_list      = NULL,
3139                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3140         },
3141         {
3142                 .label          = "lock spin time",
3143                 .type           = P_INTEGER,
3144                 .p_class        = P_GLOBAL,
3145                 .offset         = GLOBAL_VAR(iLockSpinTime),
3146                 .special        = NULL,
3147                 .enum_list      = NULL,
3148                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3149         },
3150         {
3151                 .label          = "oplocks",
3152                 .type           = P_BOOL,
3153                 .p_class        = P_LOCAL,
3154                 .offset         = LOCAL_VAR(bOpLocks),
3155                 .special        = NULL,
3156                 .enum_list      = NULL,
3157                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3158         },
3159         {
3160                 .label          = "level2 oplocks",
3161                 .type           = P_BOOL,
3162                 .p_class        = P_LOCAL,
3163                 .offset         = LOCAL_VAR(bLevel2OpLocks),
3164                 .special        = NULL,
3165                 .enum_list      = NULL,
3166                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3167         },
3168         {
3169                 .label          = "oplock break wait time",
3170                 .type           = P_INTEGER,
3171                 .p_class        = P_GLOBAL,
3172                 .offset         = GLOBAL_VAR(oplock_break_wait_time),
3173                 .special        = NULL,
3174                 .enum_list      = NULL,
3175                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3176         },
3177         {
3178                 .label          = "oplock contention limit",
3179                 .type           = P_INTEGER,
3180                 .p_class        = P_LOCAL,
3181                 .offset         = LOCAL_VAR(iOplockContentionLimit),
3182                 .special        = NULL,
3183                 .enum_list      = NULL,
3184                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3185         },
3186         {
3187                 .label          = "posix locking",
3188                 .type           = P_BOOL,
3189                 .p_class        = P_LOCAL,
3190                 .offset         = LOCAL_VAR(bPosixLocking),
3191                 .special        = NULL,
3192                 .enum_list      = NULL,
3193                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3194         },
3195         {
3196                 .label          = "strict locking",
3197                 .type           = P_ENUM,
3198                 .p_class        = P_LOCAL,
3199                 .offset         = LOCAL_VAR(iStrictLocking),
3200                 .special        = NULL,
3201                 .enum_list      = enum_bool_auto,
3202                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3203         },
3204         {
3205                 .label          = "share modes",
3206                 .type           = P_BOOL,
3207                 .p_class        = P_LOCAL,
3208                 .offset         = LOCAL_VAR(bShareModes),
3209                 .special        = NULL,
3210                 .enum_list      = NULL,
3211                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED,
3212         },
3213
3214         {N_("Ldap Options"), P_SEP, P_SEPARATOR},
3215
3216         {
3217                 .label          = "ldap admin dn",
3218                 .type           = P_STRING,
3219                 .p_class        = P_GLOBAL,
3220                 .offset         = GLOBAL_VAR(szLdapAdminDn),
3221                 .special        = NULL,
3222                 .enum_list      = NULL,
3223                 .flags          = FLAG_ADVANCED,
3224         },
3225         {
3226                 .label          = "ldap delete dn",
3227                 .type           = P_BOOL,
3228                 .p_class        = P_GLOBAL,
3229                 .offset         = GLOBAL_VAR(ldap_delete_dn),
3230                 .special        = NULL,
3231                 .enum_list      = NULL,
3232                 .flags          = FLAG_ADVANCED,
3233         },
3234         {
3235                 .label          = "ldap group suffix",
3236                 .type           = P_STRING,
3237                 .p_class        = P_GLOBAL,
3238                 .offset         = GLOBAL_VAR(szLdapGroupSuffix),
3239                 .special        = NULL,
3240                 .enum_list      = NULL,
3241                 .flags          = FLAG_ADVANCED,
3242         },
3243         {
3244                 .label          = "ldap idmap suffix",
3245                 .type           = P_STRING,
3246                 .p_class        = P_GLOBAL,
3247                 .offset         = GLOBAL_VAR(szLdapIdmapSuffix),
3248                 .special        = NULL,
3249                 .enum_list      = NULL,
3250                 .flags          = FLAG_ADVANCED,
3251         },
3252         {
3253                 .label          = "ldap machine suffix",
3254                 .type           = P_STRING,
3255                 .p_class        = P_GLOBAL,
3256                 .offset         = GLOBAL_VAR(szLdapMachineSuffix),
3257                 .special        = NULL,
3258                 .enum_list      = NULL,
3259                 .flags          = FLAG_ADVANCED,
3260         },
3261         {
3262                 .label          = "ldap passwd sync",
3263                 .type           = P_ENUM,
3264                 .p_class        = P_GLOBAL,
3265                 .offset         = GLOBAL_VAR(ldap_passwd_sync),
3266                 .special        = NULL,
3267                 .enum_list      = enum_ldap_passwd_sync,
3268                 .flags          = FLAG_ADVANCED,
3269         },
3270         {
3271                 .label          = "ldap password sync",
3272                 .type           = P_ENUM,
3273                 .p_class        = P_GLOBAL,
3274                 .offset         = GLOBAL_VAR(ldap_passwd_sync),
3275                 .special        = NULL,
3276                 .enum_list      = enum_ldap_passwd_sync,
3277                 .flags          = FLAG_HIDE,
3278         },
3279         {
3280                 .label          = "ldap replication sleep",
3281                 .type           = P_INTEGER,
3282                 .p_class        = P_GLOBAL,
3283                 .offset         = GLOBAL_VAR(ldap_replication_sleep),
3284                 .special        = NULL,
3285                 .enum_list      = NULL,
3286                 .flags          = FLAG_ADVANCED,
3287         },
3288         {
3289                 .label          = "ldap suffix",
3290                 .type           = P_STRING,
3291                 .p_class        = P_GLOBAL,
3292                 .offset         = GLOBAL_VAR(szLdapSuffix),
3293                 .special        = NULL,
3294                 .enum_list      = NULL,
3295                 .flags          = FLAG_ADVANCED,
3296         },
3297         {
3298                 .label          = "ldap ssl",
3299                 .type           = P_ENUM,
3300                 .p_class        = P_GLOBAL,
3301                 .offset         = GLOBAL_VAR(ldap_ssl),
3302                 .special        = NULL,
3303                 .enum_list      = enum_ldap_ssl,
3304                 .flags          = FLAG_ADVANCED,
3305         },
3306         {
3307                 .label          = "ldap ssl ads",
3308                 .type           = P_BOOL,
3309                 .p_class        = P_GLOBAL,
3310                 .offset         = GLOBAL_VAR(ldap_ssl_ads),
3311                 .special        = NULL,
3312                 .enum_list      = NULL,
3313                 .flags          = FLAG_ADVANCED,
3314         },
3315         {
3316                 .label          = "ldap deref",
3317                 .type           = P_ENUM,
3318                 .p_class        = P_GLOBAL,
3319                 .offset         = GLOBAL_VAR(ldap_deref),
3320                 .special        = NULL,
3321                 .enum_list      = enum_ldap_deref,
3322                 .flags          = FLAG_ADVANCED,
3323         },
3324         {
3325                 .label          = "ldap follow referral",
3326                 .type           = P_ENUM,
3327                 .p_class        = P_GLOBAL,
3328                 .offset         = GLOBAL_VAR(ldap_follow_referral),
3329                 .special        = NULL,
3330                 .enum_list      = enum_bool_auto,
3331                 .flags          = FLAG_ADVANCED,
3332         },
3333         {
3334                 .label          = "ldap timeout",
3335                 .type           = P_INTEGER,
3336                 .p_class        = P_GLOBAL,
3337                 .offset         = GLOBAL_VAR(ldap_timeout),
3338                 .special        = NULL,
3339                 .enum_list      = NULL,
3340                 .flags          = FLAG_ADVANCED,
3341         },
3342         {
3343                 .label          = "ldap connection timeout",
3344                 .type           = P_INTEGER,
3345                 .p_class        = P_GLOBAL,
3346                 .offset         = GLOBAL_VAR(ldap_connection_timeout),
3347                 .special        = NULL,
3348                 .enum_list      = NULL,
3349                 .flags          = FLAG_ADVANCED,
3350         },
3351         {
3352                 .label          = "ldap page size",
3353                 .type           = P_INTEGER,
3354                 .p_class        = P_GLOBAL,
3355                 .offset         = GLOBAL_VAR(ldap_page_size),
3356                 .special        = NULL,
3357                 .enum_list      = NULL,
3358                 .flags          = FLAG_ADVANCED,
3359         },
3360         {
3361                 .label          = "ldap user suffix",
3362                 .type           = P_STRING,
3363                 .p_class        = P_GLOBAL,
3364                 .offset         = GLOBAL_VAR(szLdapUserSuffix),
3365                 .special        = NULL,
3366                 .enum_list      = NULL,
3367                 .flags          = FLAG_ADVANCED,
3368         },
3369         {
3370                 .label          = "ldap debug level",
3371                 .type           = P_INTEGER,
3372                 .p_class        = P_GLOBAL,
3373                 .offset         = GLOBAL_VAR(ldap_debug_level),
3374                 .special        = handle_ldap_debug_level,
3375                 .enum_list      = NULL,
3376                 .flags          = FLAG_ADVANCED,
3377         },
3378         {
3379                 .label          = "ldap debug threshold",
3380                 .type           = P_INTEGER,
3381                 .p_class        = P_GLOBAL,
3382                 .offset         = GLOBAL_VAR(ldap_debug_threshold),
3383                 .special        = NULL,
3384                 .enum_list      = NULL,
3385                 .flags          = FLAG_ADVANCED,
3386         },
3387
3388         {N_("EventLog Options"), P_SEP, P_SEPARATOR},
3389
3390         {
3391                 .label          = "eventlog list",
3392                 .type           = P_LIST,
3393                 .p_class        = P_GLOBAL,
3394                 .offset         = GLOBAL_VAR(szEventLogs),
3395                 .special        = NULL,
3396                 .enum_list      = NULL,
3397                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE,
3398         },
3399
3400         {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR},
3401
3402         {
3403                 .label          = "add share command",
3404                 .type           = P_STRING,
3405                 .p_class        = P_GLOBAL,
3406                 .offset         = GLOBAL_VAR(szAddShareCommand),
3407                 .special        = NULL,
3408                 .enum_list      = NULL,
3409                 .flags          = FLAG_ADVANCED,
3410         },
3411         {
3412                 .label          = "change share command",
3413                 .type           = P_STRING,
3414                 .p_class        = P_GLOBAL,
3415                 .offset         = GLOBAL_VAR(szChangeShareCommand),
3416                 .special        = NULL,
3417                 .enum_list      = NULL,
3418                 .flags          = FLAG_ADVANCED,
3419         },
3420         {
3421                 .label          = "delete share command",
3422                 .type           = P_STRING,
3423                 .p_class        = P_GLOBAL,
3424                 .offset         = GLOBAL_VAR(szDeleteShareCommand),
3425                 .special        = NULL,
3426                 .enum_list      = NULL,
3427                 .flags          = FLAG_ADVANCED,
3428         },
3429         {
3430                 .label          = "config file",
3431                 .type           = P_STRING,
3432                 .p_class        = P_GLOBAL,
3433                 .offset         = GLOBAL_VAR(szConfigFile),
3434                 .special        = NULL,
3435                 .enum_list      = NULL,
3436                 .flags          = FLAG_HIDE|FLAG_META,
3437         },
3438         {
3439                 .label          = "preload",
3440                 .type           = P_STRING,
3441                 .p_class        = P_GLOBAL,
3442                 .offset         = GLOBAL_VAR(szAutoServices),
3443                 .special        = NULL,
3444                 .enum_list      = NULL,
3445                 .flags          = FLAG_ADVANCED,
3446         },
3447         {
3448                 .label          = "auto services",
3449                 .type           = P_STRING,
3450                 .p_class        = P_GLOBAL,
3451                 .offset         = GLOBAL_VAR(szAutoServices),
3452                 .special        = NULL,
3453                 .enum_list      = NULL,
3454                 .flags          = FLAG_ADVANCED,
3455         },
3456         {
3457                 .label          = "lock directory",
3458                 .type           = P_STRING,
3459                 .p_class        = P_GLOBAL,
3460                 .offset         = GLOBAL_VAR(szLockDir),
3461                 .special        = NULL,
3462                 .enum_list      = NULL,
3463                 .flags          = FLAG_ADVANCED,
3464         },
3465         {
3466                 .label          = "lock dir",
3467                 .type           = P_STRING,
3468                 .p_class        = P_GLOBAL,
3469                 .offset         = GLOBAL_VAR(szLockDir),
3470                 .special        = NULL,
3471                 .enum_list      = NULL,
3472                 .flags          = FLAG_HIDE,
3473         },
3474         {
3475                 .label          = "state directory",
3476                 .type           = P_STRING,
3477                 .p_class        = P_GLOBAL,
3478                 .offset         = GLOBAL_VAR(szStateDir),
3479                 .special        = NULL,
3480                 .enum_list      = NULL,
3481                 .flags          = FLAG_ADVANCED,
3482         },
3483         {
3484                 .label          = "cache directory",
3485                 .type           = P_STRING,
3486                 .p_class        = P_GLOBAL,
3487                 .offset         = GLOBAL_VAR(szCacheDir),
3488                 .special        = NULL,
3489                 .enum_list      = NULL,
3490                 .flags          = FLAG_ADVANCED,
3491         },
3492         {
3493                 .label          = "pid directory",
3494                 .type           = P_STRING,
3495                 .p_class        = P_GLOBAL,
3496                 .offset         = GLOBAL_VAR(szPidDir),
3497                 .special        = NULL,
3498                 .enum_list      = NULL,
3499                 .flags          = FLAG_ADVANCED,
3500         },
3501 #ifdef WITH_UTMP
3502         {
3503                 .label          = "utmp directory",
3504                 .type           = P_STRING,
3505                 .p_class        = P_GLOBAL,
3506                 .offset         = GLOBAL_VAR(szUtmpDir),
3507                 .special        = NULL,
3508                 .enum_list      = NULL,
3509                 .flags          = FLAG_ADVANCED,
3510         },
3511         {
3512                 .label          = "wtmp directory",
3513                 .type           = P_STRING,
3514                 .p_class        = P_GLOBAL,
3515                 .offset         = GLOBAL_VAR(szWtmpDir),
3516                 .special        = NULL,
3517                 .enum_list      = NULL,
3518                 .flags          = FLAG_ADVANCED,
3519         },
3520         {
3521                 .label          = "utmp",
3522                 .type           = P_BOOL,
3523                 .p_class        = P_GLOBAL,
3524                 .offset         = GLOBAL_VAR(bUtmp),
3525                 .special        = NULL,
3526                 .enum_list      = NULL,
3527                 .flags          = FLAG_ADVANCED,
3528         },
3529 #endif
3530         {
3531                 .label          = "default service",
3532                 .type           = P_STRING,
3533                 .p_class        = P_GLOBAL,
3534                 .offset         = GLOBAL_VAR(szDefaultService),
3535                 .special        = NULL,
3536                 .enum_list      = NULL,
3537                 .flags          = FLAG_ADVANCED,
3538         },
3539         {
3540                 .label          = "default",
3541                 .type           = P_STRING,
3542                 .p_class        = P_GLOBAL,
3543                 .offset         = GLOBAL_VAR(szDefaultService),
3544                 .special        = NULL,
3545                 .enum_list      = NULL,
3546                 .flags          = FLAG_ADVANCED,
3547         },
3548         {
3549                 .label          = "message command",
3550                 .type           = P_STRING,
3551                 .p_class        = P_GLOBAL,
3552                 .offset         = GLOBAL_VAR(szMsgCommand),
3553                 .special        = NULL,
3554                 .enum_list      = NULL,
3555                 .flags          = FLAG_ADVANCED,
3556         },
3557         {
3558                 .label          = "dfree cache time",
3559                 .type           = P_INTEGER,
3560                 .p_class        = P_LOCAL,
3561                 .offset         = LOCAL_VAR(iDfreeCacheTime),
3562                 .special        = NULL,
3563                 .enum_list      = NULL,
3564                 .flags          = FLAG_ADVANCED,
3565         },
3566         {
3567                 .label          = "dfree command",
3568                 .type           = P_STRING,
3569                 .p_class        = P_LOCAL,
3570                 .offset         = LOCAL_VAR(szDfree),
3571                 .special        = NULL,
3572                 .enum_list      = NULL,
3573                 .flags          = FLAG_ADVANCED,
3574         },
3575         {
3576                 .label          = "get quota command",
3577                 .type           = P_STRING,
3578                 .p_class        = P_GLOBAL,
3579                 .offset         = GLOBAL_VAR(szGetQuota),
3580                 .special        = NULL,
3581                 .enum_list      = NULL,
3582                 .flags          = FLAG_ADVANCED,
3583         },
3584         {
3585                 .label          = "set quota command",
3586                 .type           = P_STRING,
3587                 .p_class        = P_GLOBAL,
3588                 .offset         = GLOBAL_VAR(szSetQuota),
3589                 .special        = NULL,
3590                 .enum_list      = NULL,
3591                 .flags          = FLAG_ADVANCED,
3592         },
3593         {
3594                 .label          = "remote announce",
3595                 .type           = P_STRING,
3596                 .p_class        = P_GLOBAL,
3597                 .offset         = GLOBAL_VAR(szRemoteAnnounce),
3598                 .special        = NULL,
3599                 .enum_list      = NULL,
3600                 .flags          = FLAG_ADVANCED,
3601         },
3602         {
3603                 .label          = "remote browse sync",
3604                 .type           = P_STRING,
3605                 .p_class        = P_GLOBAL,
3606                 .offset         = GLOBAL_VAR(szRemoteBrowseSync),
3607                 .special        = NULL,
3608                 .enum_list      = NULL,
3609                 .flags          = FLAG_ADVANCED,
3610         },
3611         {
3612                 .label          = "socket address",
3613                 .type           = P_STRING,
3614                 .p_class        = P_GLOBAL,
3615                 .offset         = GLOBAL_VAR(szSocketAddress),
3616                 .special        = NULL,
3617                 .enum_list      = NULL,
3618                 .flags          = FLAG_ADVANCED,
3619         },
3620         {
3621                 .label          = "nmbd bind explicit broadcast",
3622                 .type           = P_BOOL,
3623                 .p_class        = P_GLOBAL,
3624                 .offset         = GLOBAL_VAR(bNmbdBindExplicitBroadcast),
3625                 .special        = NULL,
3626                 .enum_list      = NULL,
3627                 .flags          = FLAG_ADVANCED,
3628         },
3629         {
3630                 .label          = "homedir map",
3631                 .type           = P_STRING,
3632                 .p_class        = P_GLOBAL,
3633                 .offset         = GLOBAL_VAR(szNISHomeMapName),
3634                 .special        = NULL,
3635                 .enum_list      = NULL,
3636                 .flags          = FLAG_ADVANCED,
3637         },
3638         {
3639                 .label          = "afs username map",
3640                 .type           = P_STRING,
3641                 .p_class        = P_GLOBAL,
3642                 .offset         = GLOBAL_VAR(szAfsUsernameMap),
3643                 .special        = NULL,
3644                 .enum_list      = NULL,
3645                 .flags          = FLAG_ADVANCED,
3646         },
3647         {
3648                 .label          = "afs token lifetime",
3649                 .type           = P_INTEGER,
3650                 .p_class        = P_GLOBAL,
3651                 .offset         = GLOBAL_VAR(iAfsTokenLifetime),
3652                 .special        = NULL,
3653                 .enum_list      = NULL,
3654                 .flags          = FLAG_ADVANCED,
3655         },
3656         {
3657                 .label          = "log nt token command",
3658                 .type           = P_STRING,
3659                 .p_class        = P_GLOBAL,
3660                 .offset         = GLOBAL_VAR(szLogNtTokenCommand),
3661                 .special        = NULL,
3662                 .enum_list      = NULL,
3663                 .flags          = FLAG_ADVANCED,
3664         },
3665         {
3666                 .label          = "NIS homedir",
3667                 .type           = P_BOOL,
3668                 .p_class        = P_GLOBAL,
3669                 .offset         = GLOBAL_VAR(bNISHomeMap),
3670                 .special        = NULL,
3671                 .enum_list      = NULL,
3672                 .flags          = FLAG_ADVANCED,
3673         },
3674         {
3675                 .label          = "-valid",
3676                 .type           = P_BOOL,
3677                 .p_class        = P_LOCAL,
3678                 .offset         = LOCAL_VAR(valid),
3679                 .special        = NULL,
3680                 .enum_list      = NULL,
3681                 .flags          = FLAG_HIDE,
3682         },
3683         {
3684                 .label          = "copy",
3685                 .type           = P_STRING,
3686                 .p_class        = P_LOCAL,
3687                 .offset         = LOCAL_VAR(szCopy),
3688                 .special        = handle_copy,
3689                 .enum_list      = NULL,
3690                 .flags          = FLAG_HIDE,
3691         },
3692         {
3693                 .label          = "include",
3694                 .type           = P_STRING,
3695                 .p_class        = P_LOCAL,
3696                 .offset         = LOCAL_VAR(szInclude),
3697                 .special        = handle_include,
3698                 .enum_list      = NULL,
3699                 .flags          = FLAG_HIDE|FLAG_META,
3700         },
3701         {
3702                 .label          = "preexec",
3703                 .type           = P_STRING,
3704                 .p_class        = P_LOCAL,
3705                 .offset         = LOCAL_VAR(szPreExec),
3706                 .special        = NULL,
3707                 .enum_list      = NULL,
3708                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3709         },
3710         {
3711                 .label          = "exec",
3712                 .type           = P_STRING,
3713                 .p_class        = P_LOCAL,
3714                 .offset         = LOCAL_VAR(szPreExec),
3715                 .special        = NULL,
3716                 .enum_list      = NULL,
3717                 .flags          = FLAG_ADVANCED,
3718         },
3719         {
3720                 .label          = "preexec close",
3721                 .type           = P_BOOL,
3722                 .p_class        = P_LOCAL,
3723                 .offset         = LOCAL_VAR(bPreexecClose),
3724                 .special        = NULL,
3725                 .enum_list      = NULL,
3726                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3727         },
3728         {
3729                 .label          = "postexec",
3730                 .type           = P_STRING,
3731                 .p_class        = P_LOCAL,
3732                 .offset         = LOCAL_VAR(szPostExec),
3733                 .special        = NULL,
3734                 .enum_list      = NULL,
3735                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3736         },
3737         {
3738                 .label          = "root preexec",
3739                 .type           = P_STRING,
3740                 .p_class        = P_LOCAL,
3741                 .offset         = LOCAL_VAR(szRootPreExec),
3742                 .special        = NULL,
3743                 .enum_list      = NULL,
3744                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3745         },
3746         {
3747                 .label          = "root preexec close",
3748                 .type           = P_BOOL,
3749                 .p_class        = P_LOCAL,
3750                 .offset         = LOCAL_VAR(bRootpreexecClose),
3751                 .special        = NULL,
3752                 .enum_list      = NULL,
3753                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3754         },
3755         {
3756                 .label          = "root postexec",
3757                 .type           = P_STRING,
3758                 .p_class        = P_LOCAL,
3759                 .offset         = LOCAL_VAR(szRootPostExec),
3760                 .special        = NULL,
3761                 .enum_list      = NULL,
3762                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3763         },
3764         {
3765                 .label          = "available",
3766                 .type           = P_BOOL,
3767                 .p_class        = P_LOCAL,
3768                 .offset         = LOCAL_VAR(bAvailable),
3769                 .special        = NULL,
3770                 .enum_list      = NULL,
3771                 .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
3772         },
3773         {
3774                 .label          = "registry shares",
3775                 .type           = P_BOOL,
3776                 .p_class        = P_GLOBAL,
3777                 .offset         = GLOBAL_VAR(bRegistryShares),
3778                 .special        = NULL,
3779                 .enum_list      = NULL,
3780                 .flags          = FLAG_ADVANCED,
3781         },
3782         {
3783                 .label          = "usershare allow guests",
3784                 .type           = P_BOOL,
3785                 .p_class        = P_GLOBAL,
3786                 .offset         = GLOBAL_VAR(bUsershareAllowGuests),
3787                 .special        = NULL,
3788                 .enum_list      = NULL,
3789                 .flags          = FLAG_ADVANCED,
3790         },
3791         {
3792                 .label          = "usershare max shares",
3793                 .type           = P_INTEGER,
3794                 .p_class        = P_GLOBAL,
3795                 .offset         = GLOBAL_VAR(iUsershareMaxShares),
3796                 .special        = NULL,
3797                 .enum_list      = NULL,
3798                 .flags          = FLAG_ADVANCED,
3799         },
3800         {
3801                 .label          = "usershare owner only",
3802                 .type           = P_BOOL,
3803                 .p_class        = P_GLOBAL,
3804                 .offset         = GLOBAL_VAR(bUsershareOwnerOnly),
3805                 .special        = NULL,
3806                 .enum_list      = NULL,
3807                 .flags          = FLAG_ADVANCED,
3808         },
3809         {
3810                 .label          = "usershare path",
3811                 .type           = P_STRING,
3812                 .p_class        = P_GLOBAL,
3813                 .offset         = GLOBAL_VAR(szUsersharePath),
3814                 .special        = NULL,
3815                 .enum_list      = NULL,
3816                 .flags          = FLAG_ADVANCED,
3817         },
3818         {
3819                 .label          = "usershare prefix allow list",
3820                 .type           = P_LIST,
3821                 .p_class        = P_GLOBAL,
3822                 .offset         = GLOBAL_VAR(szUsersharePrefixAllowList),
3823                 .special        = NULL,
3824                 .enum_list      = NULL,
3825                 .flags          = FLAG_ADVANCED,
3826         },
3827         {
3828                 .label          = "usershare prefix deny list",
3829                 .type           = P_LIST,
3830                 .p_class        = P_GLOBAL,
3831                 .offset         = GLOBAL_VAR(szUsersharePrefixDenyList),
3832                 .special        = NULL,
3833                 .enum_list      = NULL,
3834                 .flags          = FLAG_ADVANCED,
3835         },
3836         {
3837                 .label          = "usershare template share",
3838                 .type           = P_STRING,
3839                 .p_class        = P_GLOBAL,
3840                 .offset         = GLOBAL_VAR(szUsershareTemplateShare),
3841                 .special        = NULL,
3842                 .enum_list      = NULL,
3843                 .flags          = FLAG_ADVANCED,
3844         },
3845         {
3846                 .label          = "volume",
3847                 .type           = P_STRING,
3848                 .p_class        = P_LOCAL,
3849                 .offset         = LOCAL_VAR(volume),
3850                 .special        = NULL,
3851                 .enum_list      = NULL,
3852                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3853         },
3854         {
3855                 .label          = "fstype",
3856                 .type           = P_STRING,
3857                 .p_class        = P_LOCAL,
3858                 .offset         = LOCAL_VAR(fstype),
3859                 .special        = NULL,
3860                 .enum_list      = NULL,
3861                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3862         },
3863         {
3864                 .label          = "set directory",
3865                 .type           = P_BOOLREV,
3866                 .p_class        = P_LOCAL,
3867                 .offset         = LOCAL_VAR(bNo_set_dir),
3868                 .special        = NULL,
3869                 .enum_list      = NULL,
3870                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3871         },
3872         {
3873                 .label          = "allow insecure wide links",
3874                 .type           = P_BOOL,
3875                 .p_class        = P_GLOBAL,
3876                 .offset         = GLOBAL_VAR(bAllowInsecureWidelinks),
3877                 .special        = NULL,
3878                 .enum_list      = NULL,
3879                 .flags          = FLAG_ADVANCED,
3880         },
3881         {
3882                 .label          = "wide links",
3883                 .type           = P_BOOL,
3884                 .p_class        = P_LOCAL,
3885                 .offset         = LOCAL_VAR(bWidelinks),
3886                 .special        = NULL,
3887                 .enum_list      = NULL,
3888                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3889         },
3890         {
3891                 .label          = "follow symlinks",
3892                 .type           = P_BOOL,
3893                 .p_class        = P_LOCAL,
3894                 .offset         = LOCAL_VAR(bSymlinks),
3895                 .special        = NULL,
3896                 .enum_list      = NULL,
3897                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3898         },
3899         {
3900                 .label          = "dont descend",
3901                 .type           = P_STRING,
3902                 .p_class        = P_LOCAL,
3903                 .offset         = LOCAL_VAR(szDontdescend),
3904                 .special        = NULL,
3905                 .enum_list      = NULL,
3906                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3907         },
3908         {
3909                 .label          = "magic script",
3910                 .type           = P_STRING,
3911                 .p_class        = P_LOCAL,
3912                 .offset         = LOCAL_VAR(szMagicScript),
3913                 .special        = NULL,
3914                 .enum_list      = NULL,
3915                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3916         },
3917         {
3918                 .label          = "magic output",
3919                 .type           = P_STRING,
3920                 .p_class        = P_LOCAL,
3921                 .offset         = LOCAL_VAR(szMagicOutput),
3922                 .special        = NULL,
3923                 .enum_list      = NULL,
3924                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
3925         },
3926         {
3927                 .label          = "delete readonly",
3928                 .type           = P_BOOL,
3929                 .p_class        = P_LOCAL,
3930                 .offset         = LOCAL_VAR(bDeleteReadonly),
3931                 .special        = NULL,
3932                 .enum_list      = NULL,
3933                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3934         },
3935         {
3936                 .label          = "dos filemode",
3937                 .type           = P_BOOL,
3938                 .p_class        = P_LOCAL,
3939                 .offset         = LOCAL_VAR(bDosFilemode),
3940                 .special        = NULL,
3941                 .enum_list      = NULL,
3942                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3943         },
3944         {
3945                 .label          = "dos filetimes",
3946                 .type           = P_BOOL,
3947                 .p_class        = P_LOCAL,
3948                 .offset         = LOCAL_VAR(bDosFiletimes),
3949                 .special        = NULL,
3950                 .enum_list      = NULL,
3951                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3952         },
3953         {
3954                 .label          = "dos filetime resolution",
3955                 .type           = P_BOOL,
3956                 .p_class        = P_LOCAL,
3957                 .offset         = LOCAL_VAR(bDosFiletimeResolution),
3958                 .special        = NULL,
3959                 .enum_list      = NULL,
3960                 .flags          = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
3961         },
3962         {
3963                 .label          = "fake directory create times",
3964                 .type           = P_BOOL,
3965                 .p_class        = P_LOCAL,
3966                 .offset         = LOCAL_VAR(bFakeDirCreateTimes),
3967                 .special        = NULL,
3968                 .enum_list      = NULL,
3969                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3970         },
3971         {
3972                 .label          = "async smb echo handler",
3973                 .type           = P_BOOL,
3974                 .p_class        = P_GLOBAL,
3975                 .offset         = GLOBAL_VAR(bAsyncSMBEchoHandler),
3976                 .special        = NULL,
3977                 .enum_list      = NULL,
3978                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3979         },
3980         {
3981                 .label          = "multicast dns register",
3982                 .type           = P_BOOL,
3983                 .p_class        = P_GLOBAL,
3984                 .offset         = GLOBAL_VAR(bMulticastDnsRegister),
3985                 .special        = NULL,
3986                 .enum_list      = NULL,
3987                 .flags          = FLAG_ADVANCED | FLAG_GLOBAL,
3988         },
3989         {
3990                 .label          = "panic action",
3991                 .type           = P_STRING,
3992                 .p_class        = P_GLOBAL,
3993                 .offset         = GLOBAL_VAR(szPanicAction),
3994                 .special        = NULL,
3995                 .enum_list      = NULL,
3996                 .flags          = FLAG_ADVANCED,
3997         },
3998         {
3999                 .label          = "perfcount module",
4000                 .type           = P_STRING,
4001                 .p_class        = P_GLOBAL,
4002                 .offset         = GLOBAL_VAR(szSMBPerfcountModule),
4003                 .special        = NULL,
4004                 .enum_list      = NULL,
4005                 .flags          = FLAG_ADVANCED,
4006         },
4007
4008         {N_("VFS module options"), P_SEP, P_SEPARATOR},
4009
4010         {
4011                 .label          = "vfs objects",
4012                 .type           = P_LIST,
4013                 .p_class        = P_LOCAL,
4014                 .offset         = LOCAL_VAR(szVfsObjects),
4015                 .special        = NULL,
4016                 .enum_list      = NULL,
4017                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4018         },
4019         {
4020                 .label          = "vfs object",
4021                 .type           = P_LIST,
4022                 .p_class        = P_LOCAL,
4023                 .offset         = LOCAL_VAR(szVfsObjects),
4024                 .special        = NULL,
4025                 .enum_list      = NULL,
4026                 .flags          = FLAG_HIDE,
4027         },
4028
4029
4030         {N_("MSDFS options"), P_SEP, P_SEPARATOR},
4031
4032         {
4033                 .label          = "msdfs root",
4034                 .type           = P_BOOL,
4035                 .p_class        = P_LOCAL,
4036                 .offset         = LOCAL_VAR(bMSDfsRoot),
4037                 .special        = NULL,
4038                 .enum_list      = NULL,
4039                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4040         },
4041         {
4042                 .label          = "msdfs proxy",
4043                 .type           = P_STRING,
4044                 .p_class        = P_LOCAL,
4045                 .offset         = LOCAL_VAR(szMSDfsProxy),
4046                 .special        = NULL,
4047                 .enum_list      = NULL,
4048                 .flags          = FLAG_ADVANCED | FLAG_SHARE,
4049         },
4050         {
4051                 .label          = "host msdfs",
4052                 .type           = P_BOOL,
4053                 .p_class        = P_GLOBAL,
4054                 .offset         = GLOBAL_VAR(bHostMSDfs),
4055                 .special        = NULL,
4056                 .enum_list      = NULL,
4057                 .flags          = FLAG_ADVANCED,
4058         },
4059
4060         {N_("Winbind options"), P_SEP, P_SEPARATOR},
4061
4062         {
4063                 .label          = "passdb expand explicit",
4064                 .type           = P_BOOL,
4065                 .p_class        = P_GLOBAL,
4066                 .offset         = GLOBAL_VAR(bPassdbExpandExplicit),
4067                 .special        = NULL,
4068                 .enum_list      = NULL,
4069                 .flags          = FLAG_ADVANCED,
4070         },
4071         {
4072                 .label          = "idmap backend",
4073                 .type           = P_STRING,
4074                 .p_class        = P_GLOBAL,
4075                 .offset         = GLOBAL_VAR(szIdmapBackend),
4076                 .special        = handle_idmap_backend,
4077                 .enum_list      = NULL,
4078                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
4079         },
4080         {
4081                 .label          = "idmap cache time",
4082                 .type           = P_INTEGER,
4083                 .p_class        = P_GLOBAL,
4084                 .offset         = GLOBAL_VAR(iIdmapCacheTime),
4085                 .special        = NULL,
4086                 .enum_list      = NULL,
4087                 .flags          = FLAG_ADVANCED,
4088         },
4089         {
4090                 .label          = "idmap negative cache time",
4091                 .type           = P_INTEGER,
4092                 .p_class        = P_GLOBAL,
4093                 .offset         = GLOBAL_VAR(iIdmapNegativeCacheTime),
4094                 .special        = NULL,
4095                 .enum_list      = NULL,
4096                 .flags          = FLAG_ADVANCED,
4097         },
4098         {
4099                 .label          = "idmap uid",
4100                 .type           = P_STRING,
4101                 .p_class        = P_GLOBAL,
4102                 .offset         = GLOBAL_VAR(szIdmapUID),
4103                 .special        = handle_idmap_uid,
4104                 .enum_list      = NULL,
4105                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
4106         },
4107         {
4108                 .label          = "winbind uid",
4109                 .type           = P_STRING,
4110                 .p_class        = P_GLOBAL,
4111                 .offset         = GLOBAL_VAR(szIdmapUID),
4112                 .special        = handle_idmap_uid,
4113                 .enum_list      = NULL,
4114                 .flags          = FLAG_HIDE,
4115         },
4116         {
4117                 .label          = "idmap gid",
4118                 .type           = P_STRING,
4119                 .p_class        = P_GLOBAL,
4120                 .offset         = GLOBAL_VAR(szIdmapGID),
4121                 .special        = handle_idmap_gid,
4122                 .enum_list      = NULL,
4123                 .flags          = FLAG_ADVANCED | FLAG_DEPRECATED,
4124         },
4125         {
4126                 .label          = "winbind gid",
4127                 .type           = P_STRING,
4128                 .p_class        = P_GLOBAL,
4129                 .offset         = GLOBAL_VAR(szIdmapGID),
4130                 .special        = handle_idmap_gid,
4131                 .enum_list      = NULL,
4132                 .flags          = FLAG_HIDE,
4133         },
4134         {
4135                 .label          = "template homedir",
4136                 .type           = P_STRING,
4137                 .p_class        = P_GLOBAL,
4138                 .offset         = GLOBAL_VAR(szTemplateHomedir),
4139                 .special        = NULL,
4140                 .enum_list      = NULL,
4141                 .flags          = FLAG_ADVANCED,
4142         },
4143         {
4144                 .label          = "template shell",
4145                 .type           = P_STRING,
4146                 .p_class        = P_GLOBAL,
4147                 .offset         = GLOBAL_VAR(szTemplateShell),
4148                 .special        = NULL,
4149                 .enum_list      = NULL,
4150                 .flags          = FLAG_ADVANCED,
4151         },
4152         {
4153                 .label          = "winbind separator",
4154                 .type           = P_STRING,
4155                 .p_class        = P_GLOBAL,
4156                 .offset         = GLOBAL_VAR(szWinbindSeparator),
4157                 .special        = NULL,
4158                 .enum_list      = NULL,
4159                 .flags          = FLAG_ADVANCED,
4160         },
4161         {
4162                 .label          = "winbind cache time",
4163                 .type           = P_INTEGER,
4164                 .p_class        = P_GLOBAL,
4165                 .offset         = GLOBAL_VAR(winbind_cache_time),
4166                 .special        = NULL,
4167                 .enum_list      = NULL,
4168                 .flags          = FLAG_ADVANCED,
4169         },
4170         {
4171                 .label          = "winbind reconnect delay",
4172                 .type           = P_INTEGER,
4173                 .p_class        = P_GLOBAL,
4174                 .offset         = GLOBAL_VAR(winbind_reconnect_delay),
4175                 .special        = NULL,
4176                 .enum_list      = NULL,
4177                 .flags          = FLAG_ADVANCED,
4178         },
4179         {
4180                 .label          = "winbind max clients",
4181                 .type           = P_INTEGER,
4182                 .p_class        = P_GLOBAL,
4183                 .offset         = GLOBAL_VAR(winbind_max_clients),
4184                 .special        = NULL,
4185                 .enum_list      = NULL,
4186                 .flags          = FLAG_ADVANCED,
4187         },
4188         {
4189                 .label          = "winbind enum users",
4190                 .type           = P_BOOL,
4191                 .p_class        = P_GLOBAL,
4192                 .offset         = GLOBAL_VAR(bWinbindEnumUsers),
4193                 .special        = NULL,
4194                 .enum_list      = NULL,
4195                 .flags          = FLAG_ADVANCED,
4196         },
4197         {
4198                 .label          = "winbind enum groups",
4199                 .type           = P_BOOL,
4200                 .p_class        = P_GLOBAL,
4201                 .offset         = GLOBAL_VAR(bWinbindEnumGroups),
4202                 .special        = NULL,
4203                 .enum_list      = NULL,
4204                 .flags          = FLAG_ADVANCED,
4205         },
4206         {
4207                 .label          = "winbind use default domain",
4208                 .type           = P_BOOL,
4209                 .p_class        = P_GLOBAL,
4210                 .offset         = GLOBAL_VAR(bWinbindUseDefaultDomain),
4211                 .special        = NULL,
4212                 .enum_list      = NULL,
4213                 .flags          = FLAG_ADVANCED,
4214         },
4215         {
4216                 .label          = "winbind trusted domains only",
4217                 .type           = P_BOOL,
4218                 .p_class        = P_GLOBAL,
4219                 .offset         = GLOBAL_VAR(bWinbindTrustedDomainsOnly),
4220                 .special        = NULL,
4221                 .enum_list      = NULL,
4222                 .flags          = FLAG_ADVANCED,
4223         },
4224         {
4225                 .label          = "winbind nested groups",
4226                 .type           = P_BOOL,
4227                 .p_class        = P_GLOBAL,
4228                 .offset         = GLOBAL_VAR(bWinbindNestedGroups),
4229                 .special        = NULL,
4230                 .enum_list      = NULL,
4231                 .flags          = FLAG_ADVANCED,
4232         },
4233         {
4234                 .label          = "winbind expand groups",
4235                 .type           = P_INTEGER,
4236                 .p_class        = P_GLOBAL,
4237                 .offset         = GLOBAL_VAR(winbind_expand_groups),
4238                 .special        = NULL,
4239                 .enum_list      = NULL,
4240                 .flags          = FLAG_ADVANCED,
4241         },
4242         {
4243                 .label          = "winbind nss info",
4244                 .type           = P_LIST,
4245                 .p_class        = P_GLOBAL,
4246                 .offset         = GLOBAL_VAR(szWinbindNssInfo),
4247                 .special        = NULL,
4248                 .enum_list      = NULL,
4249                 .flags          = FLAG_ADVANCED,
4250         },
4251         {
4252                 .label          = "winbind refresh tickets",
4253                 .type           = P_BOOL,
4254                 .p_class        = P_GLOBAL,
4255                 .offset         = GLOBAL_VAR(bWinbindRefreshTickets),
4256                 .special        = NULL,
4257                 .enum_list      = NULL,
4258                 .flags          = FLAG_ADVANCED,
4259         },
4260         {
4261                 .label          = "winbind offline logon",
4262                 .type           = P_BOOL,
4263                 .p_class        = P_GLOBAL,
4264                 .offset         = GLOBAL_VAR(bWinbindOfflineLogon),
4265                 .special        = NULL,
4266                 .enum_list      = NULL,
4267                 .flags          = FLAG_ADVANCED,
4268         },
4269         {
4270                 .label          = "winbind normalize names",
4271                 .type           = P_BOOL,
4272                 .p_class        = P_GLOBAL,
4273                 .offset         = GLOBAL_VAR(bWinbindNormalizeNames),
4274                 .special        = NULL,
4275                 .enum_list      = NULL,
4276                 .flags          = FLAG_ADVANCED,
4277         },
4278         {
4279                 .label          = "winbind rpc only",
4280                 .type           = P_BOOL,
4281                 .p_class        = P_GLOBAL,
4282                 .offset         = GLOBAL_VAR(bWinbindRpcOnly),
4283                 .special        = NULL,
4284                 .enum_list      = NULL,
4285                 .flags          = FLAG_ADVANCED,
4286         },
4287         {
4288                 .label          = "create krb5 conf",
4289                 .type           = P_BOOL,
4290                 .p_class        = P_GLOBAL,
4291                 .offset         = GLOBAL_VAR(bCreateKrb5Conf),
4292                 .special        = NULL,
4293                 .enum_list      = NULL,
4294                 .flags          = FLAG_ADVANCED,
4295         },
4296         {
4297                 .label          = "ncalrpc dir",
4298                 .type           = P_STRING,
4299                 .p_class        = P_GLOBAL,
4300                 .offset         = GLOBAL_VAR(ncalrpc_dir),
4301                 .special        = NULL,
4302                 .enum_list      = NULL,
4303                 .flags          = FLAG_ADVANCED,
4304         },
4305         {
4306                 .label          = "winbind max domain connections",
4307                 .type           = P_INTEGER,
4308                 .p_class        = P_GLOBAL,
4309                 .offset         = GLOBAL_VAR(winbindMaxDomainConnections),
4310                 .special        = NULL,
4311                 .enum_list      = NULL,
4312                 .flags          = FLAG_ADVANCED,
4313         },
4314
4315         {NULL,  P_BOOL,  P_NONE,  0,  NULL,  NULL,  0}
4316 };
4317
4318 /***************************************************************************
4319  Initialise the sDefault parameter structure for the printer values.
4320 ***************************************************************************/
4321
4322 static void init_printer_values(struct loadparm_service *pService)
4323 {
4324         /* choose defaults depending on the type of printing */
4325         switch (pService->iPrinting) {
4326                 case PRINT_BSD:
4327                 case PRINT_AIX:
4328                 case PRINT_LPRNT:
4329                 case PRINT_LPROS2:
4330                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4331                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4332                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4333                         break;
4334
4335                 case PRINT_LPRNG:
4336                 case PRINT_PLP:
4337                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4338                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4339                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
4340                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
4341                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
4342                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
4343                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
4344                         break;
4345
4346                 case PRINT_CUPS:
4347                 case PRINT_IPRINT:
4348 #ifdef HAVE_CUPS
4349                         /* set the lpq command to contain the destination printer
4350                            name only.  This is used by cups_queue_get() */
4351                         string_set(&pService->szLpqcommand, "%p");
4352                         string_set(&pService->szLprmcommand, "");
4353                         string_set(&pService->szPrintcommand, "");
4354                         string_set(&pService->szLppausecommand, "");
4355                         string_set(&pService->szLpresumecommand, "");
4356                         string_set(&pService->szQueuepausecommand, "");
4357                         string_set(&pService->szQueueresumecommand, "");
4358 #else
4359                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
4360                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
4361                         string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
4362                         string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
4363                         string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
4364                         string_set(&pService->szQueuepausecommand, "disable '%p'");
4365                         string_set(&pService->szQueueresumecommand, "enable '%p'");
4366 #endif /* HAVE_CUPS */
4367                         break;
4368
4369                 case PRINT_SYSV:
4370                 case PRINT_HPUX:
4371                         string_set(&pService->szLpqcommand, "lpstat -o%p");
4372                         string_set(&pService->szLprmcommand, "cancel %p-%j");
4373                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
4374                         string_set(&pService->szQueuepausecommand, "disable %p");
4375                         string_set(&pService->szQueueresumecommand, "enable %p");
4376 #ifndef HPUX
4377                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
4378                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
4379 #endif /* HPUX */
4380                         break;
4381
4382                 case PRINT_QNX:
4383                         string_set(&pService->szLpqcommand, "lpq -P%p");
4384                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
4385                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
4386                         break;
4387
4388 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
4389
4390         case PRINT_TEST:
4391         case PRINT_VLP: {
4392                 const char *tdbfile;
4393                 char *tmp;
4394
4395                 tdbfile = talloc_asprintf(
4396                         talloc_tos(), "tdbfile=%s",
4397                         lp_parm_const_string(-1, "vlp", "tdbfile",
4398                                              "/tmp/vlp.tdb"));
4399                 if (tdbfile == NULL) {
4400                         tdbfile="tdbfile=/tmp/vlp.tdb";
4401                 }
4402
4403                 tmp = talloc_asprintf(talloc_tos(), "vlp %s print %%p %%s",
4404                                       tdbfile);
4405                 string_set(&pService->szPrintcommand,
4406                            tmp ? tmp : "vlp print %p %s");
4407                 TALLOC_FREE(tmp);
4408
4409                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lpq %%p",
4410                                       tdbfile);
4411                 string_set(&pService->szLpqcommand,
4412                            tmp ? tmp : "vlp lpq %p");
4413                 TALLOC_FREE(tmp);
4414
4415                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lprm %%p %%j",
4416                                       tdbfile);
4417                 string_set(&pService->szLprmcommand,
4418                            tmp ? tmp : "vlp lprm %p %j");
4419                 TALLOC_FREE(tmp);
4420
4421                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lppause %%p %%j",
4422                                       tdbfile);
4423                 string_set(&pService->szLppausecommand,
4424                            tmp ? tmp : "vlp lppause %p %j");
4425                 TALLOC_FREE(tmp);
4426
4427                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lpresume %%p %%j",
4428                                       tdbfile);
4429                 string_set(&pService->szLpresumecommand,
4430                            tmp ? tmp : "vlp lpresume %p %j");
4431                 TALLOC_FREE(tmp);
4432
4433                 tmp = talloc_asprintf(talloc_tos(), "vlp %s queuepause %%p",
4434                                       tdbfile);
4435                 string_set(&pService->szQueuepausecommand,
4436                            tmp ? tmp : "vlp queuepause %p");
4437                 TALLOC_FREE(tmp);
4438
4439                 tmp = talloc_asprintf(talloc_tos(), "vlp %s queueresume %%p",
4440                                       tdbfile);
4441                 string_set(&pService->szQueueresumecommand,
4442                            tmp ? tmp : "vlp queueresume %p");
4443                 TALLOC_FREE(tmp);
4444
4445                 break;
4446         }
4447 #endif /* DEVELOPER */
4448
4449         }
4450 }
4451 /**
4452  *  Function to return the default value for the maximum number of open
4453  *  file descriptors permitted.  This function tries to consult the
4454  *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
4455  *  the smaller of those.
4456  */
4457 static int max_open_files(void)
4458 {
4459         int sysctl_max = MAX_OPEN_FILES;
4460         int rlimit_max = MAX_OPEN_FILES;
4461
4462 #ifdef HAVE_SYSCTLBYNAME
4463         {
4464                 size_t size = sizeof(sysctl_max);
4465                 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
4466                              0);
4467         }
4468 #endif
4469
4470 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
4471         {
4472                 struct rlimit rl;
4473
4474                 ZERO_STRUCT(rl);
4475
4476                 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
4477                         rlimit_max = rl.rlim_cur;
4478
4479 #if defined(RLIM_INFINITY)
4480                 if(rl.rlim_cur == RLIM_INFINITY)
4481                         rlimit_max = MAX_OPEN_FILES;
4482 #endif
4483         }
4484 #endif
4485
4486         if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
4487                 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
4488                         "minimum Windows limit (%d)\n",
4489                         sysctl_max,
4490                         MIN_OPEN_FILES_WINDOWS));
4491                 sysctl_max = MIN_OPEN_FILES_WINDOWS;
4492         }
4493
4494         if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
4495                 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
4496                         "minimum Windows limit (%d)\n",
4497                         rlimit_max,
4498                         MIN_OPEN_FILES_WINDOWS));
4499                 rlimit_max = MIN_OPEN_FILES_WINDOWS;
4500         }
4501
4502         return MIN(sysctl_max, rlimit_max);
4503 }
4504
4505 /**
4506  * Common part of freeing allocated data for one parameter.
4507  */
4508 static void free_one_parameter_common(void *parm_ptr,
4509                                       struct parm_struct parm)
4510 {
4511         if ((parm.type == P_STRING) ||
4512             (parm.type == P_USTRING))
4513         {
4514                 string_free((char**)parm_ptr);
4515         } else if (parm.type == P_LIST) {
4516                 TALLOC_FREE(*((char***)parm_ptr));
4517         }
4518 }
4519
4520 /**
4521  * Free the allocated data for one parameter for a share
4522  * given as a service struct.
4523  */
4524 static void free_one_parameter(struct loadparm_service *service,
4525                                struct parm_struct parm)
4526 {
4527         void *parm_ptr;
4528
4529         if (parm.p_class != P_LOCAL) {
4530                 return;
4531         }
4532
4533         parm_ptr = lp_parm_ptr(service, &parm);
4534
4535         free_one_parameter_common(parm_ptr, parm);
4536 }
4537
4538 /**
4539  * Free the allocated parameter data of a share given
4540  * as a service struct.
4541  */
4542 static void free_parameters(struct loadparm_service *service)
4543 {
4544         uint32_t i;
4545
4546         for (i=0; parm_table[i].label; i++) {
4547                 free_one_parameter(service, parm_table[i]);
4548         }
4549 }
4550
4551 /**
4552  * Free the allocated data for one parameter for a given share
4553  * specified by an snum.
4554  */
4555 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
4556 {
4557         void *parm_ptr;
4558
4559         if (snum < 0) {
4560                 parm_ptr = lp_parm_ptr(NULL, &parm);
4561         } else if (parm.p_class != P_LOCAL) {
4562                 return;
4563         } else {
4564                 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
4565         }
4566
4567         free_one_parameter_common(parm_ptr, parm);
4568 }
4569
4570 /**
4571  * Free the allocated parameter data for a share specified
4572  * by an snum.
4573  */
4574 static void free_parameters_by_snum(int snum)
4575 {
4576         uint32_t i;
4577
4578         for (i=0; parm_table[i].label; i++) {
4579                 free_one_parameter_by_snum(snum, parm_table[i]);
4580         }
4581 }
4582
4583 /**
4584  * Free the allocated global parameters.
4585  */
4586 static void free_global_parameters(void)
4587 {
4588         free_param_opts(&Globals.param_opt);
4589         free_parameters_by_snum(GLOBAL_SECTION_SNUM);
4590 }
4591
4592 static int map_parameter(const char *pszParmName);
4593
4594 struct lp_stored_option {
4595         struct lp_stored_option *prev, *next;
4596         const char *label;
4597         const char *value;
4598 };
4599
4600 static struct lp_stored_option *stored_options;
4601
4602 /*
4603   save options set by lp_set_cmdline() into a list. This list is
4604   re-applied when we do a globals reset, so that cmdline set options
4605   are sticky across reloads of smb.conf
4606  */
4607 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
4608 {
4609         struct lp_stored_option *entry, *entry_next;
4610         for (entry = stored_options; entry != NULL; entry = entry_next) {
4611                 entry_next = entry->next;
4612                 if (strcmp(pszParmName, entry->label) == 0) {
4613                         DLIST_REMOVE(stored_options, entry);
4614                         talloc_free(entry);
4615                         break;
4616                 }
4617         }
4618
4619         entry = talloc(NULL, struct lp_stored_option);
4620         if (!entry) {
4621                 return false;
4622         }
4623
4624         entry->label = talloc_strdup(entry, pszParmName);
4625         if (!entry->label) {
4626                 talloc_free(entry);
4627                 return false;
4628         }
4629
4630         entry->value = talloc_strdup(entry, pszParmValue);
4631         if (!entry->value) {
4632                 talloc_free(entry);
4633                 return false;
4634         }
4635
4636         DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
4637
4638         return true;
4639 }
4640
4641 static bool apply_lp_set_cmdline(void)
4642 {
4643         struct lp_stored_option *entry = NULL;
4644         for (entry = stored_options; entry != NULL; entry = entry->next) {
4645                 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
4646                         DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
4647                                   entry->label, entry->value));
4648                         return false;
4649                 }
4650         }
4651         return true;
4652 }
4653
4654 /***************************************************************************
4655  Initialise the global parameter structure.
4656 ***************************************************************************/
4657
4658 static void init_globals(bool reinit_globals)
4659 {
4660         static bool done_init = false;
4661         char *s = NULL;
4662         int i;
4663
4664         /* If requested to initialize only once and we've already done it... */
4665         if (!reinit_globals && done_init) {
4666                 /* ... then we have nothing more to do */
4667                 return;
4668         }
4669
4670         if (!done_init) {
4671                 /* The logfile can be set before this is invoked. Free it if so. */
4672                 if (Globals.logfile != NULL) {
4673                         string_free(&Globals.logfile);
4674                         Globals.logfile = NULL;
4675                 }
4676                 done_init = true;
4677         } else {
4678                 free_global_parameters();
4679         }
4680
4681         /* This memset and the free_global_parameters() above will
4682          * wipe out smb.conf options set with lp_set_cmdline().  The
4683          * apply_lp_set_cmdline() call puts these values back in the
4684          * table once the defaults are set */
4685         ZERO_STRUCT(Globals);
4686
4687         for (i = 0; parm_table[i].label; i++) {
4688                 if ((parm_table[i].type == P_STRING ||
4689                      parm_table[i].type == P_USTRING))
4690                 {
4691                         string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
4692                 }
4693         }
4694
4695
4696         string_set(&sDefault.fstype, FSTYPE_STRING);
4697         string_set(&sDefault.szPrintjobUsername, "%U");
4698
4699         init_printer_values(&sDefault);
4700
4701
4702         DEBUG(3, ("Initialising global parameters\n"));
4703
4704         /* Must manually force to upper case here, as this does not go via the handler */
4705         string_set(&Globals.szNetbiosName, myhostname_upper());
4706
4707         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
4708         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
4709
4710         /* use the new 'hash2' method by default, with a prefix of 1 */
4711         string_set(&Globals.szManglingMethod, "hash2");
4712         Globals.mangle_prefix = 1;
4713
4714         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
4715
4716         /* using UTF8 by default allows us to support all chars */
4717         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
4718
4719         /* Use codepage 850 as a default for the dos character set */
4720         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
4721
4722         /*
4723          * Allow the default PASSWD_CHAT to be overridden in local.h.
4724          */
4725         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
4726
4727         string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
4728
4729         string_set(&Globals.szPasswdProgram, "");
4730         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
4731         string_set(&Globals.szStateDir, get_dyn_STATEDIR());
4732         string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
4733         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
4734         string_set(&Globals.szSocketAddress, "0.0.0.0");
4735         /*
4736          * By default support explicit binding to broadcast
4737          * addresses.
4738          */
4739         Globals.bNmbdBindExplicitBroadcast = true;
4740
4741         if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
4742                 smb_panic("init_globals: ENOMEM");
4743         }
4744         string_set(&Globals.szServerString, s);
4745         SAFE_FREE(s);
4746 #ifdef DEVELOPER
4747         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
4748 #endif
4749
4750         string_set(&Globals.szSocketOptions, DEFAULT_SOCKET_OPTIONS);
4751
4752         string_set(&Globals.szLogonDrive, "");
4753         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
4754         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
4755         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
4756
4757         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
4758         string_set(&Globals.szPasswordServer, "*");
4759
4760         Globals.AlgorithmicRidBase = BASE_RID;
4761
4762         Globals.bLoadPrinters = true;
4763         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
4764
4765         Globals.ConfigBackend = config_backend;
4766         Globals.ServerRole = ROLE_AUTO;
4767
4768         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
4769         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
4770         Globals.max_xmit = 0x4104;
4771         Globals.max_mux = 50;   /* This is *needed* for profile support. */
4772         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
4773         Globals.bDisableSpoolss = false;
4774         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
4775         Globals.pwordlevel = 0;
4776         Globals.unamelevel = 0;
4777         Globals.deadtime = 0;
4778         Globals.getwd_cache = true;
4779         Globals.bLargeReadwrite = true;
4780         Globals.max_log_size = 5000;
4781         Globals.max_open_files = max_open_files();
4782         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
4783         Globals.srv_maxprotocol = PROTOCOL_SMB2_02;
4784         Globals.srv_minprotocol = PROTOCOL_CORE;
4785         Globals.security = SEC_USER;
4786         Globals.paranoid_server_security = true;
4787         Globals.bEncryptPasswords = true;
4788         Globals.clientSchannel = Auto;
4789         Globals.serverSchannel = Auto;
4790         Globals.bReadRaw = true;
4791         Globals.bWriteRaw = true;
4792         Globals.bNullPasswords = false;
4793         Globals.bObeyPamRestrictions = false;
4794         Globals.syslog = 1;
4795         Globals.bSyslogOnly = false;
4796         Globals.bTimestampLogs = true;
4797         string_set(&Globals.szLogLevel, "0");
4798         Globals.bDebugPrefixTimestamp = false;
4799         Globals.bDebugHiresTimestamp = true;
4800         Globals.bDebugPid = false;
4801         Globals.bDebugUid = false;
4802         Globals.bDebugClass = false;
4803         Globals.bEnableCoreFiles = true;
4804         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
4805         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
4806         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
4807         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
4808         Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
4809         Globals.lm_interval = 60;
4810 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
4811         Globals.bNISHomeMap = false;
4812 #ifdef WITH_NISPLUS_HOME
4813         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
4814 #else
4815         string_set(&Globals.szNISHomeMapName, "auto.home");
4816 #endif
4817 #endif
4818         Globals.bTimeServer = false;
4819         Globals.bBindInterfacesOnly = false;
4820         Globals.bUnixPasswdSync = false;
4821         Globals.bPamPasswordChange = false;
4822         Globals.bPasswdChatDebug = false;
4823         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
4824         Globals.bNTPipeSupport = true;  /* Do NT pipes by default. */
4825         Globals.bNTStatusSupport = true; /* Use NT status by default. */
4826         Globals.bStatCache = true;      /* use stat cache by default */
4827         Globals.iMaxStatCacheSize = 256; /* 256k by default */
4828         Globals.restrict_anonymous = 0;
4829         Globals.bClientLanManAuth = false;      /* Do NOT use the LanMan hash if it is available */
4830         Globals.bClientPlaintextAuth = false;   /* Do NOT use a plaintext password even if is requested by the server */
4831         Globals.bLanmanAuth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
4832         Globals.bNTLMAuth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
4833         Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
4834         /* Note, that we will also use NTLM2 session security (which is different), if it is available */
4835
4836         Globals.map_to_guest = 0;       /* By Default, "Never" */
4837         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
4838         Globals.enhanced_browsing = true;
4839         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
4840 #ifdef MMAP_BLACKLIST
4841         Globals.bUseMmap = false;
4842 #else
4843         Globals.bUseMmap = true;
4844 #endif
4845         Globals.bUnixExtensions = true;
4846         Globals.bResetOnZeroVC = false;
4847         Globals.bLogWriteableFilesOnExit = false;
4848         Globals.bCreateKrb5Conf = true;
4849         Globals.winbindMaxDomainConnections = 1;
4850
4851         /* hostname lookups can be very expensive and are broken on
4852            a large number of sites (tridge) */
4853         Globals.bHostnameLookups = false;
4854
4855         string_set(&Globals.szPassdbBackend, "tdbsam");
4856         string_set(&Globals.szLdapSuffix, "");
4857         string_set(&Globals.szLdapMachineSuffix, "");
4858         string_set(&Globals.szLdapUserSuffix, "");
4859         string_set(&Globals.szLdapGroupSuffix, "");
4860         string_set(&Globals.szLdapIdmapSuffix, "");
4861
4862         string_set(&Globals.szLdapAdminDn, "");
4863         Globals.ldap_ssl = LDAP_SSL_START_TLS;
4864         Globals.ldap_ssl_ads = false;
4865         Globals.ldap_deref = -1;
4866         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
4867         Globals.ldap_delete_dn = false;
4868         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
4869         Globals.ldap_follow_referral = Auto;
4870         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
4871         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
4872         Globals.ldap_page_size = LDAP_PAGE_SIZE;
4873
4874         Globals.ldap_debug_level = 0;
4875         Globals.ldap_debug_threshold = 10;
4876
4877         /* This is what we tell the afs client. in reality we set the token 
4878          * to never expire, though, when this runs out the afs client will 
4879          * forget the token. Set to 0 to get NEVERDATE.*/
4880         Globals.iAfsTokenLifetime = 604800;
4881         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
4882
4883 /* these parameters are set to defaults that are more appropriate
4884    for the increasing samba install base:
4885
4886    as a member of the workgroup, that will possibly become a
4887    _local_ master browser (lm = true).  this is opposed to a forced
4888    local master browser startup (pm = true).
4889
4890    doesn't provide WINS server service by default (wsupp = false),
4891    and doesn't provide domain master browser services by default, either.
4892
4893 */
4894
4895         Globals.bMsAddPrinterWizard = true;
4896         Globals.os_level = 20;
4897         Globals.bLocalMaster = true;
4898         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
4899         Globals.bDomainLogons = false;
4900         Globals.bBrowseList = true;
4901         Globals.bWINSsupport = false;
4902         Globals.bWINSproxy = false;
4903
4904         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
4905         Globals.InitLogonDelay = 100; /* 100 ms default delay */
4906
4907         Globals.bWINSdnsProxy = true;
4908
4909         Globals.bAllowTrustedDomains = true;
4910         string_set(&Globals.szIdmapBackend, "tdb");
4911
4912         string_set(&Globals.szTemplateShell, "/bin/false");
4913         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
4914         string_set(&Globals.szWinbindSeparator, "\\");
4915
4916         string_set(&Globals.szCupsServer, "");
4917         string_set(&Globals.szIPrintServer, "");
4918
4919         string_set(&Globals.ctdbdSocket, "");
4920         Globals.szClusterAddresses = NULL;
4921         Globals.clustering = false;
4922         Globals.ctdb_timeout = 0;
4923         Globals.ctdb_locktime_warn_threshold = 0;
4924
4925         Globals.winbind_cache_time = 300;       /* 5 minutes */
4926         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
4927         Globals.winbind_max_clients = 200;
4928         Globals.bWinbindEnumUsers = false;
4929         Globals.bWinbindEnumGroups = false;
4930         Globals.bWinbindUseDefaultDomain = false;
4931         Globals.bWinbindTrustedDomainsOnly = false;
4932         Globals.bWinbindNestedGroups = true;
4933         Globals.winbind_expand_groups = 1;
4934         Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
4935         Globals.bWinbindRefreshTickets = false;
4936         Globals.bWinbindOfflineLogon = false;
4937
4938         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
4939         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
4940
4941         Globals.bPassdbExpandExplicit = false;
4942
4943         Globals.name_cache_timeout = 660; /* In seconds */
4944
4945         Globals.bUseSpnego = true;
4946         Globals.bClientUseSpnego = true;
4947
4948         Globals.client_signing = SMB_SIGNING_DEFAULT;
4949         Globals.server_signing = SMB_SIGNING_DEFAULT;
4950
4951         Globals.bDeferSharingViolations = true;
4952         string_set(&Globals.smb_ports, SMB_PORTS);
4953
4954         Globals.bEnablePrivileges = true;
4955         Globals.bHostMSDfs        = true;
4956         Globals.bASUSupport       = false;
4957
4958         /* User defined shares. */
4959         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
4960                 smb_panic("init_globals: ENOMEM");
4961         }
4962         string_set(&Globals.szUsersharePath, s);
4963         SAFE_FREE(s);
4964         string_set(&Globals.szUsershareTemplateShare, "");
4965         Globals.iUsershareMaxShares = 0;
4966         /* By default disallow sharing of directories not owned by the sharer. */
4967         Globals.bUsershareOwnerOnly = true;
4968         /* By default disallow guest access to usershares. */
4969         Globals.bUsershareAllowGuests = false;
4970
4971         Globals.iKeepalive = DEFAULT_KEEPALIVE;
4972
4973         /* By default no shares out of the registry */
4974         Globals.bRegistryShares = false;
4975
4976         Globals.iminreceivefile = 0;
4977
4978         Globals.bMapUntrustedToDomain = false;
4979         Globals.bMulticastDnsRegister = true;
4980
4981         Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
4982         Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
4983         Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
4984         Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
4985
4986         string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
4987
4988         /* Now put back the settings that were set with lp_set_cmdline() */
4989         apply_lp_set_cmdline();
4990 }
4991
4992 /*******************************************************************
4993  Convenience routine to grab string parameters into temporary memory
4994  and run standard_sub_basic on them. The buffers can be written to by
4995  callers without affecting the source string.
4996 ********************************************************************/
4997
4998 static char *lp_string(const char *s)
4999 {
5000         char *ret;
5001         TALLOC_CTX *ctx = talloc_tos();
5002
5003         /* The follow debug is useful for tracking down memory problems
5004            especially if you have an inner loop that is calling a lp_*()
5005            function that returns a string.  Perhaps this debug should be
5006            present all the time? */
5007
5008 #if 0
5009         DEBUG(10, ("lp_string(%s)\n", s));
5010 #endif
5011         if (!s) {
5012                 return NULL;
5013         }
5014
5015         ret = talloc_sub_basic(ctx,
5016                         get_current_username(),
5017                         current_user_info.domain,
5018                         s);
5019         if (trim_char(ret, '\"', '\"')) {
5020                 if (strchr(ret,'\"') != NULL) {
5021                         TALLOC_FREE(ret);
5022                         ret = talloc_sub_basic(ctx,
5023                                         get_current_username(),
5024                                         current_user_info.domain,
5025                                         s);
5026                 }
5027         }
5028         return ret;
5029 }
5030
5031 /*
5032    In this section all the functions that are used to access the
5033    parameters from the rest of the program are defined
5034 */
5035
5036 #define FN_GLOBAL_STRING(fn_name,ptr) \
5037  char *lp_ ## fn_name(void) {return(lp_string(*(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
5038 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
5039  const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
5040 #define FN_GLOBAL_LIST(fn_name,ptr) \
5041  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
5042 #define FN_GLOBAL_BOOL(fn_name,ptr) \
5043  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
5044 #define FN_GLOBAL_CHAR(fn_name,ptr) \
5045  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
5046 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
5047  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
5048
5049 #define FN_LOCAL_STRING(fn_name,val) \
5050  char *lp_ ## fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
5051 #define FN_LOCAL_CONST_STRING(fn_name,val) \
5052  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
5053 #define FN_LOCAL_LIST(fn_name,val) \
5054  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5055 #define FN_LOCAL_BOOL(fn_name,val) \
5056  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5057 #define FN_LOCAL_INTEGER(fn_name,val) \
5058  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5059
5060 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
5061  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5062 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
5063  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5064 #define FN_LOCAL_CHAR(fn_name,val) \
5065  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5066
5067 FN_GLOBAL_BOOL(allow_insecure_widelinks, bAllowInsecureWidelinks)
5068 FN_GLOBAL_BOOL(allow_trusted_domains, bAllowTrustedDomains)
5069 FN_GLOBAL_BOOL(async_smb_echo_handler, bAsyncSMBEchoHandler)
5070 FN_GLOBAL_BOOL(bind_interfaces_only, bBindInterfacesOnly)
5071 FN_GLOBAL_BOOL(browse_list, bBrowseList)
5072 FN_GLOBAL_BOOL(client_lanman_auth, bClientLanManAuth)
5073 FN_GLOBAL_BOOL(client_ntlmv2_auth, bClientNTLMv2Auth)
5074 FN_GLOBAL_BOOL(client_plaintext_auth, bClientPlaintextAuth)
5075 FN_GLOBAL_BOOL(client_use_spnego, bClientUseSpnego)
5076 FN_GLOBAL_BOOL(client_use_spnego_principal, client_use_spnego_principal)
5077 FN_GLOBAL_BOOL(clustering, clustering)
5078 FN_GLOBAL_BOOL(create_krb5_conf, bCreateKrb5Conf)
5079 FN_GLOBAL_BOOL(debug_class, bDebugClass)
5080 FN_GLOBAL_BOOL(debug_hires_timestamp, bDebugHiresTimestamp)
5081 FN_GLOBAL_BOOL(debug_pid, bDebugPid)
5082 FN_GLOBAL_BOOL(debug_prefix_timestamp, bDebugPrefixTimestamp)
5083 FN_GLOBAL_BOOL(debug_uid, bDebugUid)
5084 FN_GLOBAL_BOOL(defer_sharing_violations, bDeferSharingViolations)
5085 FN_GLOBAL_BOOL(disable_netbios, bDisableNetbios)
5086 FN_GLOBAL_BOOL(_disable_spoolss, bDisableSpoolss)
5087 FN_GLOBAL_BOOL(dns_proxy, bWINSdnsProxy)
5088 FN_GLOBAL_BOOL(enable_asu_support, bASUSupport)
5089 FN_GLOBAL_BOOL(enable_core_files, bEnableCoreFiles)
5090 FN_GLOBAL_BOOL(enable_privileges, bEnablePrivileges)
5091 FN_GLOBAL_BOOL(encrypted_passwords, bEncryptPasswords)
5092 FN_GLOBAL_BOOL(enhanced_browsing, enhanced_browsing)
5093 FN_GLOBAL_BOOL(getwd_cache, getwd_cache)
5094 FN_GLOBAL_BOOL(host_msdfs, bHostMSDfs)
5095 FN_GLOBAL_BOOL(hostname_lookups, bHostnameLookups)
5096 FN_GLOBAL_BOOL(lanman_auth, bLanmanAuth)
5097 FN_GLOBAL_BOOL(large_readwrite, bLargeReadwrite)
5098 FN_GLOBAL_BOOL(ldap_delete_dn, ldap_delete_dn)
5099 FN_GLOBAL_BOOL(ldap_ssl_ads, ldap_ssl_ads)
5100 FN_GLOBAL_BOOL(load_printers, bLoadPrinters)
5101 FN_GLOBAL_BOOL(local_master, bLocalMaster)
5102 FN_GLOBAL_BOOL(log_writeable_files_on_exit, bLogWriteableFilesOnExit)
5103 FN_GLOBAL_BOOL(map_untrusted_to_domain, bMapUntrustedToDomain)
5104 FN_GLOBAL_BOOL(ms_add_printer_wizard, bMsAddPrinterWizard)
5105 FN_GLOBAL_BOOL(multicast_dns_register, bMulticastDnsRegister)
5106 FN_GLOBAL_BOOL(nis_home_map, bNISHomeMap)
5107 FN_GLOBAL_BOOL(nmbd_bind_explicit_broadcast, bNmbdBindExplicitBroadcast)
5108 FN_GLOBAL_BOOL(ntlm_auth, bNTLMAuth)
5109 FN_GLOBAL_BOOL(nt_pipe_support, bNTPipeSupport)
5110 FN_GLOBAL_BOOL(nt_status_support, bNTStatusSupport)
5111 FN_GLOBAL_BOOL(null_passwords, bNullPasswords)
5112 FN_GLOBAL_BOOL(obey_pam_restrictions, bObeyPamRestrictions)
5113 FN_GLOBAL_BOOL(pam_password_change, bPamPasswordChange)
5114 FN_GLOBAL_BOOL(paranoid_server_security, paranoid_server_security)
5115 FN_GLOBAL_BOOL(passdb_expand_explicit, bPassdbExpandExplicit)
5116 FN_GLOBAL_BOOL(passwd_chat_debug, bPasswdChatDebug)
5117 FN_GLOBAL_BOOL(registry_shares, bRegistryShares)
5118 FN_GLOBAL_BOOL(reset_on_zero_vc, bResetOnZeroVC)
5119 FN_GLOBAL_BOOL(stat_cache, bStatCache)
5120 FN_GLOBAL_BOOL(syslog_only, bSyslogOnly)
5121 FN_GLOBAL_BOOL(timestamp_logs, bTimestampLogs)
5122 FN_GLOBAL_BOOL(unix_extensions, bUnixExtensions)
5123 FN_GLOBAL_BOOL(unix_password_sync, bUnixPasswdSync)
5124 FN_GLOBAL_BOOL(use_mmap, bUseMmap)
5125 FN_GLOBAL_BOOL(usershare_allow_guests, bUsershareAllowGuests)
5126 FN_GLOBAL_BOOL(usershare_owner_only, bUsershareOwnerOnly)
5127 FN_GLOBAL_BOOL(use_spnego, bUseSpnego)
5128 FN_GLOBAL_BOOL(utmp, bUtmp)
5129 FN_GLOBAL_BOOL(we_are_a_wins_server, bWINSsupport)
5130 FN_GLOBAL_BOOL(winbind_enum_groups, bWinbindEnumGroups)
5131 FN_GLOBAL_BOOL(winbind_enum_users, bWinbindEnumUsers)
5132 FN_GLOBAL_BOOL(winbind_nested_groups, bWinbindNestedGroups)
5133 FN_GLOBAL_BOOL(winbind_normalize_names, bWinbindNormalizeNames)
5134 FN_GLOBAL_BOOL(winbind_offline_logon, bWinbindOfflineLogon)
5135 FN_GLOBAL_BOOL(winbind_refresh_tickets, bWinbindRefreshTickets)
5136 FN_GLOBAL_BOOL(winbind_rpc_only, bWinbindRpcOnly)
5137 FN_GLOBAL_BOOL(winbind_trusted_domains_only, bWinbindTrustedDomainsOnly)
5138 FN_GLOBAL_BOOL(winbind_use_default_domain, bWinbindUseDefaultDomain)
5139 FN_GLOBAL_BOOL(wins_proxy, bWINSproxy)
5140 FN_GLOBAL_CONST_STRING(afs_username_map, szAfsUsernameMap)
5141 FN_GLOBAL_CONST_STRING(dedicated_keytab_file, szDedicatedKeytabFile)
5142 FN_GLOBAL_CONST_STRING(dnsdomain, szDnsDomain)
5143 FN_GLOBAL_CONST_STRING(dos_charset, dos_charset)
5144 FN_GLOBAL_CONST_STRING(guestaccount, szGuestaccount)
5145 FN_GLOBAL_CONST_STRING(idmap_backend, szIdmapBackend)
5146 FN_GLOBAL_CONST_STRING(lockdir, szLockDir)
5147 FN_GLOBAL_CONST_STRING(logon_drive, szLogonDrive)
5148 FN_GLOBAL_CONST_STRING(logon_home, szLogonHome)
5149 FN_GLOBAL_CONST_STRING(logon_path, szLogonPath)
5150 FN_GLOBAL_CONST_STRING(logon_script, szLogonScript)
5151 FN_GLOBAL_CONST_STRING(name_resolve_order, szNameResolveOrder)
5152 FN_GLOBAL_CONST_STRING(ncalrpc_dir, ncalrpc_dir)
5153 FN_GLOBAL_CONST_STRING(netbios_name, szNetbiosName)
5154 FN_GLOBAL_CONST_STRING(netbios_scope, szNetbiosScope)
5155 FN_GLOBAL_CONST_STRING(passdb_backend, szPassdbBackend)
5156 FN_GLOBAL_CONST_STRING(passwordserver, szPasswordServer)
5157 FN_GLOBAL_CONST_STRING(piddir, szPidDir)
5158 FN_GLOBAL_CONST_STRING(private_dir, szPrivateDir)
5159 FN_GLOBAL_CONST_STRING(realm, szRealmUpper)
5160 FN_GLOBAL_CONST_STRING(smb_passwd_file, szSMBPasswdFile)
5161 FN_GLOBAL_CONST_STRING(smb_ports, smb_ports)
5162 FN_GLOBAL_CONST_STRING(socket_options, szSocketOptions)
5163 FN_GLOBAL_CONST_STRING(template_homedir, szTemplateHomedir)
5164 FN_GLOBAL_CONST_STRING(template_shell, szTemplateShell)
5165 FN_GLOBAL_CONST_STRING(unix_charset, unix_charset)
5166 FN_GLOBAL_CONST_STRING(utmpdir, szUtmpDir)
5167 FN_GLOBAL_CONST_STRING(winbind_separator, szWinbindSeparator)
5168 FN_GLOBAL_CONST_STRING(workgroup, szWorkgroup)
5169 FN_GLOBAL_CONST_STRING(wtmpdir, szWtmpDir)
5170 FN_GLOBAL_INTEGER(acl_compatibility, iAclCompat)
5171 FN_GLOBAL_INTEGER(afs_token_lifetime, iAfsTokenLifetime)
5172 FN_GLOBAL_INTEGER(algorithmic_rid_base, AlgorithmicRidBase)
5173 FN_GLOBAL_INTEGER(client_ldap_sasl_wrapping, client_ldap_sasl_wrapping)
5174 FN_GLOBAL_INTEGER(client_schannel, clientSchannel)
5175 FN_GLOBAL_INTEGER(client_signing, client_signing)
5176 FN_GLOBAL_INTEGER(config_backend, ConfigBackend)
5177 FN_GLOBAL_INTEGER(ctdb_locktime_warn_threshold, ctdb_locktime_warn_threshold)
5178 FN_GLOBAL_INTEGER(ctdb_timeout, ctdb_timeout)
5179 FN_GLOBAL_INTEGER(cups_connection_timeout, cups_connection_timeout)
5180 FN_GLOBAL_INTEGER(deadtime, deadtime)
5181 FN_GLOBAL_INTEGER(idmap_cache_time, iIdmapCacheTime)
5182 FN_GLOBAL_INTEGER(idmap_negative_cache_time, iIdmapNegativeCacheTime)
5183 FN_GLOBAL_INTEGER(init_logon_delay, InitLogonDelay)
5184 FN_GLOBAL_INTEGER(keepalive, iKeepalive)
5185 FN_GLOBAL_INTEGER(kerberos_method, iKerberosMethod)
5186 FN_GLOBAL_INTEGER(ldap_connection_timeout, ldap_connection_timeout)
5187 FN_GLOBAL_INTEGER(ldap_debug_level, ldap_debug_level)
5188 FN_GLOBAL_INTEGER(ldap_debug_threshold, ldap_debug_threshold)
5189 FN_GLOBAL_INTEGER(ldap_deref, ldap_deref)
5190 FN_GLOBAL_INTEGER(ldap_follow_referral, ldap_follow_referral)
5191 FN_GLOBAL_INTEGER(ldap_page_size, ldap_page_size)
5192 FN_GLOBAL_INTEGER(ldap_passwd_sync, ldap_passwd_sync)
5193 FN_GLOBAL_INTEGER(ldap_replication_sleep, ldap_replication_sleep)
5194 FN_GLOBAL_INTEGER(ldap_ssl, ldap_ssl)
5195 FN_GLOBAL_INTEGER(ldap_timeout, ldap_timeout)
5196 FN_GLOBAL_INTEGER(lm_announce, lm_announce)
5197 FN_GLOBAL_INTEGER(lm_interval, lm_interval)
5198 FN_GLOBAL_INTEGER(lock_spin_time, iLockSpinTime)
5199 FN_GLOBAL_INTEGER(lpqcachetime, lpqcachetime)
5200 FN_GLOBAL_INTEGER(machine_password_timeout, machine_password_timeout)
5201 FN_GLOBAL_INTEGER(mangle_prefix, mangle_prefix)
5202 FN_GLOBAL_INTEGER(map_to_guest, map_to_guest)
5203 FN_GLOBAL_INTEGER(maxdisksize, maxdisksize)
5204 FN_GLOBAL_INTEGER(max_log_size, max_log_size)
5205 FN_GLOBAL_INTEGER(maxmux, max_mux)
5206 FN_GLOBAL_INTEGER(max_open_files, max_open_files)
5207 FN_GLOBAL_INTEGER(max_smbd_processes, iMaxSmbdProcesses)
5208 FN_GLOBAL_INTEGER(max_stat_cache_size, iMaxStatCacheSize)
5209 FN_GLOBAL_INTEGER(max_ttl, max_ttl)
5210 FN_GLOBAL_INTEGER(max_wins_ttl, max_wins_ttl)
5211 FN_GLOBAL_INTEGER(maxxmit, max_xmit)
5212 FN_GLOBAL_INTEGER(min_wins_ttl, min_wins_ttl)
5213 FN_GLOBAL_INTEGER(name_cache_timeout, name_cache_timeout)
5214 FN_GLOBAL_INTEGER(open_files_db_hash_size, open_files_db_hash_size)
5215 FN_GLOBAL_INTEGER(oplock_break_wait_time, oplock_break_wait_time)
5216 FN_GLOBAL_INTEGER(os_level, os_level)
5217 FN_GLOBAL_INTEGER(passwd_chat_timeout, iPasswdChatTimeout)
5218 FN_GLOBAL_INTEGER(passwordlevel, pwordlevel)
5219 FN_GLOBAL_INTEGER(printcap_cache_time, PrintcapCacheTime)
5220 FN_GLOBAL_INTEGER(restrict_anonymous, restrict_anonymous)
5221 FN_GLOBAL_INTEGER(security, security)
5222 FN_GLOBAL_INTEGER(server_schannel, serverSchannel)
5223 FN_GLOBAL_INTEGER(server_signing, server_signing)
5224 FN_GLOBAL_INTEGER(smb2_max_read, ismb2_max_read)
5225 FN_GLOBAL_INTEGER(smb2_max_trans, ismb2_max_trans)
5226 FN_GLOBAL_INTEGER(smb2_max_write, ismb2_max_write)
5227 FN_GLOBAL_INTEGER(srv_maxprotocol, srv_maxprotocol)
5228 FN_GLOBAL_INTEGER(srv_minprotocol, srv_minprotocol)
5229 FN_GLOBAL_INTEGER(syslog, syslog)
5230 FN_GLOBAL_INTEGER(usernamelevel, unamelevel)
5231 FN_GLOBAL_INTEGER(username_map_cache_time, iUsernameMapCacheTime)
5232 FN_GLOBAL_INTEGER(usershare_max_shares, iUsershareMaxShares)
5233 FN_GLOBAL_INTEGER(winbind_cache_time, winbind_cache_time)
5234 FN_GLOBAL_INTEGER(winbind_expand_groups, winbind_expand_groups)
5235 FN_GLOBAL_INTEGER(winbind_max_clients, winbind_max_clients)
5236 FN_GLOBAL_INTEGER(winbind_reconnect_delay, winbind_reconnect_delay)
5237 FN_GLOBAL_LIST(auth_methods, AuthMethods)
5238 FN_GLOBAL_LIST(cluster_addresses, szClusterAddresses)
5239 FN_GLOBAL_LIST(eventlog_list, szEventLogs)
5240 FN_GLOBAL_LIST(init_logon_delayed_hosts, szInitLogonDelayedHosts)
5241 FN_GLOBAL_LIST(interfaces, szInterfaces)
5242 FN_GLOBAL_LIST(netbios_aliases, szNetbiosAliases)
5243 FN_GLOBAL_LIST(preload_modules, szPreloadModules)
5244 FN_GLOBAL_LIST(svcctl_list, szServicesList)
5245 FN_GLOBAL_LIST(usershare_prefix_allow_list, szUsersharePrefixAllowList)
5246 FN_GLOBAL_LIST(usershare_prefix_deny_list, szUsersharePrefixDenyList)
5247 FN_GLOBAL_LIST(winbind_nss_info, szWinbindNssInfo)
5248 FN_GLOBAL_LIST(wins_server_list, szWINSservers)
5249 FN_GLOBAL_STRING(abort_shutdown_script, szAbortShutdownScript)
5250 FN_GLOBAL_STRING(addgroup_script, szAddGroupScript)
5251 FN_GLOBAL_STRING(addmachine_script, szAddMachineScript)
5252 FN_GLOBAL_STRING(addport_cmd, szAddPortCommand)
5253 FN_GLOBAL_STRING(addprinter_cmd, szAddPrinterCommand)
5254 FN_GLOBAL_STRING(add_share_cmd, szAddShareCommand)
5255 FN_GLOBAL_STRING(adduser_script, szAddUserScript)
5256 FN_GLOBAL_STRING(addusertogroup_script, szAddUserToGroupScript)
5257 FN_GLOBAL_STRING(auto_services, szAutoServices)
5258 FN_GLOBAL_STRING(change_share_cmd, szChangeShareCommand)
5259 FN_GLOBAL_STRING(check_password_script, szCheckPasswordScript)
5260 FN_GLOBAL_STRING(configfile, szConfigFile)
5261 FN_GLOBAL_STRING(cups_server, szCupsServer)
5262 FN_GLOBAL_STRING(defaultservice, szDefaultService)
5263 FN_GLOBAL_STRING(deleteprinter_cmd, szDeletePrinterCommand)
5264 FN_GLOBAL_STRING(delete_share_cmd, szDeleteShareCommand)
5265 FN_GLOBAL_STRING(delgroup_script, szDelGroupScript)
5266 FN_GLOBAL_STRING(deluserfromgroup_script, szDelUserFromGroupScript)
5267 FN_GLOBAL_STRING(deluser_script, szDelUserScript)
5268 FN_GLOBAL_STRING(enumports_cmd, szEnumPortsCommand)
5269 FN_GLOBAL_STRING(get_quota_command, szGetQuota)
5270 FN_GLOBAL_STRING(iprint_server, szIPrintServer)
5271 FN_GLOBAL_STRING(ldap_admin_dn, szLdapAdminDn)
5272 FN_GLOBAL_STRING(ldap_suffix, szLdapSuffix)
5273 FN_GLOBAL_STRING(logfile, logfile)
5274 FN_GLOBAL_STRING(log_nt_token_command, szLogNtTokenCommand)
5275 FN_GLOBAL_STRING(mangling_method, szManglingMethod)
5276 FN_GLOBAL_STRING(msg_command, szMsgCommand)
5277 FN_GLOBAL_STRING(nis_home_map_name, szNISHomeMapName)
5278 FN_GLOBAL_STRING(os2_driver_map, szOs2DriverMap)
5279 FN_GLOBAL_STRING(panic_action, szPanicAction)
5280 FN_GLOBAL_STRING(passwd_chat, szPasswdChat)
5281 FN_GLOBAL_STRING(passwd_program, szPasswdProgram)
5282 FN_GLOBAL_STRING(perfcount_module, szSMBPerfcountModule)
5283 FN_GLOBAL_STRING(remote_announce, szRemoteAnnounce)
5284 FN_GLOBAL_STRING(remote_browse_sync, szRemoteBrowseSync)
5285 FN_GLOBAL_STRING(renameuser_script, szRenameUserScript)
5286 FN_GLOBAL_STRING(rootdir, szRootdir)
5287 FN_GLOBAL_STRING(serverstring, szServerString)
5288 FN_GLOBAL_STRING(setprimarygroup_script, szSetPrimaryGroupScript)
5289 FN_GLOBAL_STRING(set_quota_command, szSetQuota)
5290 FN_GLOBAL_STRING(shutdown_script, szShutdownScript)
5291 FN_GLOBAL_STRING(username_map_script, szUsernameMapScript)
5292 FN_GLOBAL_STRING(username_map, szUsernameMap)
5293 FN_GLOBAL_STRING(usershare_path, szUsersharePath)
5294 FN_GLOBAL_STRING(wins_hook, szWINSHook)
5295 static FN_GLOBAL_BOOL(domain_logons, bDomainLogons)
5296 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
5297 static FN_GLOBAL_BOOL(time_server, bTimeServer)
5298 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
5299 static FN_GLOBAL_CONST_STRING(_ctdbd_socket, ctdbdSocket)
5300 static FN_GLOBAL_INTEGER(_server_role, ServerRole)
5301
5302 /* If lp_statedir() and lp_cachedir() are explicitely set during the
5303  * build process or in smb.conf, we use that value.  Otherwise they
5304  * default to the value of lp_lockdir(). */
5305 const char *lp_statedir(void) {
5306         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
5307             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
5308                 return(*(char **)(&Globals.szStateDir) ?
5309                        *(char **)(&Globals.szStateDir) : "");
5310         else
5311                 return(*(char **)(&Globals.szLockDir) ?
5312                        *(char **)(&Globals.szLockDir) : "");
5313 }
5314 const char *lp_cachedir(void) {
5315         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
5316             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
5317                 return(*(char **)(&Globals.szCacheDir) ?
5318                        *(char **)(&Globals.szCacheDir) : "");
5319         else
5320                 return(*(char **)(&Globals.szLockDir) ?
5321                        *(char **)(&Globals.szLockDir) : "");
5322 }
5323 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
5324                   winbindMaxDomainConnections)
5325
5326 int lp_winbind_max_domain_connections(void)
5327 {
5328         if (lp_winbind_offline_logon() &&
5329             lp_winbind_max_domain_connections_int() > 1) {
5330                 DEBUG(1, ("offline logons active, restricting max domain "
5331                           "connections to 1\n"));
5332                 return 1;
5333         }
5334         return MAX(1, lp_winbind_max_domain_connections_int());
5335 }
5336
5337 int lp_smb2_max_credits(void)
5338 {
5339         if (Globals.ismb2_max_credits == 0) {
5340                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
5341         }
5342         return Globals.ismb2_max_credits;
5343 }
5344 int lp_cups_encrypt(void)
5345 {
5346         int result = 0;
5347 #ifdef HAVE_HTTPCONNECTENCRYPT
5348         switch (Globals.CupsEncrypt) {
5349                 case Auto:
5350                         result = HTTP_ENCRYPT_REQUIRED;
5351                         break;
5352                 case true:
5353                         result = HTTP_ENCRYPT_ALWAYS;
5354                         break;
5355                 case false:
5356                         result = HTTP_ENCRYPT_NEVER;
5357                         break;
5358         }
5359 #endif
5360         return result;
5361 }
5362
5363 #include "lib/param/param_functions.c"
5364
5365 FN_LOCAL_STRING(servicename, szService)
5366 FN_LOCAL_CONST_STRING(const_servicename, szService)
5367
5368 /* local prototypes */
5369
5370 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5371 static const char *get_boolean(bool bool_value);
5372 static int getservicebyname(const char *pszServiceName,
5373                             struct loadparm_service *pserviceDest);
5374 static void copy_service(struct loadparm_service *pserviceDest,
5375                          struct loadparm_service *pserviceSource,
5376                          struct bitmap *pcopymapDest);
5377 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5378                          void *userdata);
5379 static bool do_section(const char *pszSectionName, void *userdata);
5380 static void init_copymap(struct loadparm_service *pservice);
5381 static bool hash_a_service(const char *name, int number);
5382 static void free_service_byindex(int iService);
5383 static void show_parameter(int parmIndex);
5384 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5385
5386 /*
5387  * This is a helper function for parametrical options support.  It returns a
5388  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5389  * parametrical functions are quite simple
5390  */
5391 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
5392                                                            const char *option)
5393 {
5394         bool global_section = false;
5395         char* param_key;
5396         struct parmlist_entry *data;
5397
5398         if (service == NULL) {
5399                 data = Globals.param_opt;
5400                 global_section = true;
5401         } else {
5402                 data = service->param_opt;
5403         }
5404
5405         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
5406                 DEBUG(0,("asprintf failed!\n"));
5407                 return NULL;
5408         }
5409
5410         while (data) {
5411                 if (strwicmp(data->key, param_key) == 0) {
5412                         string_free(&param_key);
5413                         return data;
5414                 }
5415                 data = data->next;
5416         }
5417
5418         if (!global_section) {
5419                 /* Try to fetch the same option but from globals */
5420                 /* but only if we are not already working with Globals */
5421                 data = Globals.param_opt;
5422                 while (data) {
5423                         if (strwicmp(data->key, param_key) == 0) {
5424                                 string_free(&param_key);
5425                                 return data;
5426                         }
5427                         data = data->next;
5428                 }
5429         }
5430
5431         string_free(&param_key);
5432
5433         return NULL;
5434 }
5435
5436 /*
5437  * This is a helper function for parametrical options support.  It returns a
5438  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5439  * parametrical functions are quite simple
5440  */
5441 static struct parmlist_entry *get_parametrics(int snum, const char *type,
5442                                                 const char *option)
5443 {
5444         if (snum >= iNumServices) return NULL;
5445
5446         if (snum < 0) {
5447                 return get_parametrics_by_service(NULL, type, option);
5448         } else {
5449                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
5450         }
5451 }
5452
5453
5454 #define MISSING_PARAMETER(name) \
5455     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5456
5457 /*******************************************************************
5458 convenience routine to return int parameters.
5459 ********************************************************************/
5460 static int lp_int(const char *s)
5461 {
5462
5463         if (!s || !*s) {
5464                 MISSING_PARAMETER(lp_int);
5465                 return (-1);
5466         }
5467
5468         return (int)strtol(s, NULL, 0);
5469 }
5470
5471 /*******************************************************************
5472 convenience routine to return unsigned long parameters.
5473 ********************************************************************/
5474 static unsigned long lp_ulong(const char *s)
5475 {
5476
5477         if (!s || !*s) {
5478                 MISSING_PARAMETER(lp_ulong);
5479                 return (0);
5480         }
5481
5482         return strtoul(s, NULL, 0);
5483 }
5484
5485 /*******************************************************************
5486 convenience routine to return boolean parameters.
5487 ********************************************************************/
5488 static bool lp_bool(const char *s)
5489 {
5490         bool ret = false;
5491
5492         if (!s || !*s) {
5493                 MISSING_PARAMETER(lp_bool);
5494                 return false;
5495         }
5496
5497         if (!set_boolean(s, &ret)) {
5498                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5499                 return false;
5500         }
5501
5502         return ret;
5503 }
5504
5505 /*******************************************************************
5506 convenience routine to return enum parameters.
5507 ********************************************************************/
5508 static int lp_enum(const char *s,const struct enum_list *_enum)
5509 {
5510         int i;
5511
5512         if (!s || !*s || !_enum) {
5513                 MISSING_PARAMETER(lp_enum);
5514                 return (-1);
5515         }
5516
5517         for (i=0; _enum[i].name; i++) {
5518                 if (strequal(_enum[i].name,s))
5519                         return _enum[i].value;
5520         }
5521
5522         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5523         return (-1);
5524 }
5525
5526 #undef MISSING_PARAMETER
5527
5528 /* Return parametric option from a given service. Type is a part of option before ':' */
5529 /* Parametric option has following syntax: 'Type: option = value' */
5530 /* the returned value is talloced on the talloc_tos() */
5531 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
5532 {
5533         struct parmlist_entry *data = get_parametrics(snum, type, option);
5534
5535         if (data == NULL||data->value==NULL) {
5536                 if (def) {
5537                         return lp_string(def);
5538                 } else {
5539                         return NULL;
5540                 }
5541         }
5542
5543         return lp_string(data->value);
5544 }
5545
5546 /* Return parametric option from a given service. Type is a part of option before ':' */
5547 /* Parametric option has following syntax: 'Type: option = value' */
5548 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5549 {
5550         struct parmlist_entry *data = get_parametrics(snum, type, option);
5551
5552         if (data == NULL||data->value==NULL)
5553                 return def;
5554
5555         return data->value;
5556 }
5557
5558 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
5559 {
5560         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
5561
5562         if (data == NULL||data->value==NULL)
5563                 return NULL;
5564
5565         return data->value;
5566 }
5567
5568
5569 /* Return parametric option from a given service. Type is a part of option before ':' */
5570 /* Parametric option has following syntax: 'Type: option = value' */
5571
5572 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5573 {
5574         struct parmlist_entry *data = get_parametrics(snum, type, option);
5575
5576         if (data == NULL||data->value==NULL)
5577                 return (const char **)def;
5578
5579         if (data->list==NULL) {
5580                 data->list = str_list_make_v3(NULL, data->value, NULL);
5581         }
5582
5583         return (const char **)data->list;
5584 }
5585
5586 /* Return parametric option from a given service. Type is a part of option before ':' */
5587 /* Parametric option has following syntax: 'Type: option = value' */
5588
5589 int lp_parm_int(int snum, const char *type, const char *option, int def)
5590 {
5591         struct parmlist_entry *data = get_parametrics(snum, type, option);
5592
5593         if (data && data->value && *data->value)
5594                 return lp_int(data->value);
5595
5596         return def;
5597 }
5598
5599 /* Return parametric option from a given service. Type is a part of option before ':' */
5600 /* Parametric option has following syntax: 'Type: option = value' */
5601
5602 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5603 {
5604         struct parmlist_entry *data = get_parametrics(snum, type, option);
5605
5606         if (data && data->value && *data->value)
5607                 return lp_ulong(data->value);
5608
5609         return def;
5610 }
5611
5612 /* Return parametric option from a given service. Type is a part of option before ':' */
5613 /* Parametric option has following syntax: 'Type: option = value' */
5614
5615 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5616 {
5617         struct parmlist_entry *data = get_parametrics(snum, type, option);
5618
5619         if (data && data->value && *data->value)
5620                 return lp_bool(data->value);
5621
5622         return def;
5623 }
5624
5625 /* Return parametric option from a given service. Type is a part of option before ':' */
5626 /* Parametric option has following syntax: 'Type: option = value' */
5627
5628 int lp_parm_enum(int snum, const char *type, const char *option,
5629                  const struct enum_list *_enum, int def)
5630 {
5631         struct parmlist_entry *data = get_parametrics(snum, type, option);
5632
5633         if (data && data->value && *data->value && _enum)
5634                 return lp_enum(data->value, _enum);
5635
5636         return def;
5637 }
5638
5639
5640 /***************************************************************************
5641  Initialise a service to the defaults.
5642 ***************************************************************************/
5643
5644 static void init_service(struct loadparm_service *pservice)
5645 {
5646         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
5647         copy_service(pservice, &sDefault, NULL);
5648 }
5649
5650
5651 /**
5652  * free a param_opts structure.
5653  * param_opts handling should be moved to talloc;
5654  * then this whole functions reduces to a TALLOC_FREE().
5655  */
5656
5657 static void free_param_opts(struct parmlist_entry **popts)
5658 {
5659         struct parmlist_entry *opt, *next_opt;
5660
5661         if (popts == NULL) {
5662                 return;
5663         }
5664
5665         if (*popts != NULL) {
5666                 DEBUG(5, ("Freeing parametrics:\n"));
5667         }
5668         opt = *popts;
5669         while (opt != NULL) {
5670                 string_free(&opt->key);
5671                 string_free(&opt->value);
5672                 TALLOC_FREE(opt->list);
5673                 next_opt = opt->next;
5674                 SAFE_FREE(opt);
5675                 opt = next_opt;
5676         }
5677         *popts = NULL;
5678 }
5679
5680 /***************************************************************************
5681  Free the dynamically allocated parts of a service struct.
5682 ***************************************************************************/
5683
5684 static void free_service(struct loadparm_service *pservice)
5685 {
5686         if (!pservice)
5687                 return;
5688
5689         if (pservice->szService)
5690                 DEBUG(5, ("free_service: Freeing service %s\n",
5691                        pservice->szService));
5692
5693         free_parameters(pservice);
5694
5695         string_free(&pservice->szService);
5696         TALLOC_FREE(pservice->copymap);
5697
5698         free_param_opts(&pservice->param_opt);
5699
5700         ZERO_STRUCTP(pservice);
5701 }
5702
5703
5704 /***************************************************************************
5705  remove a service indexed in the ServicePtrs array from the ServiceHash
5706  and free the dynamically allocated parts
5707 ***************************************************************************/
5708
5709 static void free_service_byindex(int idx)
5710 {
5711         if ( !LP_SNUM_OK(idx) ) 
5712                 return;
5713
5714         ServicePtrs[idx]->valid = false;
5715         invalid_services[num_invalid_services++] = idx;
5716
5717         /* we have to cleanup the hash record */
5718
5719         if (ServicePtrs[idx]->szService) {
5720                 char *canon_name = canonicalize_servicename(
5721                         talloc_tos(),
5722                         ServicePtrs[idx]->szService );
5723
5724                 dbwrap_delete_bystring(ServiceHash, canon_name );
5725                 TALLOC_FREE(canon_name);
5726         }
5727
5728         free_service(ServicePtrs[idx]);
5729 }
5730
5731 /***************************************************************************
5732  Add a new service to the services array initialising it with the given 
5733  service. 
5734 ***************************************************************************/
5735
5736 static int add_a_service(const struct loadparm_service *pservice, const char *name)
5737 {
5738         int i;
5739         struct loadparm_service tservice;
5740         int num_to_alloc = iNumServices + 1;
5741
5742         tservice = *pservice;
5743
5744         /* it might already exist */
5745         if (name) {
5746                 i = getservicebyname(name, NULL);
5747                 if (i >= 0) {
5748                         return (i);
5749                 }
5750         }
5751
5752         /* find an invalid one */
5753         i = iNumServices;
5754         if (num_invalid_services > 0) {
5755                 i = invalid_services[--num_invalid_services];
5756         }
5757
5758         /* if not, then create one */
5759         if (i == iNumServices) {
5760                 struct loadparm_service **tsp;
5761                 int *tinvalid;
5762
5763                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
5764                 if (tsp == NULL) {
5765                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5766                         return (-1);
5767                 }
5768                 ServicePtrs = tsp;
5769                 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
5770                 if (!ServicePtrs[iNumServices]) {
5771                         DEBUG(0,("add_a_service: out of memory!\n"));
5772                         return (-1);
5773                 }
5774                 iNumServices++;
5775
5776                 /* enlarge invalid_services here for now... */
5777                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5778                                              num_to_alloc);
5779                 if (tinvalid == NULL) {
5780                         DEBUG(0,("add_a_service: failed to enlarge "
5781                                  "invalid_services!\n"));
5782                         return (-1);
5783                 }
5784                 invalid_services = tinvalid;
5785         } else {
5786                 free_service_byindex(i);
5787         }
5788
5789         ServicePtrs[i]->valid = true;
5790
5791         init_service(ServicePtrs[i]);
5792         copy_service(ServicePtrs[i], &tservice, NULL);
5793         if (name)
5794                 string_set(&ServicePtrs[i]->szService, name);
5795
5796         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
5797                 i, ServicePtrs[i]->szService));
5798
5799         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5800                 return (-1);
5801         }
5802
5803         return (i);
5804 }
5805
5806 /***************************************************************************
5807   Convert a string to uppercase and remove whitespaces.
5808 ***************************************************************************/
5809
5810 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
5811 {
5812         char *result;
5813
5814         if ( !src ) {
5815                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5816                 return NULL;
5817         }
5818
5819         result = talloc_strdup(ctx, src);
5820         SMB_ASSERT(result != NULL);
5821
5822         strlower_m(result);
5823         return result;
5824 }
5825
5826 /***************************************************************************
5827   Add a name/index pair for the services array to the hash table.
5828 ***************************************************************************/
5829
5830 static bool hash_a_service(const char *name, int idx)
5831 {
5832         char *canon_name;
5833
5834         if ( !ServiceHash ) {
5835                 DEBUG(10,("hash_a_service: creating servicehash\n"));
5836                 ServiceHash = db_open_rbt(NULL);
5837                 if ( !ServiceHash ) {
5838                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5839                         return false;
5840                 }
5841         }
5842
5843         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5844                 idx, name));
5845
5846         canon_name = canonicalize_servicename(talloc_tos(), name );
5847
5848         dbwrap_store_bystring(ServiceHash, canon_name,
5849                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
5850                               TDB_REPLACE);
5851
5852         TALLOC_FREE(canon_name);
5853
5854         return true;
5855 }
5856
5857 /***************************************************************************
5858  Add a new home service, with the specified home directory, defaults coming
5859  from service ifrom.
5860 ***************************************************************************/
5861
5862 bool lp_add_home(const char *pszHomename, int iDefaultService,
5863                  const char *user, const char *pszHomedir)
5864 {
5865         int i;
5866
5867         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
5868                         pszHomedir[0] == '\0') {
5869                 return false;
5870         }
5871
5872         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5873
5874         if (i < 0)
5875                 return false;
5876
5877         if (!(*(ServicePtrs[iDefaultService]->szPath))
5878             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
5879                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5880         }
5881
5882         if (!(*(ServicePtrs[i]->comment))) {
5883                 char *comment = NULL;
5884                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5885                         return false;
5886                 }
5887                 string_set(&ServicePtrs[i]->comment, comment);
5888                 SAFE_FREE(comment);
5889         }
5890
5891         /* set the browseable flag from the global default */
5892
5893         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5894         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
5895
5896         ServicePtrs[i]->autoloaded = true;
5897
5898         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
5899                user, ServicePtrs[i]->szPath ));
5900
5901         return true;
5902 }
5903
5904 /***************************************************************************
5905  Add a new service, based on an old one.
5906 ***************************************************************************/
5907
5908 int lp_add_service(const char *pszService, int iDefaultService)
5909 {
5910         if (iDefaultService < 0) {
5911                 return add_a_service(&sDefault, pszService);
5912         }
5913
5914         return (add_a_service(ServicePtrs[iDefaultService], pszService));
5915 }
5916
5917 /***************************************************************************
5918  Add the IPC service.
5919 ***************************************************************************/
5920
5921 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5922 {
5923         char *comment = NULL;
5924         int i = add_a_service(&sDefault, ipc_name);
5925
5926         if (i < 0)
5927                 return false;
5928
5929         if (asprintf(&comment, "IPC Service (%s)",
5930                                 Globals.szServerString) < 0) {
5931                 return false;
5932         }
5933
5934         string_set(&ServicePtrs[i]->szPath, tmpdir());
5935         string_set(&ServicePtrs[i]->szUsername, "");
5936         string_set(&ServicePtrs[i]->comment, comment);
5937         string_set(&ServicePtrs[i]->fstype, "IPC");
5938         ServicePtrs[i]->iMaxConnections = 0;
5939         ServicePtrs[i]->bAvailable = true;
5940         ServicePtrs[i]->bRead_only = true;
5941         ServicePtrs[i]->bGuest_only = false;
5942         ServicePtrs[i]->bAdministrative_share = true;
5943         ServicePtrs[i]->bGuest_ok = guest_ok;
5944         ServicePtrs[i]->bPrint_ok = false;
5945         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5946
5947         DEBUG(3, ("adding IPC service\n"));
5948
5949         SAFE_FREE(comment);
5950         return true;
5951 }
5952
5953 /***************************************************************************
5954  Add a new printer service, with defaults coming from service iFrom.
5955 ***************************************************************************/
5956
5957 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
5958 {
5959         const char *comment = "From Printcap";
5960         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
5961
5962         if (i < 0)
5963                 return false;
5964
5965         /* note that we do NOT default the availability flag to true - */
5966         /* we take it from the default service passed. This allows all */
5967         /* dynamic printers to be disabled by disabling the [printers] */
5968         /* entry (if/when the 'available' keyword is implemented!).    */
5969
5970         /* the printer name is set to the service name. */
5971         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
5972         string_set(&ServicePtrs[i]->comment, comment);
5973
5974         /* set the browseable flag from the gloabl default */
5975         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5976
5977         /* Printers cannot be read_only. */
5978         ServicePtrs[i]->bRead_only = false;
5979         /* No share modes on printer services. */
5980         ServicePtrs[i]->bShareModes = false;
5981         /* No oplocks on printer services. */
5982         ServicePtrs[i]->bOpLocks = false;
5983         /* Printer services must be printable. */
5984         ServicePtrs[i]->bPrint_ok = true;
5985
5986         DEBUG(3, ("adding printer service %s\n", pszPrintername));
5987
5988         return true;
5989 }
5990
5991
5992 /***************************************************************************
5993  Check whether the given parameter name is valid.
5994  Parametric options (names containing a colon) are considered valid.
5995 ***************************************************************************/
5996
5997 bool lp_parameter_is_valid(const char *pszParmName)
5998 {
5999         return ((map_parameter(pszParmName) != -1) ||
6000                 (strchr(pszParmName, ':') != NULL));
6001 }
6002
6003 /***************************************************************************
6004  Check whether the given name is the name of a global parameter.
6005  Returns true for strings belonging to parameters of class
6006  P_GLOBAL, false for all other strings, also for parametric options
6007  and strings not belonging to any option.
6008 ***************************************************************************/
6009
6010 bool lp_parameter_is_global(const char *pszParmName)
6011 {
6012         int num = map_parameter(pszParmName);
6013
6014         if (num >= 0) {
6015                 return (parm_table[num].p_class == P_GLOBAL);
6016         }
6017
6018         return false;
6019 }
6020
6021 /**************************************************************************
6022  Check whether the given name is the canonical name of a parameter.
6023  Returns false if it is not a valid parameter Name.
6024  For parametric options, true is returned.
6025 **************************************************************************/
6026
6027 bool lp_parameter_is_canonical(const char *parm_name)
6028 {
6029         if (!lp_parameter_is_valid(parm_name)) {
6030                 return false;
6031         }
6032
6033         return (map_parameter(parm_name) ==
6034                 map_parameter_canonical(parm_name, NULL));
6035 }
6036
6037 /**************************************************************************
6038  Determine the canonical name for a parameter.
6039  Indicate when it is an inverse (boolean) synonym instead of a
6040  "usual" synonym.
6041 **************************************************************************/
6042
6043 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
6044                                bool *inverse)
6045 {
6046         int num;
6047
6048         if (!lp_parameter_is_valid(parm_name)) {
6049                 *canon_parm = NULL;
6050                 return false;
6051         }
6052
6053         num = map_parameter_canonical(parm_name, inverse);
6054         if (num < 0) {
6055                 /* parametric option */
6056                 *canon_parm = parm_name;
6057         } else {
6058                 *canon_parm = parm_table[num].label;
6059         }
6060
6061         return true;
6062
6063 }
6064
6065 /**************************************************************************
6066  Determine the canonical name for a parameter.
6067  Turn the value given into the inverse boolean expression when
6068  the synonym is an invers boolean synonym.
6069
6070  Return true if parm_name is a valid parameter name and
6071  in case it is an invers boolean synonym, if the val string could
6072  successfully be converted to the reverse bool.
6073  Return false in all other cases.
6074 **************************************************************************/
6075
6076 bool lp_canonicalize_parameter_with_value(const char *parm_name,
6077                                           const char *val,
6078                                           const char **canon_parm,
6079                                           const char **canon_val)
6080 {
6081         int num;
6082         bool inverse;
6083
6084         if (!lp_parameter_is_valid(parm_name)) {
6085                 *canon_parm = NULL;
6086                 *canon_val = NULL;
6087                 return false;
6088         }
6089
6090         num = map_parameter_canonical(parm_name, &inverse);
6091         if (num < 0) {
6092                 /* parametric option */
6093                 *canon_parm = parm_name;
6094                 *canon_val = val;
6095         } else {
6096                 *canon_parm = parm_table[num].label;
6097                 if (inverse) {
6098                         if (!lp_invert_boolean(val, canon_val)) {
6099                                 *canon_val = NULL;
6100                                 return false;
6101                         }
6102                 } else {
6103                         *canon_val = val;
6104                 }
6105         }
6106
6107         return true;
6108 }
6109
6110 /***************************************************************************
6111  Map a parameter's string representation to something we can use. 
6112  Returns false if the parameter string is not recognised, else TRUE.
6113 ***************************************************************************/
6114
6115 static int map_parameter(const char *pszParmName)
6116 {
6117         int iIndex;
6118
6119         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
6120                 return (-1);
6121
6122         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
6123                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
6124                         return (iIndex);
6125
6126         /* Warn only if it isn't parametric option */
6127         if (strchr(pszParmName, ':') == NULL)
6128                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
6129         /* We do return 'fail' for parametric options as well because they are
6130            stored in different storage
6131          */
6132         return (-1);
6133 }
6134
6135 /***************************************************************************
6136  Map a parameter's string representation to the index of the canonical
6137  form of the parameter (it might be a synonym).
6138  Returns -1 if the parameter string is not recognised.
6139 ***************************************************************************/
6140
6141 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
6142 {
6143         int parm_num, canon_num;
6144         bool loc_inverse = false;
6145
6146         parm_num = map_parameter(pszParmName);
6147         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
6148                 /* invalid, parametric or no canidate for synonyms ... */
6149                 goto done;
6150         }
6151
6152         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
6153                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
6154                         parm_num = canon_num;
6155                         goto done;
6156                 }
6157         }
6158
6159 done:
6160         if (inverse != NULL) {
6161                 *inverse = loc_inverse;
6162         }
6163         return parm_num;
6164 }
6165
6166 /***************************************************************************
6167  return true if parameter number parm1 is a synonym of parameter
6168  number parm2 (parm2 being the principal name).
6169  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
6170  false otherwise.
6171 ***************************************************************************/
6172
6173 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
6174 {
6175         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
6176             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
6177             (parm_table[parm1].flags & FLAG_HIDE) &&
6178             !(parm_table[parm2].flags & FLAG_HIDE))
6179         {
6180                 if (inverse != NULL) {
6181                         if ((parm_table[parm1].type == P_BOOLREV) &&
6182                             (parm_table[parm2].type == P_BOOL))
6183                         {
6184                                 *inverse = true;
6185                         } else {
6186                                 *inverse = false;
6187                         }
6188                 }
6189                 return true;
6190         }
6191         return false;
6192 }
6193
6194 /***************************************************************************
6195  Show one parameter's name, type, [values,] and flags.
6196  (helper functions for show_parameter_list)
6197 ***************************************************************************/
6198
6199 static void show_parameter(int parmIndex)
6200 {
6201         int enumIndex, flagIndex;
6202         int parmIndex2;
6203         bool hadFlag;
6204         bool hadSyn;
6205         bool inverse;
6206         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
6207                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
6208                 "P_ENUM", "P_SEP"};
6209         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
6210                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
6211                 FLAG_HIDE};
6212         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
6213                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
6214                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
6215
6216         printf("%s=%s", parm_table[parmIndex].label,
6217                type[parm_table[parmIndex].type]);
6218         if (parm_table[parmIndex].type == P_ENUM) {
6219                 printf(",");
6220                 for (enumIndex=0;
6221                      parm_table[parmIndex].enum_list[enumIndex].name;
6222                      enumIndex++)
6223                 {
6224                         printf("%s%s",
6225                                enumIndex ? "|" : "",
6226                                parm_table[parmIndex].enum_list[enumIndex].name);
6227                 }
6228         }
6229         printf(",");
6230         hadFlag = false;
6231         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
6232                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
6233                         printf("%s%s",
6234                                 hadFlag ? "|" : "",
6235                                 flag_names[flagIndex]);
6236                         hadFlag = true;
6237                 }
6238         }
6239
6240         /* output synonyms */
6241         hadSyn = false;
6242         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6243                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6244                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6245                                parm_table[parmIndex2].label);
6246                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6247                         if (!hadSyn) {
6248                                 printf(" (synonyms: ");
6249                                 hadSyn = true;
6250                         } else {
6251                                 printf(", ");
6252                         }
6253                         printf("%s%s", parm_table[parmIndex2].label,
6254                                inverse ? "[i]" : "");
6255                 }
6256         }
6257         if (hadSyn) {
6258                 printf(")");
6259         }
6260
6261         printf("\n");
6262 }
6263
6264 /***************************************************************************
6265  Show all parameter's name, type, [values,] and flags.
6266 ***************************************************************************/
6267
6268 void show_parameter_list(void)
6269 {
6270         int classIndex, parmIndex;
6271         const char *section_names[] = { "local", "global", NULL};
6272
6273         for (classIndex=0; section_names[classIndex]; classIndex++) {
6274                 printf("[%s]\n", section_names[classIndex]);
6275                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6276                         if (parm_table[parmIndex].p_class == classIndex) {
6277                                 show_parameter(parmIndex);
6278                         }
6279                 }
6280         }
6281 }
6282
6283 /***************************************************************************
6284  Check if a given string correctly represents a boolean value.
6285 ***************************************************************************/
6286
6287 bool lp_string_is_valid_boolean(const char *parm_value)
6288 {
6289         return set_boolean(parm_value, NULL);
6290 }
6291
6292 /***************************************************************************
6293  Get the standard string representation of a boolean value ("yes" or "no")
6294 ***************************************************************************/
6295
6296 static const char *get_boolean(bool bool_value)
6297 {
6298         static const char *yes_str = "yes";
6299         static const char *no_str = "no";
6300
6301         return (bool_value ? yes_str : no_str);
6302 }
6303
6304 /***************************************************************************
6305  Provide the string of the negated boolean value associated to the boolean
6306  given as a string. Returns false if the passed string does not correctly
6307  represent a boolean.
6308 ***************************************************************************/
6309
6310 bool lp_invert_boolean(const char *str, const char **inverse_str)
6311 {
6312         bool val;
6313
6314         if (!set_boolean(str, &val)) {
6315                 return false;
6316         }
6317
6318         *inverse_str = get_boolean(!val);
6319         return true;
6320 }
6321
6322 /***************************************************************************
6323  Provide the canonical string representation of a boolean value given
6324  as a string. Return true on success, false if the string given does
6325  not correctly represent a boolean.
6326 ***************************************************************************/
6327
6328 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6329 {
6330         bool val;
6331
6332         if (!set_boolean(str, &val)) {
6333                 return false;
6334         }
6335
6336         *canon_str = get_boolean(val);
6337         return true;
6338 }
6339
6340 /***************************************************************************
6341 Find a service by name. Otherwise works like get_service.
6342 ***************************************************************************/
6343
6344 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
6345 {
6346         int iService = -1;
6347         char *canon_name;
6348         TDB_DATA data;
6349         NTSTATUS status;
6350
6351         if (ServiceHash == NULL) {
6352                 return -1;
6353         }
6354
6355         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
6356
6357         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
6358                                        &data);
6359
6360         if (NT_STATUS_IS_OK(status) &&
6361             (data.dptr != NULL) &&
6362             (data.dsize == sizeof(iService)))
6363         {
6364                 iService = *(int *)data.dptr;
6365         }
6366
6367         TALLOC_FREE(canon_name);
6368
6369         if ((iService != -1) && (LP_SNUM_OK(iService))
6370             && (pserviceDest != NULL)) {
6371                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6372         }
6373
6374         return (iService);
6375 }
6376
6377 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
6378 struct loadparm_service *lp_service(const char *pszServiceName)
6379 {
6380         int iService = getservicebyname(pszServiceName, NULL);
6381         if (iService == -1 || !LP_SNUM_OK(iService)) {
6382                 return NULL;
6383         }
6384         return ServicePtrs[iService];
6385 }
6386
6387 struct loadparm_service *lp_servicebynum(int snum)
6388 {
6389         if ((snum == -1) || !LP_SNUM_OK(snum)) {
6390                 return NULL;
6391         }
6392         return ServicePtrs[snum];
6393 }
6394
6395 struct loadparm_service *lp_default_loadparm_service()
6396 {
6397         return &sDefault;
6398 }
6399
6400
6401 /***************************************************************************
6402  Copy a service structure to another.
6403  If pcopymapDest is NULL then copy all fields
6404 ***************************************************************************/
6405
6406 /**
6407  * Add a parametric option to a parmlist_entry,
6408  * replacing old value, if already present.
6409  */
6410 static void set_param_opt(struct parmlist_entry **opt_list,
6411                           const char *opt_name,
6412                           const char *opt_value,
6413                           unsigned priority)
6414 {
6415         struct parmlist_entry *new_opt, *opt;
6416         bool not_added;
6417
6418         if (opt_list == NULL) {
6419                 return;
6420         }
6421
6422         opt = *opt_list;
6423         not_added = true;
6424
6425         /* Traverse destination */
6426         while (opt) {
6427                 /* If we already have same option, override it */
6428                 if (strwicmp(opt->key, opt_name) == 0) {
6429                         if ((opt->priority & FLAG_CMDLINE) &&
6430                             !(priority & FLAG_CMDLINE)) {
6431                                 /* it's been marked as not to be
6432                                    overridden */
6433                                 return;
6434                         }
6435                         string_free(&opt->value);
6436                         TALLOC_FREE(opt->list);
6437                         opt->value = SMB_STRDUP(opt_value);
6438                         opt->priority = priority;
6439                         not_added = false;
6440                         break;
6441                 }
6442                 opt = opt->next;
6443         }
6444         if (not_added) {
6445             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
6446             new_opt->key = SMB_STRDUP(opt_name);
6447             new_opt->value = SMB_STRDUP(opt_value);
6448             new_opt->list = NULL;
6449             new_opt->priority = priority;
6450             DLIST_ADD(*opt_list, new_opt);
6451         }
6452 }
6453
6454 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
6455                          struct bitmap *pcopymapDest)
6456 {
6457         int i;
6458         bool bcopyall = (pcopymapDest == NULL);
6459         struct parmlist_entry *data;
6460
6461         for (i = 0; parm_table[i].label; i++)
6462                 if (parm_table[i].p_class == P_LOCAL &&
6463                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6464                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
6465                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
6466
6467                         switch (parm_table[i].type) {
6468                                 case P_BOOL:
6469                                 case P_BOOLREV:
6470                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6471                                         break;
6472
6473                                 case P_INTEGER:
6474                                 case P_ENUM:
6475                                 case P_OCTAL:
6476                                 case P_BYTES:
6477                                         *(int *)dest_ptr = *(int *)src_ptr;
6478                                         break;
6479
6480                                 case P_CHAR:
6481                                         *(char *)dest_ptr = *(char *)src_ptr;
6482                                         break;
6483
6484                                 case P_STRING:
6485                                         string_set((char **)dest_ptr,
6486                                                    *(char **)src_ptr);
6487                                         break;
6488
6489                                 case P_USTRING:
6490                                 {
6491                                         char *upper_string = strupper_talloc(talloc_tos(), 
6492                                                                              *(char **)src_ptr);
6493                                         string_set((char **)dest_ptr,
6494                                                    upper_string);
6495                                         TALLOC_FREE(upper_string);
6496                                         break;
6497                                 }
6498                                 case P_LIST:
6499                                         TALLOC_FREE(*((char ***)dest_ptr));
6500                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6501                                                       *(const char ***)src_ptr);
6502                                         break;
6503                                 default:
6504                                         break;
6505                         }
6506                 }
6507
6508         if (bcopyall) {
6509                 init_copymap(pserviceDest);
6510                 if (pserviceSource->copymap)
6511                         bitmap_copy(pserviceDest->copymap,
6512                                     pserviceSource->copymap);
6513         }
6514
6515         data = pserviceSource->param_opt;
6516         while (data) {
6517                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
6518                 data = data->next;
6519         }
6520 }
6521
6522 /***************************************************************************
6523 Check a service for consistency. Return false if the service is in any way
6524 incomplete or faulty, else true.
6525 ***************************************************************************/
6526
6527 bool service_ok(int iService)
6528 {
6529         bool bRetval;
6530
6531         bRetval = true;
6532         if (ServicePtrs[iService]->szService[0] == '\0') {
6533                 DEBUG(0, ("The following message indicates an internal error:\n"));
6534                 DEBUG(0, ("No service name in service entry.\n"));
6535                 bRetval = false;
6536         }
6537
6538         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6539         /* I can't see why you'd want a non-printable printer service...        */
6540         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6541                 if (!ServicePtrs[iService]->bPrint_ok) {
6542                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6543                                ServicePtrs[iService]->szService));
6544                         ServicePtrs[iService]->bPrint_ok = true;
6545                 }
6546                 /* [printers] service must also be non-browsable. */
6547                 if (ServicePtrs[iService]->bBrowseable)
6548                         ServicePtrs[iService]->bBrowseable = false;
6549         }
6550
6551         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6552             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6553             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6554             ) {
6555                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6556                         ServicePtrs[iService]->szService));
6557                 ServicePtrs[iService]->bAvailable = false;
6558         }
6559
6560         /* If a service is flagged unavailable, log the fact at level 1. */
6561         if (!ServicePtrs[iService]->bAvailable)
6562                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6563                           ServicePtrs[iService]->szService));
6564
6565         return (bRetval);
6566 }
6567
6568 static struct smbconf_ctx *lp_smbconf_ctx(void)
6569 {
6570         sbcErr err;
6571         static struct smbconf_ctx *conf_ctx = NULL;
6572
6573         if (conf_ctx == NULL) {
6574                 err = smbconf_init(NULL, &conf_ctx, "registry:");
6575                 if (!SBC_ERROR_IS_OK(err)) {
6576                         DEBUG(1, ("error initializing registry configuration: "
6577                                   "%s\n", sbcErrorString(err)));
6578                         conf_ctx = NULL;
6579                 }
6580         }
6581
6582         return conf_ctx;
6583 }
6584
6585 static bool process_smbconf_service(struct smbconf_service *service)
6586 {
6587         uint32_t count;
6588         bool ret;
6589
6590         if (service == NULL) {
6591                 return false;
6592         }
6593
6594         ret = do_section(service->name, NULL);
6595         if (ret != true) {
6596                 return false;
6597         }
6598         for (count = 0; count < service->num_params; count++) {
6599                 ret = do_parameter(service->param_names[count],
6600                                    service->param_values[count],
6601                                    NULL);
6602                 if (ret != true) {
6603                         return false;
6604                 }
6605         }
6606         if (iServiceIndex >= 0) {
6607                 return service_ok(iServiceIndex);
6608         }
6609         return true;
6610 }
6611
6612 /**
6613  * load a service from registry and activate it
6614  */
6615 bool process_registry_service(const char *service_name)
6616 {
6617         sbcErr err;
6618         struct smbconf_service *service = NULL;
6619         TALLOC_CTX *mem_ctx = talloc_stackframe();
6620         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6621         bool ret = false;
6622
6623         if (conf_ctx == NULL) {
6624                 goto done;
6625         }
6626
6627         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
6628
6629         if (!smbconf_share_exists(conf_ctx, service_name)) {
6630                 /*
6631                  * Registry does not contain data for this service (yet),
6632                  * but make sure lp_load doesn't return false.
6633                  */
6634                 ret = true;
6635                 goto done;
6636         }
6637
6638         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
6639         if (!SBC_ERROR_IS_OK(err)) {
6640                 goto done;
6641         }
6642
6643         ret = process_smbconf_service(service);
6644         if (!ret) {
6645                 goto done;
6646         }
6647
6648         /* store the csn */
6649         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6650
6651 done:
6652         TALLOC_FREE(mem_ctx);
6653         return ret;
6654 }
6655
6656 /*
6657  * process_registry_globals
6658  */
6659 static bool process_registry_globals(void)
6660 {
6661         bool ret;
6662
6663         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
6664
6665         ret = do_parameter("registry shares", "yes", NULL);
6666         if (!ret) {
6667                 return ret;
6668         }
6669
6670         return process_registry_service(GLOBAL_NAME);
6671 }
6672
6673 bool process_registry_shares(void)
6674 {
6675         sbcErr err;
6676         uint32_t count;
6677         struct smbconf_service **service = NULL;
6678         uint32_t num_shares = 0;
6679         TALLOC_CTX *mem_ctx = talloc_stackframe();
6680         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6681         bool ret = false;
6682
6683         if (conf_ctx == NULL) {
6684                 goto done;
6685         }
6686
6687         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6688         if (!SBC_ERROR_IS_OK(err)) {
6689                 goto done;
6690         }
6691
6692         ret = true;
6693
6694         for (count = 0; count < num_shares; count++) {
6695                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6696                         continue;
6697                 }
6698                 ret = process_smbconf_service(service[count]);
6699                 if (!ret) {
6700                         goto done;
6701                 }
6702         }
6703
6704         /* store the csn */
6705         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6706
6707 done:
6708         TALLOC_FREE(mem_ctx);
6709         return ret;
6710 }
6711
6712 /**
6713  * reload those shares from registry that are already
6714  * activated in the services array.
6715  */
6716 static bool reload_registry_shares(void)
6717 {
6718         int i;
6719         bool ret = true;
6720
6721         for (i = 0; i < iNumServices; i++) {
6722                 if (!VALID(i)) {
6723                         continue;
6724                 }
6725
6726                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
6727                         continue;
6728                 }
6729
6730                 ret = process_registry_service(ServicePtrs[i]->szService);
6731                 if (!ret) {
6732                         goto done;
6733                 }
6734         }
6735
6736 done:
6737         return ret;
6738 }
6739
6740
6741 #define MAX_INCLUDE_DEPTH 100
6742
6743 static uint8_t include_depth;
6744
6745 static struct file_lists {
6746         struct file_lists *next;
6747         char *name;
6748         char *subfname;
6749         time_t modtime;
6750 } *file_lists = NULL;
6751
6752 /*******************************************************************
6753  Keep a linked list of all config files so we know when one has changed 
6754  it's date and needs to be reloaded.
6755 ********************************************************************/
6756
6757 static void add_to_file_list(const char *fname, const char *subfname)
6758 {
6759         struct file_lists *f = file_lists;
6760
6761         while (f) {
6762                 if (f->name && !strcmp(f->name, fname))
6763                         break;
6764                 f = f->next;
6765         }
6766
6767         if (!f) {
6768                 f = SMB_MALLOC_P(struct file_lists);
6769                 if (!f)
6770                         return;
6771                 f->next = file_lists;
6772                 f->name = SMB_STRDUP(fname);
6773                 if (!f->name) {
6774                         SAFE_FREE(f);
6775                         return;
6776                 }
6777                 f->subfname = SMB_STRDUP(subfname);
6778                 if (!f->subfname) {
6779                         SAFE_FREE(f->name);
6780                         SAFE_FREE(f);
6781                         return;
6782                 }
6783                 file_lists = f;
6784                 f->modtime = file_modtime(subfname);
6785         } else {
6786                 time_t t = file_modtime(subfname);
6787                 if (t)
6788                         f->modtime = t;
6789         }
6790         return;
6791 }
6792
6793 /**
6794  * Free the file lists
6795  */
6796 static void free_file_list(void)
6797 {
6798         struct file_lists *f;
6799         struct file_lists *next;
6800
6801         f = file_lists;
6802         while( f ) {
6803                 next = f->next;
6804                 SAFE_FREE( f->name );
6805                 SAFE_FREE( f->subfname );
6806                 SAFE_FREE( f );
6807                 f = next;
6808         }
6809         file_lists = NULL;
6810 }
6811
6812
6813 /**
6814  * Utility function for outsiders to check if we're running on registry.
6815  */
6816 bool lp_config_backend_is_registry(void)
6817 {
6818         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6819 }
6820
6821 /**
6822  * Utility function to check if the config backend is FILE.
6823  */
6824 bool lp_config_backend_is_file(void)
6825 {
6826         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6827 }
6828
6829 /*******************************************************************
6830  Check if a config file has changed date.
6831 ********************************************************************/
6832
6833 bool lp_file_list_changed(void)
6834 {
6835         struct file_lists *f = file_lists;
6836
6837         DEBUG(6, ("lp_file_list_changed()\n"));
6838
6839         while (f) {
6840                 time_t mod_time;
6841
6842                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
6843                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6844
6845                         if (conf_ctx == NULL) {
6846                                 return false;
6847                         }
6848                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
6849                                             NULL))
6850                         {
6851                                 DEBUGADD(6, ("registry config changed\n"));
6852                                 return true;
6853                         }
6854                 } else {
6855                         char *n2 = NULL;
6856                         n2 = talloc_sub_basic(talloc_tos(),
6857                                               get_current_username(),
6858                                               current_user_info.domain,
6859                                               f->name);
6860                         if (!n2) {
6861                                 return false;
6862                         }
6863                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
6864                                      f->name, n2, ctime(&f->modtime)));
6865
6866                         mod_time = file_modtime(n2);
6867
6868                         if (mod_time &&
6869                             ((f->modtime != mod_time) ||
6870                              (f->subfname == NULL) ||
6871                              (strcmp(n2, f->subfname) != 0)))
6872                         {
6873                                 DEBUGADD(6,
6874                                          ("file %s modified: %s\n", n2,
6875                                           ctime(&mod_time)));
6876                                 f->modtime = mod_time;
6877                                 SAFE_FREE(f->subfname);
6878                                 f->subfname = SMB_STRDUP(n2);
6879                                 TALLOC_FREE(n2);
6880                                 return true;
6881                         }
6882                         TALLOC_FREE(n2);
6883                 }
6884                 f = f->next;
6885         }
6886         return false;
6887 }
6888
6889
6890 /**
6891  * Initialize iconv conversion descriptors.
6892  *
6893  * This is called the first time it is needed, and also called again
6894  * every time the configuration is reloaded, because the charset or
6895  * codepage might have changed.
6896  **/
6897 static void init_iconv(void)
6898 {
6899         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
6900                                                       lp_unix_charset(),
6901                                                       true, global_iconv_handle);
6902 }
6903
6904 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6905 {
6906         if (strcmp(*ptr, pszParmValue) != 0) {
6907                 string_set(ptr, pszParmValue);
6908                 init_iconv();
6909         }
6910         return true;
6911 }
6912
6913 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6914 {
6915         bool is_utf8 = false;
6916         size_t len = strlen(pszParmValue);
6917
6918         if (len == 4 || len == 5) {
6919                 /* Don't use StrCaseCmp here as we don't want to
6920                    initialize iconv. */
6921                 if ((toupper_m(pszParmValue[0]) == 'U') &&
6922                     (toupper_m(pszParmValue[1]) == 'T') &&
6923                     (toupper_m(pszParmValue[2]) == 'F')) {
6924                         if (len == 4) {
6925                                 if (pszParmValue[3] == '8') {
6926                                         is_utf8 = true;
6927                                 }
6928                         } else {
6929                                 if (pszParmValue[3] == '-' &&
6930                                     pszParmValue[4] == '8') {
6931                                         is_utf8 = true;
6932                                 }
6933                         }
6934                 }
6935         }
6936
6937         if (strcmp(*ptr, pszParmValue) != 0) {
6938                 if (is_utf8) {
6939                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
6940                                 "be UTF8, using (default value) %s instead.\n",
6941                                 DEFAULT_DOS_CHARSET));
6942                         pszParmValue = DEFAULT_DOS_CHARSET;
6943                 }
6944                 string_set(ptr, pszParmValue);
6945                 init_iconv();
6946         }
6947         return true;
6948 }
6949
6950 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6951 {
6952         bool ret = true;
6953         char *realm = strupper_talloc(talloc_tos(), pszParmValue);
6954         char *dnsdomain = strlower_talloc(talloc_tos(), pszParmValue);
6955
6956         ret &= string_set(&Globals.szRealm, pszParmValue);
6957         ret &= string_set(&Globals.szRealmUpper, realm);
6958         ret &= string_set(&Globals.szDnsDomain, dnsdomain);
6959         TALLOC_FREE(realm);
6960         TALLOC_FREE(dnsdomain);
6961
6962         return ret;
6963 }
6964
6965 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6966 {
6967         TALLOC_FREE(Globals.szNetbiosAliases);
6968         Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
6969         return set_netbios_aliases(Globals.szNetbiosAliases);
6970 }
6971
6972 /***************************************************************************
6973  Handle the include operation.
6974 ***************************************************************************/
6975 static bool bAllowIncludeRegistry = true;
6976
6977 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6978 {
6979         char *fname;
6980
6981         if (include_depth >= MAX_INCLUDE_DEPTH) {
6982                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
6983                           include_depth));
6984                 return false;
6985         }
6986
6987         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6988                 if (!bAllowIncludeRegistry) {
6989                         return true;
6990                 }
6991                 if (bInGlobalSection) {
6992                         bool ret;
6993                         include_depth++;
6994                         ret = process_registry_globals();
6995                         include_depth--;
6996                         return ret;
6997                 } else {
6998                         DEBUG(1, ("\"include = registry\" only effective "
6999                                   "in %s section\n", GLOBAL_NAME));
7000                         return false;
7001                 }
7002         }
7003
7004         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
7005                                  current_user_info.domain,
7006                                  pszParmValue);
7007
7008         add_to_file_list(pszParmValue, fname);
7009
7010         string_set(ptr, fname);
7011
7012         if (file_exist(fname)) {
7013                 bool ret;
7014                 include_depth++;
7015                 ret = pm_process(fname, do_section, do_parameter, NULL);
7016                 include_depth--;
7017                 TALLOC_FREE(fname);
7018                 return ret;
7019         }
7020
7021         DEBUG(2, ("Can't find include file %s\n", fname));
7022         TALLOC_FREE(fname);
7023         return true;
7024 }
7025
7026 /***************************************************************************
7027  Handle the interpretation of the copy parameter.
7028 ***************************************************************************/
7029
7030 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7031 {
7032         bool bRetval;
7033         int iTemp;
7034         struct loadparm_service serviceTemp;
7035
7036         string_set(ptr, pszParmValue);
7037
7038         init_service(&serviceTemp);
7039
7040         bRetval = false;
7041
7042         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
7043
7044         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
7045                 if (iTemp == iServiceIndex) {
7046                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
7047                 } else {
7048                         copy_service(ServicePtrs[iServiceIndex],
7049                                      &serviceTemp,
7050                                      ServicePtrs[iServiceIndex]->copymap);
7051                         bRetval = true;
7052                 }
7053         } else {
7054                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
7055                 bRetval = false;
7056         }
7057
7058         free_service(&serviceTemp);
7059         return (bRetval);
7060 }
7061
7062 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7063 {
7064         Globals.ldap_debug_level = lp_int(pszParmValue);
7065         init_ldap_debugging();
7066         return true;
7067 }
7068
7069 /***************************************************************************
7070  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
7071  parameters is:
7072
7073  [global]
7074
7075         idmap uid = 1000-1999
7076         idmap gid = 700-899
7077
7078  We only do simple parsing checks here.  The strings are parsed into useful
7079  structures in the idmap daemon code.
7080
7081 ***************************************************************************/
7082
7083 /* Some lp_ routines to return idmap [ug]id information */
7084
7085 static uid_t idmap_uid_low, idmap_uid_high;
7086 static gid_t idmap_gid_low, idmap_gid_high;
7087
7088 bool lp_idmap_uid(uid_t *low, uid_t *high)
7089 {
7090         if (idmap_uid_low == 0 || idmap_uid_high == 0)
7091                 return false;
7092
7093         if (low)
7094                 *low = idmap_uid_low;
7095
7096         if (high)
7097                 *high = idmap_uid_high;
7098
7099         return true;
7100 }
7101
7102 bool lp_idmap_gid(gid_t *low, gid_t *high)
7103 {
7104         if (idmap_gid_low == 0 || idmap_gid_high == 0)
7105                 return false;
7106
7107         if (low)
7108                 *low = idmap_gid_low;
7109
7110         if (high)
7111                 *high = idmap_gid_high;
7112
7113         return true;
7114 }
7115
7116 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7117 {
7118         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
7119
7120         return true;
7121 }
7122
7123 /* Do some simple checks on "idmap [ug]id" parameter values */
7124
7125 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7126 {
7127         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7128
7129         return true;
7130 }
7131
7132 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7133 {
7134         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7135
7136         return true;
7137 }
7138
7139 /***************************************************************************
7140  Handle the DEBUG level list.
7141 ***************************************************************************/
7142
7143 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
7144 {
7145         string_set(ptr, pszParmValueIn);
7146         return debug_parse_levels(pszParmValueIn);
7147 }
7148
7149 /***************************************************************************
7150  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
7151 ***************************************************************************/
7152
7153 static const char *append_ldap_suffix( const char *str )
7154 {
7155         const char *suffix_string;
7156
7157
7158         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
7159                                         Globals.szLdapSuffix );
7160         if ( !suffix_string ) {
7161                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
7162                 return "";
7163         }
7164
7165         return suffix_string;
7166 }
7167
7168 const char *lp_ldap_machine_suffix(void)
7169 {
7170         if (Globals.szLdapMachineSuffix[0])
7171                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
7172
7173         return lp_string(Globals.szLdapSuffix);
7174 }
7175
7176 const char *lp_ldap_user_suffix(void)
7177 {
7178         if (Globals.szLdapUserSuffix[0])
7179                 return append_ldap_suffix(Globals.szLdapUserSuffix);
7180
7181         return lp_string(Globals.szLdapSuffix);
7182 }
7183
7184 const char *lp_ldap_group_suffix(void)
7185 {
7186         if (Globals.szLdapGroupSuffix[0])
7187                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
7188
7189         return lp_string(Globals.szLdapSuffix);
7190 }
7191
7192 const char *lp_ldap_idmap_suffix(void)
7193 {
7194         if (Globals.szLdapIdmapSuffix[0])
7195                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
7196
7197         return lp_string(Globals.szLdapSuffix);
7198 }
7199
7200 /****************************************************************************
7201  set the value for a P_ENUM
7202  ***************************************************************************/
7203
7204 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
7205                               int *ptr )
7206 {
7207         int i;
7208
7209         for (i = 0; parm->enum_list[i].name; i++) {
7210                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
7211                         *ptr = parm->enum_list[i].value;
7212                         return;
7213                 }
7214         }
7215         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
7216                   pszParmValue, parm->label));
7217 }
7218
7219 /***************************************************************************
7220 ***************************************************************************/
7221
7222 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7223 {
7224         static int parm_num = -1;
7225         struct loadparm_service *s;
7226
7227         if ( parm_num == -1 )
7228                 parm_num = map_parameter( "printing" );
7229
7230         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
7231
7232         if ( snum < 0 )
7233                 s = &sDefault;
7234         else
7235                 s = ServicePtrs[snum];
7236
7237         init_printer_values( s );
7238
7239         return true;
7240 }
7241
7242
7243 /***************************************************************************
7244  Initialise a copymap.
7245 ***************************************************************************/
7246
7247 static void init_copymap(struct loadparm_service *pservice)
7248 {
7249         int i;
7250
7251         TALLOC_FREE(pservice->copymap);
7252
7253         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
7254         if (!pservice->copymap)
7255                 DEBUG(0,
7256                       ("Couldn't allocate copymap!! (size %d)\n",
7257                        (int)NUMPARAMETERS));
7258         else
7259                 for (i = 0; i < NUMPARAMETERS; i++)
7260                         bitmap_set(pservice->copymap, i);
7261 }
7262
7263 /**
7264   return the parameter pointer for a parameter
7265 */
7266 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
7267 {
7268         if (service == NULL) {
7269                 if (parm->p_class == P_LOCAL)
7270                         return (void *)(((char *)&sDefault)+parm->offset);
7271                 else if (parm->p_class == P_GLOBAL)
7272                         return (void *)(((char *)&Globals)+parm->offset);
7273                 else return NULL;
7274         } else {
7275                 return (void *)(((char *)service) + parm->offset);
7276         }
7277 }
7278
7279 /***************************************************************************
7280  Return the local pointer to a parameter given the service number and parameter
7281 ***************************************************************************/
7282
7283 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
7284 {
7285         return lp_parm_ptr(ServicePtrs[snum], parm);
7286 }
7287
7288 /***************************************************************************
7289  Process a parameter for a particular service number. If snum < 0
7290  then assume we are in the globals.
7291 ***************************************************************************/
7292
7293 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7294 {
7295         int parmnum, i;
7296         void *parm_ptr = NULL;  /* where we are going to store the result */
7297         struct parmlist_entry **opt_list;
7298
7299         parmnum = map_parameter(pszParmName);
7300
7301         if (parmnum < 0) {
7302                 if (strchr(pszParmName, ':') == NULL) {
7303                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7304                                   pszParmName));
7305                         return true;
7306                 }
7307
7308                 /*
7309                  * We've got a parametric option
7310                  */
7311
7312                 opt_list = (snum < 0)
7313                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7314                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
7315
7316                 return true;
7317         }
7318
7319         /* if it's already been set by the command line, then we don't
7320            override here */
7321         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
7322                 return true;
7323         }
7324
7325         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7326                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7327                           pszParmName));
7328         }
7329
7330         /* we might point at a service, the default service or a global */
7331         if (snum < 0) {
7332                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
7333         } else {
7334                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7335                         DEBUG(0,
7336                               ("Global parameter %s found in service section!\n",
7337                                pszParmName));
7338                         return true;
7339                 }
7340                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
7341         }
7342
7343         if (snum >= 0) {
7344                 if (!ServicePtrs[snum]->copymap)
7345                         init_copymap(ServicePtrs[snum]);
7346
7347                 /* this handles the aliases - set the copymap for other entries with
7348                    the same data pointer */
7349                 for (i = 0; parm_table[i].label; i++) {
7350                         if ((parm_table[i].offset == parm_table[parmnum].offset)
7351                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
7352                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7353                         }
7354                 }
7355         }
7356
7357         /* if it is a special case then go ahead */
7358         if (parm_table[parmnum].special) {
7359                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
7360                                                    (char **)parm_ptr);
7361         }
7362
7363         /* now switch on the type of variable it is */
7364         switch (parm_table[parmnum].type)
7365         {
7366                 case P_BOOL:
7367                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7368                         break;
7369
7370                 case P_BOOLREV:
7371                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7372                         break;
7373
7374                 case P_INTEGER:
7375                         *(int *)parm_ptr = lp_int(pszParmValue);
7376                         break;
7377
7378                 case P_CHAR:
7379                         *(char *)parm_ptr = *pszParmValue;
7380                         break;
7381
7382                 case P_OCTAL:
7383                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7384                         if ( i != 1 ) {
7385                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7386                         }
7387                         break;
7388
7389                 case P_BYTES:
7390                 {
7391                         uint64_t val;
7392                         if (conv_str_size_error(pszParmValue, &val)) {
7393                                 if (val <= INT_MAX) {
7394                                         *(int *)parm_ptr = (int)val;
7395                                         break;
7396                                 }
7397                         }
7398
7399                         DEBUG(0,("lp_do_parameter(%s): value is not "
7400                             "a valid size specifier!\n", pszParmValue));
7401                         return false;
7402                 }
7403
7404                 case P_LIST:
7405                 case P_CMDLIST:
7406                         TALLOC_FREE(*((char ***)parm_ptr));
7407                         *(char ***)parm_ptr = str_list_make_v3(
7408                                 NULL, pszParmValue, NULL);
7409                         break;
7410
7411                 case P_STRING:
7412                         string_set((char **)parm_ptr, pszParmValue);
7413                         break;
7414
7415                 case P_USTRING:
7416                 {
7417                         char *upper_string = strupper_talloc(talloc_tos(), 
7418                                                              pszParmValue);
7419                         string_set((char **)parm_ptr, upper_string);
7420                         TALLOC_FREE(upper_string);
7421                         break;
7422                 }
7423                 case P_ENUM:
7424                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7425                         break;
7426                 case P_SEP:
7427                         break;
7428         }
7429
7430         return true;
7431 }
7432
7433 /***************************************************************************
7434 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
7435 FLAG_CMDLINE won't be overridden by loads from smb.conf.
7436 ***************************************************************************/
7437
7438 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
7439 {
7440         int parmnum, i;
7441         parmnum = map_parameter(pszParmName);
7442         if (parmnum >= 0) {
7443                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
7444                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
7445                         return false;
7446                 }
7447                 parm_table[parmnum].flags |= FLAG_CMDLINE;
7448
7449                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
7450                  * be grouped in the table, so we don't have to search the
7451                  * whole table */
7452                 for (i=parmnum-1;
7453                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
7454                              && parm_table[i].p_class == parm_table[parmnum].p_class;
7455                      i--) {
7456                         parm_table[i].flags |= FLAG_CMDLINE;
7457                 }
7458                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
7459                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
7460                         parm_table[i].flags |= FLAG_CMDLINE;
7461                 }
7462
7463                 if (store_values) {
7464                         store_lp_set_cmdline(pszParmName, pszParmValue);
7465                 }
7466                 return true;
7467         }
7468
7469         /* it might be parametric */
7470         if (strchr(pszParmName, ':') != NULL) {
7471                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
7472                 if (store_values) {
7473                         store_lp_set_cmdline(pszParmName, pszParmValue);
7474                 }
7475                 return true;
7476         }
7477
7478         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
7479         return true;
7480 }
7481
7482 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
7483 {
7484         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
7485 }
7486
7487 /***************************************************************************
7488  Process a parameter.
7489 ***************************************************************************/
7490
7491 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7492                          void *userdata)
7493 {
7494         if (!bInGlobalSection && bGlobalOnly)
7495                 return true;
7496
7497         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7498
7499         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7500                                 pszParmName, pszParmValue));
7501 }
7502
7503 /*
7504   set a option from the commandline in 'a=b' format. Use to support --option
7505 */
7506 bool lp_set_option(const char *option)
7507 {
7508         char *p, *s;
7509         bool ret;
7510
7511         s = talloc_strdup(NULL, option);
7512         if (!s) {
7513                 return false;
7514         }
7515
7516         p = strchr(s, '=');
7517         if (!p) {
7518                 talloc_free(s);
7519                 return false;
7520         }
7521
7522         *p = 0;
7523
7524         /* skip white spaces after the = sign */
7525         do {
7526                 p++;
7527         } while (*p == ' ');
7528
7529         ret = lp_set_cmdline(s, p);
7530         talloc_free(s);
7531         return ret;
7532 }
7533
7534 /**************************************************************************
7535  Print a parameter of the specified type.
7536 ***************************************************************************/
7537
7538 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7539 {
7540         /* For the seperation of lists values that we print below */
7541         const char *list_sep = ", ";
7542         int i;
7543         switch (p->type)
7544         {
7545                 case P_ENUM:
7546                         for (i = 0; p->enum_list[i].name; i++) {
7547                                 if (*(int *)ptr == p->enum_list[i].value) {
7548                                         fprintf(f, "%s",
7549                                                 p->enum_list[i].name);
7550                                         break;
7551                                 }
7552                         }
7553                         break;
7554
7555                 case P_BOOL:
7556                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7557                         break;
7558
7559                 case P_BOOLREV:
7560                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7561                         break;
7562
7563                 case P_INTEGER:
7564                 case P_BYTES:
7565                         fprintf(f, "%d", *(int *)ptr);
7566                         break;
7567
7568                 case P_CHAR:
7569                         fprintf(f, "%c", *(char *)ptr);
7570                         break;
7571
7572                 case P_OCTAL: {
7573                         int val = *(int *)ptr; 
7574                         if (val == -1) {
7575                                 fprintf(f, "-1");
7576                         } else {
7577                                 fprintf(f, "0%o", val);
7578                         }
7579                         break;
7580                 }
7581
7582                 case P_CMDLIST:
7583                         list_sep = " ";
7584                         /* fall through */
7585                 case P_LIST:
7586                         if ((char ***)ptr && *(char ***)ptr) {
7587                                 char **list = *(char ***)ptr;
7588                                 for (; *list; list++) {
7589                                         /* surround strings with whitespace in double quotes */
7590                                         if (*(list+1) == NULL) {
7591                                                 /* last item, no extra separator */
7592                                                 list_sep = "";
7593                                         }
7594                                         if ( strchr_m( *list, ' ' ) ) {
7595                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
7596                                         } else {
7597                                                 fprintf(f, "%s%s", *list, list_sep);
7598                                         }
7599                                 }
7600                         }
7601                         break;
7602
7603                 case P_STRING:
7604                 case P_USTRING:
7605                         if (*(char **)ptr) {
7606                                 fprintf(f, "%s", *(char **)ptr);
7607                         }
7608                         break;
7609                 case P_SEP:
7610                         break;
7611         }
7612 }
7613
7614 /***************************************************************************
7615  Check if two parameters are equal.
7616 ***************************************************************************/
7617
7618 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7619 {
7620         switch (type) {
7621                 case P_BOOL:
7622                 case P_BOOLREV:
7623                         return (*((bool *)ptr1) == *((bool *)ptr2));
7624
7625                 case P_INTEGER:
7626                 case P_ENUM:
7627                 case P_OCTAL:
7628                 case P_BYTES:
7629                         return (*((int *)ptr1) == *((int *)ptr2));
7630
7631                 case P_CHAR:
7632                         return (*((char *)ptr1) == *((char *)ptr2));
7633
7634                 case P_LIST:
7635                 case P_CMDLIST:
7636                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7637
7638                 case P_STRING:
7639                 case P_USTRING:
7640                 {
7641                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7642                         if (p1 && !*p1)
7643                                 p1 = NULL;
7644                         if (p2 && !*p2)
7645                                 p2 = NULL;
7646                         return (p1 == p2 || strequal(p1, p2));
7647                 }
7648                 case P_SEP:
7649                         break;
7650         }
7651         return false;
7652 }
7653
7654 /***************************************************************************
7655  Initialize any local varients in the sDefault table.
7656 ***************************************************************************/
7657
7658 void init_locals(void)
7659 {
7660         /* None as yet. */
7661 }
7662
7663 /***************************************************************************
7664  Process a new section (service). At this stage all sections are services.
7665  Later we'll have special sections that permit server parameters to be set.
7666  Returns true on success, false on failure.
7667 ***************************************************************************/
7668
7669 static bool do_section(const char *pszSectionName, void *userdata)
7670 {
7671         bool bRetval;
7672         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7673                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7674         bRetval = false;
7675
7676         /* if we were in a global section then do the local inits */
7677         if (bInGlobalSection && !isglobal)
7678                 init_locals();
7679
7680         /* if we've just struck a global section, note the fact. */
7681         bInGlobalSection = isglobal;
7682
7683         /* check for multiple global sections */
7684         if (bInGlobalSection) {
7685                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7686                 return true;
7687         }
7688
7689         if (!bInGlobalSection && bGlobalOnly)
7690                 return true;
7691
7692         /* if we have a current service, tidy it up before moving on */
7693         bRetval = true;
7694
7695         if (iServiceIndex >= 0)
7696                 bRetval = service_ok(iServiceIndex);
7697
7698         /* if all is still well, move to the next record in the services array */
7699         if (bRetval) {
7700                 /* We put this here to avoid an odd message order if messages are */
7701                 /* issued by the post-processing of a previous section. */
7702                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7703
7704                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
7705                 if (iServiceIndex < 0) {
7706                         DEBUG(0, ("Failed to add a new service\n"));
7707                         return false;
7708                 }
7709                 /* Clean all parametric options for service */
7710                 /* They will be added during parsing again */
7711                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
7712         }
7713
7714         return bRetval;
7715 }
7716
7717
7718 /***************************************************************************
7719  Determine if a partcular base parameter is currentl set to the default value.
7720 ***************************************************************************/
7721
7722 static bool is_default(int i)
7723 {
7724         if (!defaults_saved)
7725                 return false;
7726         switch (parm_table[i].type) {
7727                 case P_LIST:
7728                 case P_CMDLIST:
7729                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
7730                                               *(const char ***)lp_parm_ptr(NULL, 
7731                                                                            &parm_table[i]));
7732                 case P_STRING:
7733                 case P_USTRING:
7734                         return strequal(parm_table[i].def.svalue,
7735                                         *(char **)lp_parm_ptr(NULL, 
7736                                                               &parm_table[i]));
7737                 case P_BOOL:
7738                 case P_BOOLREV:
7739                         return parm_table[i].def.bvalue ==
7740                                 *(bool *)lp_parm_ptr(NULL, 
7741                                                      &parm_table[i]);
7742                 case P_CHAR:
7743                         return parm_table[i].def.cvalue ==
7744                                 *(char *)lp_parm_ptr(NULL, 
7745                                                      &parm_table[i]);
7746                 case P_INTEGER:
7747                 case P_OCTAL:
7748                 case P_ENUM:
7749                 case P_BYTES:
7750                         return parm_table[i].def.ivalue ==
7751                                 *(int *)lp_parm_ptr(NULL, 
7752                                                     &parm_table[i]);
7753                 case P_SEP:
7754                         break;
7755         }
7756         return false;
7757 }
7758
7759 /***************************************************************************
7760 Display the contents of the global structure.
7761 ***************************************************************************/
7762
7763 static void dump_globals(FILE *f)
7764 {
7765         int i;
7766         struct parmlist_entry *data;
7767
7768         fprintf(f, "[global]\n");
7769
7770         for (i = 0; parm_table[i].label; i++)
7771                 if (parm_table[i].p_class == P_GLOBAL &&
7772                     !(parm_table[i].flags & FLAG_META) &&
7773                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
7774                         if (defaults_saved && is_default(i))
7775                                 continue;
7776                         fprintf(f, "\t%s = ", parm_table[i].label);
7777                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
7778                                                                     &parm_table[i]),
7779                                         f);
7780                         fprintf(f, "\n");
7781         }
7782         if (Globals.param_opt != NULL) {
7783                 data = Globals.param_opt;
7784                 while(data) {
7785                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7786                         data = data->next;
7787                 }
7788         }
7789
7790 }
7791
7792 /***************************************************************************
7793  Return true if a local parameter is currently set to the global default.
7794 ***************************************************************************/
7795
7796 bool lp_is_default(int snum, struct parm_struct *parm)
7797 {
7798         return equal_parameter(parm->type,
7799                                lp_parm_ptr(ServicePtrs[snum], parm),
7800                                lp_parm_ptr(NULL, parm));
7801 }
7802
7803 /***************************************************************************
7804  Display the contents of a single services record.
7805 ***************************************************************************/
7806
7807 static void dump_a_service(struct loadparm_service *pService, FILE * f)
7808 {
7809         int i;
7810         struct parmlist_entry *data;
7811
7812         if (pService != &sDefault)
7813                 fprintf(f, "[%s]\n", pService->szService);
7814
7815         for (i = 0; parm_table[i].label; i++) {
7816
7817                 if (parm_table[i].p_class == P_LOCAL &&
7818                     !(parm_table[i].flags & FLAG_META) &&
7819                     (*parm_table[i].label != '-') &&
7820                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7821                 {
7822                         if (pService == &sDefault) {
7823                                 if (defaults_saved && is_default(i))
7824                                         continue;
7825                         } else {
7826                                 if (equal_parameter(parm_table[i].type,
7827                                                     lp_parm_ptr(pService, &parm_table[i]),
7828                                                     lp_parm_ptr(NULL, &parm_table[i])))
7829                                         continue;
7830                         }
7831
7832                         fprintf(f, "\t%s = ", parm_table[i].label);
7833                         print_parameter(&parm_table[i],
7834                                         lp_parm_ptr(pService, &parm_table[i]),
7835                                         f);
7836                         fprintf(f, "\n");
7837                 }
7838         }
7839
7840                 if (pService->param_opt != NULL) {
7841                         data = pService->param_opt;
7842                         while(data) {
7843                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7844                                 data = data->next;
7845                         }
7846                 }
7847 }
7848
7849 /***************************************************************************
7850  Display the contents of a parameter of a single services record.
7851 ***************************************************************************/
7852
7853 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7854 {
7855         int i;
7856         bool result = false;
7857         parm_class p_class;
7858         unsigned flag = 0;
7859         fstring local_parm_name;
7860         char *parm_opt;
7861         const char *parm_opt_value;
7862
7863         /* check for parametrical option */
7864         fstrcpy( local_parm_name, parm_name);
7865         parm_opt = strchr( local_parm_name, ':');
7866
7867         if (parm_opt) {
7868                 *parm_opt = '\0';
7869                 parm_opt++;
7870                 if (strlen(parm_opt)) {
7871                         parm_opt_value = lp_parm_const_string( snum,
7872                                 local_parm_name, parm_opt, NULL);
7873                         if (parm_opt_value) {
7874                                 printf( "%s\n", parm_opt_value);
7875                                 result = true;
7876                         }
7877                 }
7878                 return result;
7879         }
7880
7881         /* check for a key and print the value */
7882         if (isGlobal) {
7883                 p_class = P_GLOBAL;
7884                 flag = FLAG_GLOBAL;
7885         } else
7886                 p_class = P_LOCAL;
7887
7888         for (i = 0; parm_table[i].label; i++) {
7889                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7890                     !(parm_table[i].flags & FLAG_META) &&
7891                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7892                     (*parm_table[i].label != '-') &&
7893                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7894                 {
7895                         void *ptr;
7896
7897                         if (isGlobal) {
7898                                 ptr = lp_parm_ptr(NULL, 
7899                                                   &parm_table[i]);
7900                         } else {
7901                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
7902                                                   &parm_table[i]);
7903                         }
7904
7905                         print_parameter(&parm_table[i],
7906                                         ptr, f);
7907                         fprintf(f, "\n");
7908                         result = true;
7909                         break;
7910                 }
7911         }
7912
7913         return result;
7914 }
7915
7916 /***************************************************************************
7917  Return info about the requested parameter (given as a string).
7918  Return NULL when the string is not a valid parameter name.
7919 ***************************************************************************/
7920
7921 struct parm_struct *lp_get_parameter(const char *param_name)
7922 {
7923         int num = map_parameter(param_name);
7924
7925         if (num < 0) {
7926                 return NULL;
7927         }
7928
7929         return &parm_table[num];
7930 }
7931
7932 /***************************************************************************
7933  Return info about the next parameter in a service.
7934  snum==GLOBAL_SECTION_SNUM gives the globals.
7935  Return NULL when out of parameters.
7936 ***************************************************************************/
7937
7938 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7939 {
7940         if (snum < 0) {
7941                 /* do the globals */
7942                 for (; parm_table[*i].label; (*i)++) {
7943                         if (parm_table[*i].p_class == P_SEPARATOR)
7944                                 return &parm_table[(*i)++];
7945
7946                         if ((*parm_table[*i].label == '-'))
7947                                 continue;
7948
7949                         if ((*i) > 0
7950                             && (parm_table[*i].offset ==
7951                                 parm_table[(*i) - 1].offset)
7952                             && (parm_table[*i].p_class ==
7953                                 parm_table[(*i) - 1].p_class))
7954                                 continue;
7955
7956                         if (is_default(*i) && !allparameters)
7957                                 continue;
7958
7959                         return &parm_table[(*i)++];
7960                 }
7961         } else {
7962                 struct loadparm_service *pService = ServicePtrs[snum];
7963
7964                 for (; parm_table[*i].label; (*i)++) {
7965                         if (parm_table[*i].p_class == P_SEPARATOR)
7966                                 return &parm_table[(*i)++];
7967
7968                         if (parm_table[*i].p_class == P_LOCAL &&
7969                             (*parm_table[*i].label != '-') &&
7970                             ((*i) == 0 ||
7971                              (parm_table[*i].offset !=
7972                               parm_table[(*i) - 1].offset)))
7973                         {
7974                                 if (allparameters ||
7975                                     !equal_parameter(parm_table[*i].type,
7976                                                      lp_parm_ptr(pService, 
7977                                                                  &parm_table[*i]),
7978                                                      lp_parm_ptr(NULL, 
7979                                                                  &parm_table[*i])))
7980                                 {
7981                                         return &parm_table[(*i)++];
7982                                 }
7983                         }
7984                 }
7985         }
7986
7987         return NULL;
7988 }
7989
7990
7991 #if 0
7992 /***************************************************************************
7993  Display the contents of a single copy structure.
7994 ***************************************************************************/
7995 static void dump_copy_map(bool *pcopymap)
7996 {
7997         int i;
7998         if (!pcopymap)
7999                 return;
8000
8001         printf("\n\tNon-Copied parameters:\n");
8002
8003         for (i = 0; parm_table[i].label; i++)
8004                 if (parm_table[i].p_class == P_LOCAL &&
8005                     parm_table[i].ptr && !pcopymap[i] &&
8006                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
8007                 {
8008                         printf("\t\t%s\n", parm_table[i].label);
8009                 }
8010 }
8011 #endif
8012
8013 /***************************************************************************
8014  Return TRUE if the passed service number is within range.
8015 ***************************************************************************/
8016
8017 bool lp_snum_ok(int iService)
8018 {
8019         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
8020 }
8021
8022 /***************************************************************************
8023  Auto-load some home services.
8024 ***************************************************************************/
8025
8026 static void lp_add_auto_services(char *str)
8027 {
8028         char *s;
8029         char *p;
8030         int homes;
8031         char *saveptr;
8032
8033         if (!str)
8034                 return;
8035
8036         s = SMB_STRDUP(str);
8037         if (!s)
8038                 return;
8039
8040         homes = lp_servicenumber(HOMES_NAME);
8041
8042         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
8043              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
8044                 char *home;
8045
8046                 if (lp_servicenumber(p) >= 0)
8047                         continue;
8048
8049                 home = get_user_home_dir(talloc_tos(), p);
8050
8051                 if (home && home[0] && homes >= 0)
8052                         lp_add_home(p, homes, p, home);
8053
8054                 TALLOC_FREE(home);
8055         }
8056         SAFE_FREE(s);
8057 }
8058
8059 /***************************************************************************
8060  Auto-load one printer.
8061 ***************************************************************************/
8062
8063 void lp_add_one_printer(const char *name, const char *comment,
8064                         const char *location, void *pdata)
8065 {
8066         int printers = lp_servicenumber(PRINTERS_NAME);
8067         int i;
8068
8069         if (lp_servicenumber(name) < 0) {
8070                 lp_add_printer(name, printers);
8071                 if ((i = lp_servicenumber(name)) >= 0) {
8072                         string_set(&ServicePtrs[i]->comment, comment);
8073                         ServicePtrs[i]->autoloaded = true;
8074                 }
8075         }
8076 }
8077
8078 /***************************************************************************
8079  Have we loaded a services file yet?
8080 ***************************************************************************/
8081
8082 bool lp_loaded(void)
8083 {
8084         return (bLoaded);
8085 }
8086
8087 /***************************************************************************
8088  Unload unused services.
8089 ***************************************************************************/
8090
8091 void lp_killunused(struct smbd_server_connection *sconn,
8092                    bool (*snumused) (struct smbd_server_connection *, int))
8093 {
8094         int i;
8095         for (i = 0; i < iNumServices; i++) {
8096                 if (!VALID(i))
8097                         continue;
8098
8099                 /* don't kill autoloaded or usershare services */
8100                 if ( ServicePtrs[i]->autoloaded ||
8101                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
8102                         continue;
8103                 }
8104
8105                 if (!snumused || !snumused(sconn, i)) {
8106                         free_service_byindex(i);
8107                 }
8108         }
8109 }
8110
8111 /**
8112  * Kill all except autoloaded and usershare services - convenience wrapper
8113  */
8114 void lp_kill_all_services(void)
8115 {
8116         lp_killunused(NULL, NULL);
8117 }
8118
8119 /***************************************************************************
8120  Unload a service.
8121 ***************************************************************************/
8122
8123 void lp_killservice(int iServiceIn)
8124 {
8125         if (VALID(iServiceIn)) {
8126                 free_service_byindex(iServiceIn);
8127         }
8128 }
8129
8130 /***************************************************************************
8131  Save the curent values of all global and sDefault parameters into the 
8132  defaults union. This allows swat and testparm to show only the
8133  changed (ie. non-default) parameters.
8134 ***************************************************************************/
8135
8136 static void lp_save_defaults(void)
8137 {
8138         int i;
8139         for (i = 0; parm_table[i].label; i++) {
8140                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
8141                     && parm_table[i].p_class == parm_table[i - 1].p_class)
8142                         continue;
8143                 switch (parm_table[i].type) {
8144                         case P_LIST:
8145                         case P_CMDLIST:
8146                                 parm_table[i].def.lvalue = str_list_copy(
8147                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
8148                                 break;
8149                         case P_STRING:
8150                         case P_USTRING:
8151                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
8152                                 break;
8153                         case P_BOOL:
8154                         case P_BOOLREV:
8155                                 parm_table[i].def.bvalue =
8156                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
8157                                 break;
8158                         case P_CHAR:
8159                                 parm_table[i].def.cvalue =
8160                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
8161                                 break;
8162                         case P_INTEGER:
8163                         case P_OCTAL:
8164                         case P_ENUM:
8165                         case P_BYTES:
8166                                 parm_table[i].def.ivalue =
8167                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
8168                                 break;
8169                         case P_SEP:
8170                                 break;
8171                 }
8172         }
8173         defaults_saved = true;
8174 }
8175
8176 /***********************************************************
8177  If we should send plaintext/LANMAN passwords in the clinet
8178 ************************************************************/
8179
8180 static void set_allowed_client_auth(void)
8181 {
8182         if (Globals.bClientNTLMv2Auth) {
8183                 Globals.bClientLanManAuth = false;
8184         }
8185         if (!Globals.bClientLanManAuth) {
8186                 Globals.bClientPlaintextAuth = false;
8187         }
8188 }
8189
8190 /***************************************************************************
8191  JRA.
8192  The following code allows smbd to read a user defined share file.
8193  Yes, this is my intent. Yes, I'm comfortable with that...
8194
8195  THE FOLLOWING IS SECURITY CRITICAL CODE.
8196
8197  It washes your clothes, it cleans your house, it guards you while you sleep...
8198  Do not f%^k with it....
8199 ***************************************************************************/
8200
8201 #define MAX_USERSHARE_FILE_SIZE (10*1024)
8202
8203 /***************************************************************************
8204  Check allowed stat state of a usershare file.
8205  Ensure we print out who is dicking with us so the admin can
8206  get their sorry ass fired.
8207 ***************************************************************************/
8208
8209 static bool check_usershare_stat(const char *fname,
8210                                  const SMB_STRUCT_STAT *psbuf)
8211 {
8212         if (!S_ISREG(psbuf->st_ex_mode)) {
8213                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8214                         "not a regular file\n",
8215                         fname, (unsigned int)psbuf->st_ex_uid ));
8216                 return false;
8217         }
8218
8219         /* Ensure this doesn't have the other write bit set. */
8220         if (psbuf->st_ex_mode & S_IWOTH) {
8221                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
8222                         "public write. Refusing to allow as a usershare file.\n",
8223                         fname, (unsigned int)psbuf->st_ex_uid ));
8224                 return false;
8225         }
8226
8227         /* Should be 10k or less. */
8228         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
8229                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8230                         "too large (%u) to be a user share file.\n",
8231                         fname, (unsigned int)psbuf->st_ex_uid,
8232                         (unsigned int)psbuf->st_ex_size ));
8233                 return false;
8234         }
8235
8236         return true;
8237 }
8238
8239 /***************************************************************************
8240  Parse the contents of a usershare file.
8241 ***************************************************************************/
8242
8243 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8244                         SMB_STRUCT_STAT *psbuf,
8245                         const char *servicename,
8246                         int snum,
8247                         char **lines,
8248                         int numlines,
8249                         char **pp_sharepath,
8250                         char **pp_comment,
8251                         char **pp_cp_servicename,
8252                         struct security_descriptor **ppsd,
8253                         bool *pallow_guest)
8254 {
8255         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8256         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8257         int us_vers;
8258         DIR *dp;
8259         SMB_STRUCT_STAT sbuf;
8260         char *sharepath = NULL;
8261         char *comment = NULL;
8262
8263         *pp_sharepath = NULL;
8264         *pp_comment = NULL;
8265
8266         *pallow_guest = false;
8267
8268         if (numlines < 4) {
8269                 return USERSHARE_MALFORMED_FILE;
8270         }
8271
8272         if (strcmp(lines[0], "#VERSION 1") == 0) {
8273                 us_vers = 1;
8274         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8275                 us_vers = 2;
8276                 if (numlines < 5) {
8277                         return USERSHARE_MALFORMED_FILE;
8278                 }
8279         } else {
8280                 return USERSHARE_BAD_VERSION;
8281         }
8282
8283         if (strncmp(lines[1], "path=", 5) != 0) {
8284                 return USERSHARE_MALFORMED_PATH;
8285         }
8286
8287         sharepath = talloc_strdup(ctx, &lines[1][5]);
8288         if (!sharepath) {
8289                 return USERSHARE_POSIX_ERR;
8290         }
8291         trim_string(sharepath, " ", " ");
8292
8293         if (strncmp(lines[2], "comment=", 8) != 0) {
8294                 return USERSHARE_MALFORMED_COMMENT_DEF;
8295         }
8296
8297         comment = talloc_strdup(ctx, &lines[2][8]);
8298         if (!comment) {
8299                 return USERSHARE_POSIX_ERR;
8300         }
8301         trim_string(comment, " ", " ");
8302         trim_char(comment, '"', '"');
8303
8304         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8305                 return USERSHARE_MALFORMED_ACL_DEF;
8306         }
8307
8308         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8309                 return USERSHARE_ACL_ERR;
8310         }
8311
8312         if (us_vers == 2) {
8313                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8314                         return USERSHARE_MALFORMED_ACL_DEF;
8315                 }
8316                 if (lines[4][9] == 'y') {
8317                         *pallow_guest = true;
8318                 }
8319
8320                 /* Backwards compatible extension to file version #2. */
8321                 if (numlines > 5) {
8322                         if (strncmp(lines[5], "sharename=", 10) != 0) {
8323                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
8324                         }
8325                         if (!strequal(&lines[5][10], servicename)) {
8326                                 return USERSHARE_BAD_SHARENAME;
8327                         }
8328                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
8329                         if (!*pp_cp_servicename) {
8330                                 return USERSHARE_POSIX_ERR;
8331                         }
8332                 }
8333         }
8334
8335         if (*pp_cp_servicename == NULL) {
8336                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
8337                 if (!*pp_cp_servicename) {
8338                         return USERSHARE_POSIX_ERR;
8339                 }
8340         }
8341
8342         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8343                 /* Path didn't change, no checks needed. */
8344                 *pp_sharepath = sharepath;
8345                 *pp_comment = comment;
8346                 return USERSHARE_OK;
8347         }
8348
8349         /* The path *must* be absolute. */
8350         if (sharepath[0] != '/') {
8351                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8352                         servicename, sharepath));
8353                 return USERSHARE_PATH_NOT_ABSOLUTE;
8354         }
8355
8356         /* If there is a usershare prefix deny list ensure one of these paths
8357            doesn't match the start of the user given path. */
8358         if (prefixdenylist) {
8359                 int i;
8360                 for ( i=0; prefixdenylist[i]; i++ ) {
8361                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8362                                 servicename, i, prefixdenylist[i], sharepath ));
8363                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8364                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8365                                         "usershare prefix deny list entries.\n",
8366                                         servicename, sharepath));
8367                                 return USERSHARE_PATH_IS_DENIED;
8368                         }
8369                 }
8370         }
8371
8372         /* If there is a usershare prefix allow list ensure one of these paths
8373            does match the start of the user given path. */
8374
8375         if (prefixallowlist) {
8376                 int i;
8377                 for ( i=0; prefixallowlist[i]; i++ ) {
8378                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8379                                 servicename, i, prefixallowlist[i], sharepath ));
8380                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8381                                 break;
8382                         }
8383                 }
8384                 if (prefixallowlist[i] == NULL) {
8385                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8386                                 "usershare prefix allow list entries.\n",
8387                                 servicename, sharepath));
8388                         return USERSHARE_PATH_NOT_ALLOWED;
8389                 }
8390         }
8391
8392         /* Ensure this is pointing to a directory. */
8393         dp = opendir(sharepath);
8394
8395         if (!dp) {
8396                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8397                         servicename, sharepath));
8398                 return USERSHARE_PATH_NOT_DIRECTORY;
8399         }
8400
8401         /* Ensure the owner of the usershare file has permission to share
8402            this directory. */
8403
8404         if (sys_stat(sharepath, &sbuf, false) == -1) {
8405                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8406                         servicename, sharepath, strerror(errno) ));
8407                 closedir(dp);
8408                 return USERSHARE_POSIX_ERR;
8409         }
8410
8411         closedir(dp);
8412
8413         if (!S_ISDIR(sbuf.st_ex_mode)) {
8414                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8415                         servicename, sharepath ));
8416                 return USERSHARE_PATH_NOT_DIRECTORY;
8417         }
8418
8419         /* Check if sharing is restricted to owner-only. */
8420         /* psbuf is the stat of the usershare definition file,
8421            sbuf is the stat of the target directory to be shared. */
8422
8423         if (lp_usershare_owner_only()) {
8424                 /* root can share anything. */
8425                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
8426                         return USERSHARE_PATH_NOT_ALLOWED;
8427                 }
8428         }
8429
8430         *pp_sharepath = sharepath;
8431         *pp_comment = comment;
8432         return USERSHARE_OK;
8433 }
8434
8435 /***************************************************************************
8436  Deal with a usershare file.
8437  Returns:
8438         >= 0 - snum
8439         -1 - Bad name, invalid contents.
8440            - service name already existed and not a usershare, problem
8441             with permissions to share directory etc.
8442 ***************************************************************************/
8443
8444 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8445 {
8446         SMB_STRUCT_STAT sbuf;
8447         SMB_STRUCT_STAT lsbuf;
8448         char *fname = NULL;
8449         char *sharepath = NULL;
8450         char *comment = NULL;
8451         char *cp_service_name = NULL;
8452         char **lines = NULL;
8453         int numlines = 0;
8454         int fd = -1;
8455         int iService = -1;
8456         TALLOC_CTX *ctx = talloc_stackframe();
8457         struct security_descriptor *psd = NULL;
8458         bool guest_ok = false;
8459         char *canon_name = NULL;
8460         bool added_service = false;
8461         int ret = -1;
8462
8463         /* Ensure share name doesn't contain invalid characters. */
8464         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8465                 DEBUG(0,("process_usershare_file: share name %s contains "
8466                         "invalid characters (any of %s)\n",
8467                         file_name, INVALID_SHARENAME_CHARS ));
8468                 goto out;
8469         }
8470
8471         canon_name = canonicalize_servicename(ctx, file_name);
8472         if (!canon_name) {
8473                 goto out;
8474         }
8475
8476         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
8477         if (!fname) {
8478                 goto out;
8479         }
8480
8481         /* Minimize the race condition by doing an lstat before we
8482            open and fstat. Ensure this isn't a symlink link. */
8483
8484         if (sys_lstat(fname, &lsbuf, false) != 0) {
8485                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8486                         fname, strerror(errno) ));
8487                 goto out;
8488         }
8489
8490         /* This must be a regular file, not a symlink, directory or
8491            other strange filetype. */
8492         if (!check_usershare_stat(fname, &lsbuf)) {
8493                 goto out;
8494         }
8495
8496         {
8497                 TDB_DATA data;
8498                 NTSTATUS status;
8499
8500                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
8501                                                canon_name, &data);
8502
8503                 iService = -1;
8504
8505                 if (NT_STATUS_IS_OK(status) &&
8506                     (data.dptr != NULL) &&
8507                     (data.dsize == sizeof(iService))) {
8508                         memcpy(&iService, data.dptr, sizeof(iService));
8509                 }
8510         }
8511
8512         if (iService != -1 &&
8513             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
8514                              &lsbuf.st_ex_mtime) == 0) {
8515                 /* Nothing changed - Mark valid and return. */
8516                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8517                         canon_name ));
8518                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8519                 ret = iService;
8520                 goto out;
8521         }
8522
8523         /* Try and open the file read only - no symlinks allowed. */
8524 #ifdef O_NOFOLLOW
8525         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
8526 #else
8527         fd = open(fname, O_RDONLY, 0);
8528 #endif
8529
8530         if (fd == -1) {
8531                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8532                         fname, strerror(errno) ));
8533                 goto out;
8534         }
8535
8536         /* Now fstat to be *SURE* it's a regular file. */
8537         if (sys_fstat(fd, &sbuf, false) != 0) {
8538                 close(fd);
8539                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8540                         fname, strerror(errno) ));
8541                 goto out;
8542         }
8543
8544         /* Is it the same dev/inode as was lstated ? */
8545         if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) {
8546                 close(fd);
8547                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8548                         "Symlink spoofing going on ?\n", fname ));
8549                 goto out;
8550         }
8551
8552         /* This must be a regular file, not a symlink, directory or
8553            other strange filetype. */
8554         if (!check_usershare_stat(fname, &sbuf)) {
8555                 goto out;
8556         }
8557
8558         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8559
8560         close(fd);
8561         if (lines == NULL) {
8562                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8563                         fname, (unsigned int)sbuf.st_ex_uid ));
8564                 goto out;
8565         }
8566
8567         if (parse_usershare_file(ctx, &sbuf, file_name,
8568                         iService, lines, numlines, &sharepath,
8569                         &comment, &cp_service_name,
8570                         &psd, &guest_ok) != USERSHARE_OK) {
8571                 goto out;
8572         }
8573
8574         /* Everything ok - add the service possibly using a template. */
8575         if (iService < 0) {
8576                 const struct loadparm_service *sp = &sDefault;
8577                 if (snum_template != -1) {
8578                         sp = ServicePtrs[snum_template];
8579                 }
8580
8581                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
8582                         DEBUG(0, ("process_usershare_file: Failed to add "
8583                                 "new service %s\n", cp_service_name));
8584                         goto out;
8585                 }
8586
8587                 added_service = true;
8588
8589                 /* Read only is controlled by usershare ACL below. */
8590                 ServicePtrs[iService]->bRead_only = false;
8591         }
8592
8593         /* Write the ACL of the new/modified share. */
8594         if (!set_share_security(canon_name, psd)) {
8595                  DEBUG(0, ("process_usershare_file: Failed to set share "
8596                         "security for user share %s\n",
8597                         canon_name ));
8598                 goto out;
8599         }
8600
8601         /* If from a template it may be marked invalid. */
8602         ServicePtrs[iService]->valid = true;
8603
8604         /* Set the service as a valid usershare. */
8605         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8606
8607         /* Set guest access. */
8608         if (lp_usershare_allow_guests()) {
8609                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8610         }
8611
8612         /* And note when it was loaded. */
8613         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
8614         string_set(&ServicePtrs[iService]->szPath, sharepath);
8615         string_set(&ServicePtrs[iService]->comment, comment);
8616
8617         ret = iService;
8618
8619   out:
8620
8621         if (ret == -1 && iService != -1 && added_service) {
8622                 lp_remove_service(iService);
8623         }
8624
8625         TALLOC_FREE(lines);
8626         TALLOC_FREE(ctx);
8627         return ret;
8628 }
8629
8630 /***************************************************************************
8631  Checks if a usershare entry has been modified since last load.
8632 ***************************************************************************/
8633
8634 static bool usershare_exists(int iService, struct timespec *last_mod)
8635 {
8636         SMB_STRUCT_STAT lsbuf;
8637         const char *usersharepath = Globals.szUsersharePath;
8638         char *fname;
8639
8640         if (asprintf(&fname, "%s/%s",
8641                                 usersharepath,
8642                                 ServicePtrs[iService]->szService) < 0) {
8643                 return false;
8644         }
8645
8646         if (sys_lstat(fname, &lsbuf, false) != 0) {
8647                 SAFE_FREE(fname);
8648                 return false;
8649         }
8650
8651         if (!S_ISREG(lsbuf.st_ex_mode)) {
8652                 SAFE_FREE(fname);
8653                 return false;
8654         }
8655
8656         SAFE_FREE(fname);
8657         *last_mod = lsbuf.st_ex_mtime;
8658         return true;
8659 }
8660
8661 /***************************************************************************
8662  Load a usershare service by name. Returns a valid servicenumber or -1.
8663 ***************************************************************************/
8664
8665 int load_usershare_service(const char *servicename)
8666 {
8667         SMB_STRUCT_STAT sbuf;
8668         const char *usersharepath = Globals.szUsersharePath;
8669         int max_user_shares = Globals.iUsershareMaxShares;
8670         int snum_template = -1;
8671
8672         if (*usersharepath == 0 ||  max_user_shares == 0) {
8673                 return -1;
8674         }
8675
8676         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8677                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8678                         usersharepath, strerror(errno) ));
8679                 return -1;
8680         }
8681
8682         if (!S_ISDIR(sbuf.st_ex_mode)) {
8683                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8684                         usersharepath ));
8685                 return -1;
8686         }
8687
8688         /*
8689          * This directory must be owned by root, and have the 't' bit set.
8690          * It also must not be writable by "other".
8691          */
8692
8693 #ifdef S_ISVTX
8694         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8695 #else
8696         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8697 #endif
8698                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8699                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8700                         usersharepath ));
8701                 return -1;
8702         }
8703
8704         /* Ensure the template share exists if it's set. */
8705         if (Globals.szUsershareTemplateShare[0]) {
8706                 /* We can't use lp_servicenumber here as we are recommending that
8707                    template shares have -valid=false set. */
8708                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8709                         if (ServicePtrs[snum_template]->szService &&
8710                                         strequal(ServicePtrs[snum_template]->szService,
8711                                                 Globals.szUsershareTemplateShare)) {
8712                                 break;
8713                         }
8714                 }
8715
8716                 if (snum_template == -1) {
8717                         DEBUG(0,("load_usershare_service: usershare template share %s "
8718                                 "does not exist.\n",
8719                                 Globals.szUsershareTemplateShare ));
8720                         return -1;
8721                 }
8722         }
8723
8724         return process_usershare_file(usersharepath, servicename, snum_template);
8725 }
8726
8727 /***************************************************************************
8728  Load all user defined shares from the user share directory.
8729  We only do this if we're enumerating the share list.
8730  This is the function that can delete usershares that have
8731  been removed.
8732 ***************************************************************************/
8733
8734 int load_usershare_shares(struct smbd_server_connection *sconn,
8735                           bool (*snumused) (struct smbd_server_connection *, int))
8736 {
8737         DIR *dp;
8738         SMB_STRUCT_STAT sbuf;
8739         struct dirent *de;
8740         int num_usershares = 0;
8741         int max_user_shares = Globals.iUsershareMaxShares;
8742         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8743         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8744         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8745         int iService;
8746         int snum_template = -1;
8747         const char *usersharepath = Globals.szUsersharePath;
8748         int ret = lp_numservices();
8749
8750         if (max_user_shares == 0 || *usersharepath == '\0') {
8751                 return lp_numservices();
8752         }
8753
8754         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8755                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8756                         usersharepath, strerror(errno) ));
8757                 return ret;
8758         }
8759
8760         /*
8761          * This directory must be owned by root, and have the 't' bit set.
8762          * It also must not be writable by "other".
8763          */
8764
8765 #ifdef S_ISVTX
8766         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8767 #else
8768         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8769 #endif
8770                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8771                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8772                         usersharepath ));
8773                 return ret;
8774         }
8775
8776         /* Ensure the template share exists if it's set. */
8777         if (Globals.szUsershareTemplateShare[0]) {
8778                 /* We can't use lp_servicenumber here as we are recommending that
8779                    template shares have -valid=false set. */
8780                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8781                         if (ServicePtrs[snum_template]->szService &&
8782                                         strequal(ServicePtrs[snum_template]->szService,
8783                                                 Globals.szUsershareTemplateShare)) {
8784                                 break;
8785                         }
8786                 }
8787
8788                 if (snum_template == -1) {
8789                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8790                                 "does not exist.\n",
8791                                 Globals.szUsershareTemplateShare ));
8792                         return ret;
8793                 }
8794         }
8795
8796         /* Mark all existing usershares as pending delete. */
8797         for (iService = iNumServices - 1; iService >= 0; iService--) {
8798                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8799                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8800                 }
8801         }
8802
8803         dp = opendir(usersharepath);
8804         if (!dp) {
8805                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8806                         usersharepath, strerror(errno) ));
8807                 return ret;
8808         }
8809
8810         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8811                         (de = readdir(dp));
8812                         num_dir_entries++ ) {
8813                 int r;
8814                 const char *n = de->d_name;
8815
8816                 /* Ignore . and .. */
8817                 if (*n == '.') {
8818                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8819                                 continue;
8820                         }
8821                 }
8822
8823                 if (n[0] == ':') {
8824                         /* Temporary file used when creating a share. */
8825                         num_tmp_dir_entries++;
8826                 }
8827
8828                 /* Allow 20% tmp entries. */
8829                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8830                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8831                                 "in directory %s\n",
8832                                 num_tmp_dir_entries, usersharepath));
8833                         break;
8834                 }
8835
8836                 r = process_usershare_file(usersharepath, n, snum_template);
8837                 if (r == 0) {
8838                         /* Update the services count. */
8839                         num_usershares++;
8840                         if (num_usershares >= max_user_shares) {
8841                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8842                                         "on file %s in directory %s\n",
8843                                         n, usersharepath ));
8844                                 break;
8845                         }
8846                 } else if (r == -1) {
8847                         num_bad_dir_entries++;
8848                 }
8849
8850                 /* Allow 20% bad entries. */
8851                 if (num_bad_dir_entries > allowed_bad_entries) {
8852                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8853                                 "in directory %s\n",
8854                                 num_bad_dir_entries, usersharepath));
8855                         break;
8856                 }
8857
8858                 /* Allow 20% bad entries. */
8859                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8860                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8861                         "in directory %s\n",
8862                         num_dir_entries, usersharepath));
8863                         break;
8864                 }
8865         }
8866
8867         closedir(dp);
8868
8869         /* Sweep through and delete any non-refreshed usershares that are
8870            not currently in use. */
8871         for (iService = iNumServices - 1; iService >= 0; iService--) {
8872                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8873                         if (snumused && snumused(sconn, iService)) {
8874                                 continue;
8875                         }
8876                         /* Remove from the share ACL db. */
8877                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8878                                 lp_servicename(iService) ));
8879                         delete_share_security(lp_servicename(iService));
8880                         free_service_byindex(iService);
8881                 }
8882         }
8883
8884         return lp_numservices();
8885 }
8886
8887 /********************************************************
8888  Destroy global resources allocated in this file
8889 ********************************************************/
8890
8891 void gfree_loadparm(void)
8892 {
8893         int i;
8894
8895         free_file_list();
8896
8897         /* Free resources allocated to services */
8898
8899         for ( i = 0; i < iNumServices; i++ ) {
8900                 if ( VALID(i) ) {
8901                         free_service_byindex(i);
8902                 }
8903         }
8904
8905         SAFE_FREE( ServicePtrs );
8906         iNumServices = 0;
8907
8908         /* Now release all resources allocated to global
8909            parameters and the default service */
8910
8911         free_global_parameters();
8912 }
8913
8914
8915 /***************************************************************************
8916  Allow client apps to specify that they are a client
8917 ***************************************************************************/
8918 static void lp_set_in_client(bool b)
8919 {
8920     in_client = b;
8921 }
8922
8923
8924 /***************************************************************************
8925  Determine if we're running in a client app
8926 ***************************************************************************/
8927 static bool lp_is_in_client(void)
8928 {
8929     return in_client;
8930 }
8931
8932 /***************************************************************************
8933  Load the services array from the services file. Return true on success,
8934  false on failure.
8935 ***************************************************************************/
8936
8937 static bool lp_load_ex(const char *pszFname,
8938                        bool global_only,
8939                        bool save_defaults,
8940                        bool add_ipc,
8941                        bool initialize_globals,
8942                        bool allow_include_registry,
8943                        bool load_all_shares)
8944 {
8945         char *n2 = NULL;
8946         bool bRetval;
8947
8948         bRetval = false;
8949
8950         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
8951
8952         bInGlobalSection = true;
8953         bGlobalOnly = global_only;
8954         bAllowIncludeRegistry = allow_include_registry;
8955
8956         init_globals(initialize_globals);
8957
8958         free_file_list();
8959
8960         if (save_defaults) {
8961                 init_locals();
8962                 lp_save_defaults();
8963         }
8964
8965         if (!initialize_globals) {
8966                 free_param_opts(&Globals.param_opt);
8967                 apply_lp_set_cmdline();
8968         }
8969
8970         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
8971
8972         /* We get sections first, so have to start 'behind' to make up */
8973         iServiceIndex = -1;
8974
8975         if (lp_config_backend_is_file()) {
8976                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
8977                                         current_user_info.domain,
8978                                         pszFname);
8979                 if (!n2) {
8980                         smb_panic("lp_load_ex: out of memory");
8981                 }
8982
8983                 add_to_file_list(pszFname, n2);
8984
8985                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
8986                 TALLOC_FREE(n2);
8987
8988                 /* finish up the last section */
8989                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
8990                 if (bRetval) {
8991                         if (iServiceIndex >= 0) {
8992                                 bRetval = service_ok(iServiceIndex);
8993                         }
8994                 }
8995
8996                 if (lp_config_backend_is_registry()) {
8997                         /* config backend changed to registry in config file */
8998                         /*
8999                          * We need to use this extra global variable here to
9000                          * survive restart: init_globals uses this as a default
9001                          * for ConfigBackend. Otherwise, init_globals would
9002                          *  send us into an endless loop here.
9003                          */
9004                         config_backend = CONFIG_BACKEND_REGISTRY;
9005                         /* start over */
9006                         DEBUG(1, ("lp_load_ex: changing to config backend "
9007                                   "registry\n"));
9008                         init_globals(true);
9009                         lp_kill_all_services();
9010                         return lp_load_ex(pszFname, global_only, save_defaults,
9011                                           add_ipc, initialize_globals,
9012                                           allow_include_registry,
9013                                           load_all_shares);
9014                 }
9015         } else if (lp_config_backend_is_registry()) {
9016                 bRetval = process_registry_globals();
9017         } else {
9018                 DEBUG(0, ("Illegal config  backend given: %d\n",
9019                           lp_config_backend()));
9020                 bRetval = false;
9021         }
9022
9023         if (bRetval && lp_registry_shares()) {
9024                 if (load_all_shares) {
9025                         bRetval = process_registry_shares();
9026                 } else {
9027                         bRetval = reload_registry_shares();
9028                 }
9029         }
9030
9031         lp_add_auto_services(lp_auto_services());
9032
9033         if (add_ipc) {
9034                 /* When 'restrict anonymous = 2' guest connections to ipc$
9035                    are denied */
9036                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
9037                 if ( lp_enable_asu_support() ) {
9038                         lp_add_ipc("ADMIN$", false);
9039                 }
9040         }
9041
9042         set_allowed_client_auth();
9043
9044         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
9045                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
9046                           lp_passwordserver()));
9047         }
9048
9049         bLoaded = true;
9050
9051         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
9052         /* if bWINSsupport is true and we are in the client            */
9053         if (lp_is_in_client() && Globals.bWINSsupport) {
9054                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
9055         }
9056
9057         init_iconv();
9058
9059         fault_configure(smb_panic_s3);
9060
9061         bAllowIncludeRegistry = true;
9062
9063         return (bRetval);
9064 }
9065
9066 bool lp_load(const char *pszFname,
9067              bool global_only,
9068              bool save_defaults,
9069              bool add_ipc,
9070              bool initialize_globals)
9071 {
9072         return lp_load_ex(pszFname,
9073                           global_only,
9074                           save_defaults,
9075                           add_ipc,
9076                           initialize_globals,
9077                           true,   /* allow_include_registry */
9078                           false); /* load_all_shares*/
9079 }
9080
9081 bool lp_load_initial_only(const char *pszFname)
9082 {
9083         return lp_load_ex(pszFname,
9084                           true,   /* global only */
9085                           false,  /* save_defaults */
9086                           false,  /* add_ipc */
9087                           true,   /* initialize_globals */
9088                           false,  /* allow_include_registry */
9089                           false); /* load_all_shares*/
9090 }
9091
9092 /**
9093  * most common lp_load wrapper, loading only the globals
9094  */
9095 bool lp_load_global(const char *file_name)
9096 {
9097         return lp_load_ex(file_name,
9098                           true,   /* global_only */
9099                           false,  /* save_defaults */
9100                           false,  /* add_ipc */
9101                           true,   /* initialize_globals */
9102                           true,   /* allow_include_registry */
9103                           false); /* load_all_shares*/
9104 }
9105
9106 /**
9107  * lp_load wrapper, especially for clients
9108  */
9109 bool lp_load_client(const char *file_name)
9110 {
9111         lp_set_in_client(true);
9112
9113         return lp_load_global(file_name);
9114 }
9115
9116 /**
9117  * lp_load wrapper, loading only globals, but intended
9118  * for subsequent calls, not reinitializing the globals
9119  * to default values
9120  */
9121 bool lp_load_global_no_reinit(const char *file_name)
9122 {
9123         return lp_load_ex(file_name,
9124                           true,   /* global_only */
9125                           false,  /* save_defaults */
9126                           false,  /* add_ipc */
9127                           false,  /* initialize_globals */
9128                           true,   /* allow_include_registry */
9129                           false); /* load_all_shares*/
9130 }
9131
9132 /**
9133  * lp_load wrapper, especially for clients, no reinitialization
9134  */
9135 bool lp_load_client_no_reinit(const char *file_name)
9136 {
9137         lp_set_in_client(true);
9138
9139         return lp_load_global_no_reinit(file_name);
9140 }
9141
9142 bool lp_load_with_registry_shares(const char *pszFname,
9143                                   bool global_only,
9144                                   bool save_defaults,
9145                                   bool add_ipc,
9146                                   bool initialize_globals)
9147 {
9148         return lp_load_ex(pszFname,
9149                           global_only,
9150                           save_defaults,
9151                           add_ipc,
9152                           initialize_globals,
9153                           true,  /* allow_include_registry */
9154                           true); /* load_all_shares*/
9155 }
9156
9157 /***************************************************************************
9158  Return the max number of services.
9159 ***************************************************************************/
9160
9161 int lp_numservices(void)
9162 {
9163         return (iNumServices);
9164 }
9165
9166 /***************************************************************************
9167 Display the contents of the services array in human-readable form.
9168 ***************************************************************************/
9169
9170 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
9171 {
9172         int iService;
9173
9174         if (show_defaults)
9175                 defaults_saved = false;
9176
9177         dump_globals(f);
9178
9179         dump_a_service(&sDefault, f);
9180
9181         for (iService = 0; iService < maxtoprint; iService++) {
9182                 fprintf(f,"\n");
9183                 lp_dump_one(f, show_defaults, iService);
9184         }
9185 }
9186
9187 /***************************************************************************
9188 Display the contents of one service in human-readable form.
9189 ***************************************************************************/
9190
9191 void lp_dump_one(FILE * f, bool show_defaults, int snum)
9192 {
9193         if (VALID(snum)) {
9194                 if (ServicePtrs[snum]->szService[0] == '\0')
9195                         return;
9196                 dump_a_service(ServicePtrs[snum], f);
9197         }
9198 }
9199
9200 /***************************************************************************
9201 Return the number of the service with the given name, or -1 if it doesn't
9202 exist. Note that this is a DIFFERENT ANIMAL from the internal function
9203 getservicebyname()! This works ONLY if all services have been loaded, and
9204 does not copy the found service.
9205 ***************************************************************************/
9206
9207 int lp_servicenumber(const char *pszServiceName)
9208 {
9209         int iService;
9210         fstring serviceName;
9211
9212         if (!pszServiceName) {
9213                 return GLOBAL_SECTION_SNUM;
9214         }
9215
9216         for (iService = iNumServices - 1; iService >= 0; iService--) {
9217                 if (VALID(iService) && ServicePtrs[iService]->szService) {
9218                         /*
9219                          * The substitution here is used to support %U is
9220                          * service names
9221                          */
9222                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
9223                         standard_sub_basic(get_current_username(),
9224                                            current_user_info.domain,
9225                                            serviceName,sizeof(serviceName));
9226                         if (strequal(serviceName, pszServiceName)) {
9227                                 break;
9228                         }
9229                 }
9230         }
9231
9232         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
9233                 struct timespec last_mod;
9234
9235                 if (!usershare_exists(iService, &last_mod)) {
9236                         /* Remove the share security tdb entry for it. */
9237                         delete_share_security(lp_servicename(iService));
9238                         /* Remove it from the array. */
9239                         free_service_byindex(iService);
9240                         /* Doesn't exist anymore. */
9241                         return GLOBAL_SECTION_SNUM;
9242                 }
9243
9244                 /* Has it been modified ? If so delete and reload. */
9245                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
9246                                      &last_mod) < 0) {
9247                         /* Remove it from the array. */
9248                         free_service_byindex(iService);
9249                         /* and now reload it. */
9250                         iService = load_usershare_service(pszServiceName);
9251                 }
9252         }
9253
9254         if (iService < 0) {
9255                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9256                 return GLOBAL_SECTION_SNUM;
9257         }
9258
9259         return (iService);
9260 }
9261
9262 /*******************************************************************
9263  A useful volume label function. 
9264 ********************************************************************/
9265
9266 const char *volume_label(int snum)
9267 {
9268         char *ret;
9269         const char *label = lp_volume(snum);
9270         if (!*label) {
9271                 label = lp_servicename(snum);
9272         }
9273
9274         /* This returns a 33 byte guarenteed null terminated string. */
9275         ret = talloc_strndup(talloc_tos(), label, 32);
9276         if (!ret) {
9277                 return "";
9278         }               
9279         return ret;
9280 }
9281
9282 /*******************************************************************
9283  Get the default server type we will announce as via nmbd.
9284 ********************************************************************/
9285
9286 int lp_default_server_announce(void)
9287 {
9288         int default_server_announce = 0;
9289         default_server_announce |= SV_TYPE_WORKSTATION;
9290         default_server_announce |= SV_TYPE_SERVER;
9291         default_server_announce |= SV_TYPE_SERVER_UNIX;
9292
9293         /* note that the flag should be set only if we have a 
9294            printer service but nmbd doesn't actually load the 
9295            services so we can't tell   --jerry */
9296
9297         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9298
9299         default_server_announce |= SV_TYPE_SERVER_NT;
9300         default_server_announce |= SV_TYPE_NT;
9301
9302         switch (lp_server_role()) {
9303                 case ROLE_DOMAIN_MEMBER:
9304                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9305                         break;
9306                 case ROLE_DOMAIN_PDC:
9307                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9308                         break;
9309                 case ROLE_DOMAIN_BDC:
9310                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9311                         break;
9312                 case ROLE_STANDALONE:
9313                 default:
9314                         break;
9315         }
9316         if (lp_time_server())
9317                 default_server_announce |= SV_TYPE_TIME_SOURCE;
9318
9319         if (lp_host_msdfs())
9320                 default_server_announce |= SV_TYPE_DFS_SERVER;
9321
9322         return default_server_announce;
9323 }
9324
9325 /***********************************************************
9326  If we are PDC then prefer us as DMB
9327 ************************************************************/
9328
9329 bool lp_domain_master(void)
9330 {
9331         if (Globals.iDomainMaster == Auto)
9332                 return (lp_server_role() == ROLE_DOMAIN_PDC);
9333
9334         return (bool)Globals.iDomainMaster;
9335 }
9336
9337 /***********************************************************
9338  If we are PDC then prefer us as DMB
9339 ************************************************************/
9340
9341 static bool lp_domain_master_true_or_auto(void)
9342 {
9343         if (Globals.iDomainMaster) /* auto or yes */
9344                 return true;
9345
9346         return false;
9347 }
9348
9349 /***********************************************************
9350  If we are DMB then prefer us as LMB
9351 ************************************************************/
9352
9353 bool lp_preferred_master(void)
9354 {
9355         if (Globals.iPreferredMaster == Auto)
9356                 return (lp_local_master() && lp_domain_master());
9357
9358         return (bool)Globals.iPreferredMaster;
9359 }
9360
9361 /*******************************************************************
9362  Remove a service.
9363 ********************************************************************/
9364
9365 void lp_remove_service(int snum)
9366 {
9367         ServicePtrs[snum]->valid = false;
9368         invalid_services[num_invalid_services++] = snum;
9369 }
9370
9371 /*******************************************************************
9372  Copy a service.
9373 ********************************************************************/
9374
9375 void lp_copy_service(int snum, const char *new_name)
9376 {
9377         do_section(new_name, NULL);
9378         if (snum >= 0) {
9379                 snum = lp_servicenumber(new_name);
9380                 if (snum >= 0)
9381                         lp_do_parameter(snum, "copy", lp_servicename(snum));
9382         }
9383 }
9384
9385
9386 /***********************************************************
9387  Set the global name resolution order (used in smbclient).
9388 ************************************************************/
9389
9390 void lp_set_name_resolve_order(const char *new_order)
9391 {
9392         string_set(&Globals.szNameResolveOrder, new_order);
9393 }
9394
9395 const char *lp_printername(int snum)
9396 {
9397         const char *ret = lp__printername(snum);
9398         if (ret == NULL || (ret != NULL && *ret == '\0'))
9399                 ret = lp_const_servicename(snum);
9400
9401         return ret;
9402 }
9403
9404
9405 /***********************************************************
9406  Allow daemons such as winbindd to fix their logfile name.
9407 ************************************************************/
9408
9409 void lp_set_logfile(const char *name)
9410 {
9411         string_set(&Globals.logfile, name);
9412         debug_set_logfile(name);
9413 }
9414
9415 /*******************************************************************
9416  Return the max print jobs per queue.
9417 ********************************************************************/
9418
9419 int lp_maxprintjobs(int snum)
9420 {
9421         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9422         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9423                 maxjobs = PRINT_MAX_JOBID - 1;
9424
9425         return maxjobs;
9426 }
9427
9428 const char *lp_printcapname(void)
9429 {
9430         if ((Globals.szPrintcapname != NULL) &&
9431             (Globals.szPrintcapname[0] != '\0'))
9432                 return Globals.szPrintcapname;
9433
9434         if (sDefault.iPrinting == PRINT_CUPS) {
9435 #ifdef HAVE_CUPS
9436                 return "cups";
9437 #else
9438                 return "lpstat";
9439 #endif
9440         }
9441
9442         if (sDefault.iPrinting == PRINT_BSD)
9443                 return "/etc/printcap";
9444
9445         return PRINTCAP_NAME;
9446 }
9447
9448 static uint32 spoolss_state;
9449
9450 bool lp_disable_spoolss( void )
9451 {
9452         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9453                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9454
9455         return spoolss_state == SVCCTL_STOPPED ? true : false;
9456 }
9457
9458 void lp_set_spoolss_state( uint32 state )
9459 {
9460         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9461
9462         spoolss_state = state;
9463 }
9464
9465 uint32 lp_get_spoolss_state( void )
9466 {
9467         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9468 }
9469
9470 /*******************************************************************
9471  Ensure we don't use sendfile if server smb signing is active.
9472 ********************************************************************/
9473
9474 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
9475 {
9476         bool sign_active = false;
9477
9478         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9479         if (get_Protocol() < PROTOCOL_NT1) {
9480                 return false;
9481         }
9482         if (signing_state) {
9483                 sign_active = smb_signing_is_active(signing_state);
9484         }
9485         return (lp__use_sendfile(snum) &&
9486                         (get_remote_arch() != RA_WIN95) &&
9487                         !sign_active);
9488 }
9489
9490 /*******************************************************************
9491  Turn off sendfile if we find the underlying OS doesn't support it.
9492 ********************************************************************/
9493
9494 void set_use_sendfile(int snum, bool val)
9495 {
9496         if (LP_SNUM_OK(snum))
9497                 ServicePtrs[snum]->bUseSendfile = val;
9498         else
9499                 sDefault.bUseSendfile = val;
9500 }
9501
9502 /*******************************************************************
9503  Turn off storing DOS attributes if this share doesn't support it.
9504 ********************************************************************/
9505
9506 void set_store_dos_attributes(int snum, bool val)
9507 {
9508         if (!LP_SNUM_OK(snum))
9509                 return;
9510         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9511 }
9512
9513 void lp_set_mangling_method(const char *new_method)
9514 {
9515         string_set(&Globals.szManglingMethod, new_method);
9516 }
9517
9518 /*******************************************************************
9519  Global state for POSIX pathname processing.
9520 ********************************************************************/
9521
9522 static bool posix_pathnames;
9523
9524 bool lp_posix_pathnames(void)
9525 {
9526         return posix_pathnames;
9527 }
9528
9529 /*******************************************************************
9530  Change everything needed to ensure POSIX pathname processing (currently
9531  not much).
9532 ********************************************************************/
9533
9534 void lp_set_posix_pathnames(void)
9535 {
9536         posix_pathnames = true;
9537 }
9538
9539 /*******************************************************************
9540  Global state for POSIX lock processing - CIFS unix extensions.
9541 ********************************************************************/
9542
9543 bool posix_default_lock_was_set;
9544 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9545
9546 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9547 {
9548         if (posix_default_lock_was_set) {
9549                 return posix_cifsx_locktype;
9550         } else {
9551                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9552         }
9553 }
9554
9555 /*******************************************************************
9556 ********************************************************************/
9557
9558 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9559 {
9560         posix_default_lock_was_set = true;
9561         posix_cifsx_locktype = val;
9562 }
9563
9564 int lp_min_receive_file_size(void)
9565 {
9566         if (Globals.iminreceivefile < 0) {
9567                 return 0;
9568         }
9569         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9570 }
9571
9572 /*******************************************************************
9573  If socket address is an empty character string, it is necessary to 
9574  define it as "0.0.0.0". 
9575 ********************************************************************/
9576
9577 const char *lp_socket_address(void)
9578 {
9579         char *sock_addr = Globals.szSocketAddress;
9580
9581         if (sock_addr[0] == '\0'){
9582                 string_set(&Globals.szSocketAddress, "0.0.0.0");
9583         }
9584         return  Globals.szSocketAddress;
9585 }
9586
9587 /*******************************************************************
9588  Safe wide links checks.
9589  This helper function always verify the validity of wide links,
9590  even after a configuration file reload.
9591 ********************************************************************/
9592
9593 static bool lp_widelinks_internal(int snum)
9594 {
9595         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
9596                         sDefault.bWidelinks);
9597 }
9598
9599 void widelinks_warning(int snum)
9600 {
9601         if (lp_allow_insecure_widelinks()) {
9602                 return;
9603         }
9604
9605         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
9606                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
9607                         "These parameters are incompatible. "
9608                         "Wide links will be disabled for this share.\n",
9609                         lp_servicename(snum) ));
9610         }
9611 }
9612
9613 bool lp_widelinks(int snum)
9614 {
9615         /* wide links is always incompatible with unix extensions */
9616         if (lp_unix_extensions()) {
9617                 /*
9618                  * Unless we have "allow insecure widelinks"
9619                  * turned on.
9620                  */
9621                 if (!lp_allow_insecure_widelinks()) {
9622                         return false;
9623                 }
9624         }
9625
9626         return lp_widelinks_internal(snum);
9627 }
9628
9629 bool lp_writeraw(void)
9630 {
9631         if (lp_async_smb_echo_handler()) {
9632                 return false;
9633         }
9634         return lp__writeraw();
9635 }
9636
9637 bool lp_readraw(void)
9638 {
9639         if (lp_async_smb_echo_handler()) {
9640                 return false;
9641         }
9642         return lp__readraw();
9643 }
9644
9645 int lp_server_role(void)
9646 {
9647         return lp_find_server_role(lp__server_role(),
9648                                    lp_security(),
9649                                    lp_domain_logons(),
9650                                    lp_domain_master_true_or_auto());
9651 }
9652
9653 const char *lp_ctdbd_socket(void)
9654 {
9655         const char *result = lp__ctdbd_socket();
9656
9657 #ifdef CLUSTER_SUPPORT
9658         if ((result == NULL) || (*result == '\0')) {
9659                 return CTDB_PATH;
9660         }
9661 #endif
9662         return result;
9663 }