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