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