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