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