lib/util Move bitmap.c to lib/util
[kai/samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "printing.h"
60 #include "lib/smbconf/smbconf.h"
61 #include "lib/smbconf/smbconf_init.h"
62 #include "lib/param/loadparm.h"
63
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "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].flags & FLAG_HIDE) &&
6363             !(parm_table[parm2].flags & FLAG_HIDE))
6364         {
6365                 if (inverse != NULL) {
6366                         if ((parm_table[parm1].type == P_BOOLREV) &&
6367                             (parm_table[parm2].type == P_BOOL))
6368                         {
6369                                 *inverse = true;
6370                         } else {
6371                                 *inverse = false;
6372                         }
6373                 }
6374                 return true;
6375         }
6376         return false;
6377 }
6378
6379 /***************************************************************************
6380  Show one parameter's name, type, [values,] and flags.
6381  (helper functions for show_parameter_list)
6382 ***************************************************************************/
6383
6384 static void show_parameter(int parmIndex)
6385 {
6386         int enumIndex, flagIndex;
6387         int parmIndex2;
6388         bool hadFlag;
6389         bool hadSyn;
6390         bool inverse;
6391         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
6392                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
6393                 "P_ENUM", "P_SEP"};
6394         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
6395                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
6396                 FLAG_HIDE};
6397         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
6398                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
6399                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
6400
6401         printf("%s=%s", parm_table[parmIndex].label,
6402                type[parm_table[parmIndex].type]);
6403         if (parm_table[parmIndex].type == P_ENUM) {
6404                 printf(",");
6405                 for (enumIndex=0;
6406                      parm_table[parmIndex].enum_list[enumIndex].name;
6407                      enumIndex++)
6408                 {
6409                         printf("%s%s",
6410                                enumIndex ? "|" : "",
6411                                parm_table[parmIndex].enum_list[enumIndex].name);
6412                 }
6413         }
6414         printf(",");
6415         hadFlag = false;
6416         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
6417                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
6418                         printf("%s%s",
6419                                 hadFlag ? "|" : "",
6420                                 flag_names[flagIndex]);
6421                         hadFlag = true;
6422                 }
6423         }
6424
6425         /* output synonyms */
6426         hadSyn = false;
6427         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6428                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6429                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6430                                parm_table[parmIndex2].label);
6431                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6432                         if (!hadSyn) {
6433                                 printf(" (synonyms: ");
6434                                 hadSyn = true;
6435                         } else {
6436                                 printf(", ");
6437                         }
6438                         printf("%s%s", parm_table[parmIndex2].label,
6439                                inverse ? "[i]" : "");
6440                 }
6441         }
6442         if (hadSyn) {
6443                 printf(")");
6444         }
6445
6446         printf("\n");
6447 }
6448
6449 /***************************************************************************
6450  Show all parameter's name, type, [values,] and flags.
6451 ***************************************************************************/
6452
6453 void show_parameter_list(void)
6454 {
6455         int classIndex, parmIndex;
6456         const char *section_names[] = { "local", "global", NULL};
6457
6458         for (classIndex=0; section_names[classIndex]; classIndex++) {
6459                 printf("[%s]\n", section_names[classIndex]);
6460                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6461                         if (parm_table[parmIndex].p_class == classIndex) {
6462                                 show_parameter(parmIndex);
6463                         }
6464                 }
6465         }
6466 }
6467
6468 /***************************************************************************
6469  Check if a given string correctly represents a boolean value.
6470 ***************************************************************************/
6471
6472 bool lp_string_is_valid_boolean(const char *parm_value)
6473 {
6474         return set_boolean(parm_value, NULL);
6475 }
6476
6477 /***************************************************************************
6478  Get the standard string representation of a boolean value ("yes" or "no")
6479 ***************************************************************************/
6480
6481 static const char *get_boolean(bool bool_value)
6482 {
6483         static const char *yes_str = "yes";
6484         static const char *no_str = "no";
6485
6486         return (bool_value ? yes_str : no_str);
6487 }
6488
6489 /***************************************************************************
6490  Provide the string of the negated boolean value associated to the boolean
6491  given as a string. Returns false if the passed string does not correctly
6492  represent a boolean.
6493 ***************************************************************************/
6494
6495 bool lp_invert_boolean(const char *str, const char **inverse_str)
6496 {
6497         bool val;
6498
6499         if (!set_boolean(str, &val)) {
6500                 return false;
6501         }
6502
6503         *inverse_str = get_boolean(!val);
6504         return true;
6505 }
6506
6507 /***************************************************************************
6508  Provide the canonical string representation of a boolean value given
6509  as a string. Return true on success, false if the string given does
6510  not correctly represent a boolean.
6511 ***************************************************************************/
6512
6513 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6514 {
6515         bool val;
6516
6517         if (!set_boolean(str, &val)) {
6518                 return false;
6519         }
6520
6521         *canon_str = get_boolean(val);
6522         return true;
6523 }
6524
6525 /***************************************************************************
6526 Find a service by name. Otherwise works like get_service.
6527 ***************************************************************************/
6528
6529 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
6530 {
6531         int iService = -1;
6532         char *canon_name;
6533         TDB_DATA data;
6534
6535         if (ServiceHash == NULL) {
6536                 return -1;
6537         }
6538
6539         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
6540
6541         data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
6542
6543         if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
6544                 iService = *(int *)data.dptr;
6545         }
6546
6547         TALLOC_FREE(canon_name);
6548
6549         if ((iService != -1) && (LP_SNUM_OK(iService))
6550             && (pserviceDest != NULL)) {
6551                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6552         }
6553
6554         return (iService);
6555 }
6556
6557 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
6558 struct loadparm_service *lp_service(const char *pszServiceName)
6559 {
6560         int iService = getservicebyname(pszServiceName, NULL);
6561         if (iService == -1 || !LP_SNUM_OK(iService)) {
6562                 return NULL;
6563         }
6564         return ServicePtrs[iService];
6565 }
6566
6567
6568 /***************************************************************************
6569  Copy a service structure to another.
6570  If pcopymapDest is NULL then copy all fields
6571 ***************************************************************************/
6572
6573 /**
6574  * Add a parametric option to a param_opt_struct,
6575  * replacing old value, if already present.
6576  */
6577 static void set_param_opt(struct param_opt_struct **opt_list,
6578                           const char *opt_name,
6579                           const char *opt_value,
6580                           unsigned flags)
6581 {
6582         struct param_opt_struct *new_opt, *opt;
6583         bool not_added;
6584
6585         if (opt_list == NULL) {
6586                 return;
6587         }
6588
6589         opt = *opt_list;
6590         not_added = true;
6591
6592         /* Traverse destination */
6593         while (opt) {
6594                 /* If we already have same option, override it */
6595                 if (strwicmp(opt->key, opt_name) == 0) {
6596                         if ((opt->flags & FLAG_CMDLINE) &&
6597                             !(flags & FLAG_CMDLINE)) {
6598                                 /* it's been marked as not to be
6599                                    overridden */
6600                                 return;
6601                         }
6602                         string_free(&opt->value);
6603                         TALLOC_FREE(opt->list);
6604                         opt->value = SMB_STRDUP(opt_value);
6605                         opt->flags = flags;
6606                         not_added = false;
6607                         break;
6608                 }
6609                 opt = opt->next;
6610         }
6611         if (not_added) {
6612             new_opt = SMB_XMALLOC_P(struct param_opt_struct);
6613             new_opt->key = SMB_STRDUP(opt_name);
6614             new_opt->value = SMB_STRDUP(opt_value);
6615             new_opt->list = NULL;
6616             new_opt->flags = flags;
6617             DLIST_ADD(*opt_list, new_opt);
6618         }
6619 }
6620
6621 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
6622                          struct bitmap *pcopymapDest)
6623 {
6624         int i;
6625         bool bcopyall = (pcopymapDest == NULL);
6626         struct param_opt_struct *data;
6627
6628         for (i = 0; parm_table[i].label; i++)
6629                 if (parm_table[i].p_class == P_LOCAL &&
6630                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6631                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
6632                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
6633
6634                         switch (parm_table[i].type) {
6635                                 case P_BOOL:
6636                                 case P_BOOLREV:
6637                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6638                                         break;
6639
6640                                 case P_INTEGER:
6641                                 case P_ENUM:
6642                                 case P_OCTAL:
6643                                         *(int *)dest_ptr = *(int *)src_ptr;
6644                                         break;
6645
6646                                 case P_CHAR:
6647                                         *(char *)dest_ptr = *(char *)src_ptr;
6648                                         break;
6649
6650                                 case P_STRING:
6651                                         string_set((char **)dest_ptr,
6652                                                    *(char **)src_ptr);
6653                                         break;
6654
6655                                 case P_USTRING:
6656                                 {
6657                                         char *upper_string = strupper_talloc(talloc_tos(), 
6658                                                                              *(char **)src_ptr);
6659                                         string_set((char **)dest_ptr,
6660                                                    upper_string);
6661                                         TALLOC_FREE(upper_string);
6662                                         break;
6663                                 }
6664                                 case P_LIST:
6665                                         TALLOC_FREE(*((char ***)dest_ptr));
6666                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6667                                                       *(const char ***)src_ptr);
6668                                         break;
6669                                 default:
6670                                         break;
6671                         }
6672                 }
6673
6674         if (bcopyall) {
6675                 init_copymap(pserviceDest);
6676                 if (pserviceSource->copymap)
6677                         bitmap_copy(pserviceDest->copymap,
6678                                     pserviceSource->copymap);
6679         }
6680
6681         data = pserviceSource->param_opt;
6682         while (data) {
6683                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->flags);
6684                 data = data->next;
6685         }
6686 }
6687
6688 /***************************************************************************
6689 Check a service for consistency. Return false if the service is in any way
6690 incomplete or faulty, else true.
6691 ***************************************************************************/
6692
6693 bool service_ok(int iService)
6694 {
6695         bool bRetval;
6696
6697         bRetval = true;
6698         if (ServicePtrs[iService]->szService[0] == '\0') {
6699                 DEBUG(0, ("The following message indicates an internal error:\n"));
6700                 DEBUG(0, ("No service name in service entry.\n"));
6701                 bRetval = false;
6702         }
6703
6704         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6705         /* I can't see why you'd want a non-printable printer service...        */
6706         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6707                 if (!ServicePtrs[iService]->bPrint_ok) {
6708                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6709                                ServicePtrs[iService]->szService));
6710                         ServicePtrs[iService]->bPrint_ok = true;
6711                 }
6712                 /* [printers] service must also be non-browsable. */
6713                 if (ServicePtrs[iService]->bBrowseable)
6714                         ServicePtrs[iService]->bBrowseable = false;
6715         }
6716
6717         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6718             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6719             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6720             ) {
6721                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6722                         ServicePtrs[iService]->szService));
6723                 ServicePtrs[iService]->bAvailable = false;
6724         }
6725
6726         /* If a service is flagged unavailable, log the fact at level 1. */
6727         if (!ServicePtrs[iService]->bAvailable)
6728                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6729                           ServicePtrs[iService]->szService));
6730
6731         return (bRetval);
6732 }
6733
6734 static struct smbconf_ctx *lp_smbconf_ctx(void)
6735 {
6736         sbcErr err;
6737         static struct smbconf_ctx *conf_ctx = NULL;
6738
6739         if (conf_ctx == NULL) {
6740                 err = smbconf_init(NULL, &conf_ctx, "registry:");
6741                 if (!SBC_ERROR_IS_OK(err)) {
6742                         DEBUG(1, ("error initializing registry configuration: "
6743                                   "%s\n", sbcErrorString(err)));
6744                         conf_ctx = NULL;
6745                 }
6746         }
6747
6748         return conf_ctx;
6749 }
6750
6751 static bool process_smbconf_service(struct smbconf_service *service)
6752 {
6753         uint32_t count;
6754         bool ret;
6755
6756         if (service == NULL) {
6757                 return false;
6758         }
6759
6760         ret = do_section(service->name, NULL);
6761         if (ret != true) {
6762                 return false;
6763         }
6764         for (count = 0; count < service->num_params; count++) {
6765                 ret = do_parameter(service->param_names[count],
6766                                    service->param_values[count],
6767                                    NULL);
6768                 if (ret != true) {
6769                         return false;
6770                 }
6771         }
6772         if (iServiceIndex >= 0) {
6773                 return service_ok(iServiceIndex);
6774         }
6775         return true;
6776 }
6777
6778 /**
6779  * load a service from registry and activate it
6780  */
6781 bool process_registry_service(const char *service_name)
6782 {
6783         sbcErr err;
6784         struct smbconf_service *service = NULL;
6785         TALLOC_CTX *mem_ctx = talloc_stackframe();
6786         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6787         bool ret = false;
6788
6789         if (conf_ctx == NULL) {
6790                 goto done;
6791         }
6792
6793         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
6794
6795         if (!smbconf_share_exists(conf_ctx, service_name)) {
6796                 /*
6797                  * Registry does not contain data for this service (yet),
6798                  * but make sure lp_load doesn't return false.
6799                  */
6800                 ret = true;
6801                 goto done;
6802         }
6803
6804         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
6805         if (!SBC_ERROR_IS_OK(err)) {
6806                 goto done;
6807         }
6808
6809         ret = process_smbconf_service(service);
6810         if (!ret) {
6811                 goto done;
6812         }
6813
6814         /* store the csn */
6815         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6816
6817 done:
6818         TALLOC_FREE(mem_ctx);
6819         return ret;
6820 }
6821
6822 /*
6823  * process_registry_globals
6824  */
6825 static bool process_registry_globals(void)
6826 {
6827         bool ret;
6828
6829         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
6830
6831         ret = do_parameter("registry shares", "yes", NULL);
6832         if (!ret) {
6833                 return ret;
6834         }
6835
6836         return process_registry_service(GLOBAL_NAME);
6837 }
6838
6839 bool process_registry_shares(void)
6840 {
6841         sbcErr err;
6842         uint32_t count;
6843         struct smbconf_service **service = NULL;
6844         uint32_t num_shares = 0;
6845         TALLOC_CTX *mem_ctx = talloc_stackframe();
6846         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6847         bool ret = false;
6848
6849         if (conf_ctx == NULL) {
6850                 goto done;
6851         }
6852
6853         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6854         if (!SBC_ERROR_IS_OK(err)) {
6855                 goto done;
6856         }
6857
6858         ret = true;
6859
6860         for (count = 0; count < num_shares; count++) {
6861                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6862                         continue;
6863                 }
6864                 ret = process_smbconf_service(service[count]);
6865                 if (!ret) {
6866                         goto done;
6867                 }
6868         }
6869
6870         /* store the csn */
6871         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6872
6873 done:
6874         TALLOC_FREE(mem_ctx);
6875         return ret;
6876 }
6877
6878 #define MAX_INCLUDE_DEPTH 100
6879
6880 static uint8_t include_depth;
6881
6882 static struct file_lists {
6883         struct file_lists *next;
6884         char *name;
6885         char *subfname;
6886         time_t modtime;
6887 } *file_lists = NULL;
6888
6889 /*******************************************************************
6890  Keep a linked list of all config files so we know when one has changed 
6891  it's date and needs to be reloaded.
6892 ********************************************************************/
6893
6894 static void add_to_file_list(const char *fname, const char *subfname)
6895 {
6896         struct file_lists *f = file_lists;
6897
6898         while (f) {
6899                 if (f->name && !strcmp(f->name, fname))
6900                         break;
6901                 f = f->next;
6902         }
6903
6904         if (!f) {
6905                 f = SMB_MALLOC_P(struct file_lists);
6906                 if (!f)
6907                         return;
6908                 f->next = file_lists;
6909                 f->name = SMB_STRDUP(fname);
6910                 if (!f->name) {
6911                         SAFE_FREE(f);
6912                         return;
6913                 }
6914                 f->subfname = SMB_STRDUP(subfname);
6915                 if (!f->subfname) {
6916                         SAFE_FREE(f->name);
6917                         SAFE_FREE(f);
6918                         return;
6919                 }
6920                 file_lists = f;
6921                 f->modtime = file_modtime(subfname);
6922         } else {
6923                 time_t t = file_modtime(subfname);
6924                 if (t)
6925                         f->modtime = t;
6926         }
6927         return;
6928 }
6929
6930 /**
6931  * Free the file lists
6932  */
6933 static void free_file_list(void)
6934 {
6935         struct file_lists *f;
6936         struct file_lists *next;
6937
6938         f = file_lists;
6939         while( f ) {
6940                 next = f->next;
6941                 SAFE_FREE( f->name );
6942                 SAFE_FREE( f->subfname );
6943                 SAFE_FREE( f );
6944                 f = next;
6945         }
6946         file_lists = NULL;
6947 }
6948
6949
6950 /**
6951  * Utility function for outsiders to check if we're running on registry.
6952  */
6953 bool lp_config_backend_is_registry(void)
6954 {
6955         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6956 }
6957
6958 /**
6959  * Utility function to check if the config backend is FILE.
6960  */
6961 bool lp_config_backend_is_file(void)
6962 {
6963         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6964 }
6965
6966 /*******************************************************************
6967  Check if a config file has changed date.
6968 ********************************************************************/
6969
6970 bool lp_file_list_changed(void)
6971 {
6972         struct file_lists *f = file_lists;
6973
6974         DEBUG(6, ("lp_file_list_changed()\n"));
6975
6976         while (f) {
6977                 time_t mod_time;
6978
6979                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
6980                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6981
6982                         if (conf_ctx == NULL) {
6983                                 return false;
6984                         }
6985                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
6986                                             NULL))
6987                         {
6988                                 DEBUGADD(6, ("registry config changed\n"));
6989                                 return true;
6990                         }
6991                 } else {
6992                         char *n2 = NULL;
6993                         n2 = talloc_sub_basic(talloc_tos(),
6994                                               get_current_username(),
6995                                               current_user_info.domain,
6996                                               f->name);
6997                         if (!n2) {
6998                                 return false;
6999                         }
7000                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
7001                                      f->name, n2, ctime(&f->modtime)));
7002
7003                         mod_time = file_modtime(n2);
7004
7005                         if (mod_time &&
7006                             ((f->modtime != mod_time) ||
7007                              (f->subfname == NULL) ||
7008                              (strcmp(n2, f->subfname) != 0)))
7009                         {
7010                                 DEBUGADD(6,
7011                                          ("file %s modified: %s\n", n2,
7012                                           ctime(&mod_time)));
7013                                 f->modtime = mod_time;
7014                                 SAFE_FREE(f->subfname);
7015                                 f->subfname = SMB_STRDUP(n2);
7016                                 TALLOC_FREE(n2);
7017                                 return true;
7018                         }
7019                         TALLOC_FREE(n2);
7020                 }
7021                 f = f->next;
7022         }
7023         return (false);
7024 }
7025
7026
7027 /**
7028  * Initialize iconv conversion descriptors.
7029  *
7030  * This is called the first time it is needed, and also called again
7031  * every time the configuration is reloaded, because the charset or
7032  * codepage might have changed.
7033  **/
7034 static void init_iconv(void)
7035 {
7036         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
7037                                                       lp_unix_charset(),
7038                                                       true, global_iconv_handle);
7039 }
7040
7041 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7042 {
7043         if (strcmp(*ptr, pszParmValue) != 0) {
7044                 string_set(ptr, pszParmValue);
7045                 init_iconv();
7046         }
7047         return true;
7048 }
7049
7050 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7051 {
7052         bool is_utf8 = false;
7053         size_t len = strlen(pszParmValue);
7054
7055         if (len == 4 || len == 5) {
7056                 /* Don't use StrCaseCmp here as we don't want to
7057                    initialize iconv. */
7058                 if ((toupper_ascii(pszParmValue[0]) == 'U') &&
7059                     (toupper_ascii(pszParmValue[1]) == 'T') &&
7060                     (toupper_ascii(pszParmValue[2]) == 'F')) {
7061                         if (len == 4) {
7062                                 if (pszParmValue[3] == '8') {
7063                                         is_utf8 = true;
7064                                 }
7065                         } else {
7066                                 if (pszParmValue[3] == '-' &&
7067                                     pszParmValue[4] == '8') {
7068                                         is_utf8 = true;
7069                                 }
7070                         }
7071                 }
7072         }
7073
7074         if (strcmp(*ptr, pszParmValue) != 0) {
7075                 if (is_utf8) {
7076                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
7077                                 "be UTF8, using (default value) %s instead.\n",
7078                                 DEFAULT_DOS_CHARSET));
7079                         pszParmValue = DEFAULT_DOS_CHARSET;
7080                 }
7081                 string_set(ptr, pszParmValue);
7082                 init_iconv();
7083         }
7084         return true;
7085 }
7086
7087 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7088 {
7089         bool ret = true;
7090         char *realm = strupper_talloc(talloc_tos(), pszParmValue);
7091         char *dnsdomain = strlower_talloc(talloc_tos(), pszParmValue);
7092
7093         ret &= string_set(&Globals.szRealm, pszParmValue);
7094         ret &= string_set(&Globals.szRealmUpper, realm);
7095         ret &= string_set(&Globals.szDnsDomain, dnsdomain);
7096         TALLOC_FREE(realm);
7097         TALLOC_FREE(dnsdomain);
7098
7099         return ret;
7100 }
7101
7102 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7103 {
7104         TALLOC_FREE(Globals.szNetbiosAliases);
7105         Globals.szNetbiosAliases = str_list_make_v3(NULL, pszParmValue, NULL);
7106         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
7107 }
7108
7109 /***************************************************************************
7110  Handle the include operation.
7111 ***************************************************************************/
7112 static bool bAllowIncludeRegistry = true;
7113
7114 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7115 {
7116         char *fname;
7117
7118         if (include_depth >= MAX_INCLUDE_DEPTH) {
7119                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
7120                           include_depth));
7121                 return false;
7122         }
7123
7124         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
7125                 if (!bAllowIncludeRegistry) {
7126                         return true;
7127                 }
7128                 if (bInGlobalSection) {
7129                         bool ret;
7130                         include_depth++;
7131                         ret = process_registry_globals();
7132                         include_depth--;
7133                         return ret;
7134                 } else {
7135                         DEBUG(1, ("\"include = registry\" only effective "
7136                                   "in %s section\n", GLOBAL_NAME));
7137                         return false;
7138                 }
7139         }
7140
7141         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
7142                                  current_user_info.domain,
7143                                  pszParmValue);
7144
7145         add_to_file_list(pszParmValue, fname);
7146
7147         string_set(ptr, fname);
7148
7149         if (file_exist(fname)) {
7150                 bool ret;
7151                 include_depth++;
7152                 ret = pm_process(fname, do_section, do_parameter, NULL);
7153                 include_depth--;
7154                 TALLOC_FREE(fname);
7155                 return ret;
7156         }
7157
7158         DEBUG(2, ("Can't find include file %s\n", fname));
7159         TALLOC_FREE(fname);
7160         return true;
7161 }
7162
7163 /***************************************************************************
7164  Handle the interpretation of the copy parameter.
7165 ***************************************************************************/
7166
7167 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7168 {
7169         bool bRetval;
7170         int iTemp;
7171         struct loadparm_service serviceTemp;
7172
7173         string_set(ptr, pszParmValue);
7174
7175         init_service(&serviceTemp);
7176
7177         bRetval = false;
7178
7179         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
7180
7181         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
7182                 if (iTemp == iServiceIndex) {
7183                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
7184                 } else {
7185                         copy_service(ServicePtrs[iServiceIndex],
7186                                      &serviceTemp,
7187                                      ServicePtrs[iServiceIndex]->copymap);
7188                         bRetval = true;
7189                 }
7190         } else {
7191                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
7192                 bRetval = false;
7193         }
7194
7195         free_service(&serviceTemp);
7196         return (bRetval);
7197 }
7198
7199 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7200 {
7201         Globals.ldap_debug_level = lp_int(pszParmValue);
7202         init_ldap_debugging();
7203         return true;
7204 }
7205
7206 /***************************************************************************
7207  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
7208  parameters is:
7209
7210  [global]
7211
7212         idmap uid = 1000-1999
7213         idmap gid = 700-899
7214
7215  We only do simple parsing checks here.  The strings are parsed into useful
7216  structures in the idmap daemon code.
7217
7218 ***************************************************************************/
7219
7220 /* Some lp_ routines to return idmap [ug]id information */
7221
7222 static uid_t idmap_uid_low, idmap_uid_high;
7223 static gid_t idmap_gid_low, idmap_gid_high;
7224
7225 bool lp_idmap_uid(uid_t *low, uid_t *high)
7226 {
7227         if (idmap_uid_low == 0 || idmap_uid_high == 0)
7228                 return false;
7229
7230         if (low)
7231                 *low = idmap_uid_low;
7232
7233         if (high)
7234                 *high = idmap_uid_high;
7235
7236         return true;
7237 }
7238
7239 bool lp_idmap_gid(gid_t *low, gid_t *high)
7240 {
7241         if (idmap_gid_low == 0 || idmap_gid_high == 0)
7242                 return false;
7243
7244         if (low)
7245                 *low = idmap_gid_low;
7246
7247         if (high)
7248                 *high = idmap_gid_high;
7249
7250         return true;
7251 }
7252
7253 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7254 {
7255         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
7256
7257         return true;
7258 }
7259
7260 /* Do some simple checks on "idmap [ug]id" parameter values */
7261
7262 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7263 {
7264         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7265
7266         return true;
7267 }
7268
7269 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7270 {
7271         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7272
7273         return true;
7274 }
7275
7276 /***************************************************************************
7277  Handle the DEBUG level list.
7278 ***************************************************************************/
7279
7280 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
7281 {
7282         string_set(ptr, pszParmValueIn);
7283         return debug_parse_levels(pszParmValueIn);
7284 }
7285
7286 /***************************************************************************
7287  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
7288 ***************************************************************************/
7289
7290 static const char *append_ldap_suffix( const char *str )
7291 {
7292         const char *suffix_string;
7293
7294
7295         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
7296                                         Globals.szLdapSuffix );
7297         if ( !suffix_string ) {
7298                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
7299                 return "";
7300         }
7301
7302         return suffix_string;
7303 }
7304
7305 const char *lp_ldap_machine_suffix(void)
7306 {
7307         if (Globals.szLdapMachineSuffix[0])
7308                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
7309
7310         return lp_string(Globals.szLdapSuffix);
7311 }
7312
7313 const char *lp_ldap_user_suffix(void)
7314 {
7315         if (Globals.szLdapUserSuffix[0])
7316                 return append_ldap_suffix(Globals.szLdapUserSuffix);
7317
7318         return lp_string(Globals.szLdapSuffix);
7319 }
7320
7321 const char *lp_ldap_group_suffix(void)
7322 {
7323         if (Globals.szLdapGroupSuffix[0])
7324                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
7325
7326         return lp_string(Globals.szLdapSuffix);
7327 }
7328
7329 const char *lp_ldap_idmap_suffix(void)
7330 {
7331         if (Globals.szLdapIdmapSuffix[0])
7332                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
7333
7334         return lp_string(Globals.szLdapSuffix);
7335 }
7336
7337 /****************************************************************************
7338  set the value for a P_ENUM
7339  ***************************************************************************/
7340
7341 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
7342                               int *ptr )
7343 {
7344         int i;
7345
7346         for (i = 0; parm->enum_list[i].name; i++) {
7347                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
7348                         *ptr = parm->enum_list[i].value;
7349                         return;
7350                 }
7351         }
7352         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
7353                   pszParmValue, parm->label));
7354 }
7355
7356 /***************************************************************************
7357 ***************************************************************************/
7358
7359 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7360 {
7361         static int parm_num = -1;
7362         struct loadparm_service *s;
7363
7364         if ( parm_num == -1 )
7365                 parm_num = map_parameter( "printing" );
7366
7367         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
7368
7369         if ( snum < 0 )
7370                 s = &sDefault;
7371         else
7372                 s = ServicePtrs[snum];
7373
7374         init_printer_values( s );
7375
7376         return true;
7377 }
7378
7379
7380 /***************************************************************************
7381  Initialise a copymap.
7382 ***************************************************************************/
7383
7384 static void init_copymap(struct loadparm_service *pservice)
7385 {
7386         int i;
7387
7388         TALLOC_FREE(pservice->copymap);
7389
7390         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
7391         if (!pservice->copymap)
7392                 DEBUG(0,
7393                       ("Couldn't allocate copymap!! (size %d)\n",
7394                        (int)NUMPARAMETERS));
7395         else
7396                 for (i = 0; i < NUMPARAMETERS; i++)
7397                         bitmap_set(pservice->copymap, i);
7398 }
7399
7400 /**
7401   return the parameter pointer for a parameter
7402 */
7403 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
7404 {
7405         if (service == NULL) {
7406                 if (parm->p_class == P_LOCAL)
7407                         return (void *)(((char *)&sDefault)+parm->offset);
7408                 else if (parm->p_class == P_GLOBAL)
7409                         return (void *)(((char *)&Globals)+parm->offset);
7410                 else return NULL;
7411         } else {
7412                 return (void *)(((char *)service) + parm->offset);
7413         }
7414 }
7415
7416 /***************************************************************************
7417  Return the local pointer to a parameter given the service number and parameter
7418 ***************************************************************************/
7419
7420 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
7421 {
7422         return lp_parm_ptr(ServicePtrs[snum], parm);
7423 }
7424
7425 /***************************************************************************
7426  Process a parameter for a particular service number. If snum < 0
7427  then assume we are in the globals.
7428 ***************************************************************************/
7429
7430 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7431 {
7432         int parmnum, i;
7433         void *parm_ptr = NULL;  /* where we are going to store the result */
7434         struct param_opt_struct **opt_list;
7435
7436         parmnum = map_parameter(pszParmName);
7437
7438         if (parmnum < 0) {
7439                 if (strchr(pszParmName, ':') == NULL) {
7440                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7441                                   pszParmName));
7442                         return (true);
7443                 }
7444
7445                 /*
7446                  * We've got a parametric option
7447                  */
7448
7449                 opt_list = (snum < 0)
7450                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7451                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
7452
7453                 return (true);
7454         }
7455
7456         /* if it's already been set by the command line, then we don't
7457            override here */
7458         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
7459                 return true;
7460         }
7461
7462         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7463                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7464                           pszParmName));
7465         }
7466
7467         /* we might point at a service, the default service or a global */
7468         if (snum < 0) {
7469                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
7470         } else {
7471                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7472                         DEBUG(0,
7473                               ("Global parameter %s found in service section!\n",
7474                                pszParmName));
7475                         return (true);
7476                 }
7477                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
7478         }
7479
7480         if (snum >= 0) {
7481                 if (!ServicePtrs[snum]->copymap)
7482                         init_copymap(ServicePtrs[snum]);
7483
7484                 /* this handles the aliases - set the copymap for other entries with
7485                    the same data pointer */
7486                 for (i = 0; parm_table[i].label; i++)
7487                         if (parm_table[i].offset == parm_table[parmnum].offset)
7488                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7489         }
7490
7491         /* if it is a special case then go ahead */
7492         if (parm_table[parmnum].special) {
7493                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
7494                                                    (char **)parm_ptr);
7495         }
7496
7497         /* now switch on the type of variable it is */
7498         switch (parm_table[parmnum].type)
7499         {
7500                 case P_BOOL:
7501                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7502                         break;
7503
7504                 case P_BOOLREV:
7505                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7506                         break;
7507
7508                 case P_INTEGER:
7509                         *(int *)parm_ptr = lp_int(pszParmValue);
7510                         break;
7511
7512                 case P_CHAR:
7513                         *(char *)parm_ptr = *pszParmValue;
7514                         break;
7515
7516                 case P_OCTAL:
7517                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7518                         if ( i != 1 ) {
7519                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7520                         }
7521                         break;
7522
7523                 case P_LIST:
7524                         TALLOC_FREE(*((char ***)parm_ptr));
7525                         *(char ***)parm_ptr = str_list_make_v3(
7526                                 NULL, pszParmValue, NULL);
7527                         break;
7528
7529                 case P_STRING:
7530                         string_set((char **)parm_ptr, pszParmValue);
7531                         break;
7532
7533                 case P_USTRING:
7534                 {
7535                         char *upper_string = strupper_talloc(talloc_tos(), 
7536                                                              pszParmValue);
7537                         string_set((char **)parm_ptr, upper_string);
7538                         TALLOC_FREE(upper_string);
7539                         break;
7540                 }
7541                 case P_ENUM:
7542                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7543                         break;
7544                 case P_SEP:
7545                         break;
7546         }
7547
7548         return (true);
7549 }
7550
7551 /***************************************************************************
7552 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
7553 FLAG_CMDLINE won't be overridden by loads from smb.conf.
7554 ***************************************************************************/
7555
7556 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
7557 {
7558         int parmnum, i;
7559         parmnum = map_parameter(pszParmName);
7560         if (parmnum >= 0) {
7561                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
7562                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
7563                         return false;
7564                 }
7565                 parm_table[parmnum].flags |= FLAG_CMDLINE;
7566
7567                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
7568                  * be grouped in the table, so we don't have to search the
7569                  * whole table */
7570                 for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
7571                         parm_table[i].flags |= FLAG_CMDLINE;
7572                 }
7573                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset;i++) {
7574                         parm_table[i].flags |= FLAG_CMDLINE;
7575                 }
7576
7577                 if (store_values) {
7578                         store_lp_set_cmdline(pszParmName, pszParmValue);
7579                 }
7580                 return true;
7581         }
7582
7583         /* it might be parametric */
7584         if (strchr(pszParmName, ':') != NULL) {
7585                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
7586                 if (store_values) {
7587                         store_lp_set_cmdline(pszParmName, pszParmValue);
7588                 }
7589                 return true;
7590         }
7591
7592         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
7593         return true;
7594 }
7595
7596 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
7597 {
7598         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
7599 }
7600
7601 /***************************************************************************
7602  Process a parameter.
7603 ***************************************************************************/
7604
7605 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7606                          void *userdata)
7607 {
7608         if (!bInGlobalSection && bGlobalOnly)
7609                 return (true);
7610
7611         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7612
7613         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7614                                 pszParmName, pszParmValue));
7615 }
7616
7617 /*
7618   set a option from the commandline in 'a=b' format. Use to support --option
7619 */
7620 bool lp_set_option(const char *option)
7621 {
7622         char *p, *s;
7623         bool ret;
7624
7625         s = talloc_strdup(NULL, option);
7626         if (!s) {
7627                 return false;
7628         }
7629
7630         p = strchr(s, '=');
7631         if (!p) {
7632                 talloc_free(s);
7633                 return false;
7634         }
7635
7636         *p = 0;
7637
7638         /* skip white spaces after the = sign */
7639         do {
7640                 p++;
7641         } while (*p == ' ');
7642
7643         ret = lp_set_cmdline(s, p);
7644         talloc_free(s);
7645         return ret;
7646 }
7647
7648 /**************************************************************************
7649  Print a parameter of the specified type.
7650 ***************************************************************************/
7651
7652 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7653 {
7654         int i;
7655         switch (p->type)
7656         {
7657                 case P_ENUM:
7658                         for (i = 0; p->enum_list[i].name; i++) {
7659                                 if (*(int *)ptr == p->enum_list[i].value) {
7660                                         fprintf(f, "%s",
7661                                                 p->enum_list[i].name);
7662                                         break;
7663                                 }
7664                         }
7665                         break;
7666
7667                 case P_BOOL:
7668                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7669                         break;
7670
7671                 case P_BOOLREV:
7672                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7673                         break;
7674
7675                 case P_INTEGER:
7676                         fprintf(f, "%d", *(int *)ptr);
7677                         break;
7678
7679                 case P_CHAR:
7680                         fprintf(f, "%c", *(char *)ptr);
7681                         break;
7682
7683                 case P_OCTAL: {
7684                         char *o = octal_string(*(int *)ptr);
7685                         fprintf(f, "%s", o);
7686                         TALLOC_FREE(o);
7687                         break;
7688                 }
7689
7690                 case P_LIST:
7691                         if ((char ***)ptr && *(char ***)ptr) {
7692                                 char **list = *(char ***)ptr;
7693                                 for (; *list; list++) {
7694                                         /* surround strings with whitespace in double quotes */
7695                                         if ( strchr_m( *list, ' ' ) )
7696                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
7697                                         else
7698                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
7699                                 }
7700                         }
7701                         break;
7702
7703                 case P_STRING:
7704                 case P_USTRING:
7705                         if (*(char **)ptr) {
7706                                 fprintf(f, "%s", *(char **)ptr);
7707                         }
7708                         break;
7709                 case P_SEP:
7710                         break;
7711         }
7712 }
7713
7714 /***************************************************************************
7715  Check if two parameters are equal.
7716 ***************************************************************************/
7717
7718 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7719 {
7720         switch (type) {
7721                 case P_BOOL:
7722                 case P_BOOLREV:
7723                         return (*((bool *)ptr1) == *((bool *)ptr2));
7724
7725                 case P_INTEGER:
7726                 case P_ENUM:
7727                 case P_OCTAL:
7728                         return (*((int *)ptr1) == *((int *)ptr2));
7729
7730                 case P_CHAR:
7731                         return (*((char *)ptr1) == *((char *)ptr2));
7732
7733                 case P_LIST:
7734                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7735
7736                 case P_STRING:
7737                 case P_USTRING:
7738                 {
7739                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7740                         if (p1 && !*p1)
7741                                 p1 = NULL;
7742                         if (p2 && !*p2)
7743                                 p2 = NULL;
7744                         return (p1 == p2 || strequal(p1, p2));
7745                 }
7746                 case P_SEP:
7747                         break;
7748         }
7749         return (false);
7750 }
7751
7752 /***************************************************************************
7753  Initialize any local varients in the sDefault table.
7754 ***************************************************************************/
7755
7756 void init_locals(void)
7757 {
7758         /* None as yet. */
7759 }
7760
7761 /***************************************************************************
7762  Process a new section (service). At this stage all sections are services.
7763  Later we'll have special sections that permit server parameters to be set.
7764  Returns true on success, false on failure.
7765 ***************************************************************************/
7766
7767 static bool do_section(const char *pszSectionName, void *userdata)
7768 {
7769         bool bRetval;
7770         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7771                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7772         bRetval = false;
7773
7774         /* if we were in a global section then do the local inits */
7775         if (bInGlobalSection && !isglobal)
7776                 init_locals();
7777
7778         /* if we've just struck a global section, note the fact. */
7779         bInGlobalSection = isglobal;
7780
7781         /* check for multiple global sections */
7782         if (bInGlobalSection) {
7783                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7784                 return (true);
7785         }
7786
7787         if (!bInGlobalSection && bGlobalOnly)
7788                 return (true);
7789
7790         /* if we have a current service, tidy it up before moving on */
7791         bRetval = true;
7792
7793         if (iServiceIndex >= 0)
7794                 bRetval = service_ok(iServiceIndex);
7795
7796         /* if all is still well, move to the next record in the services array */
7797         if (bRetval) {
7798                 /* We put this here to avoid an odd message order if messages are */
7799                 /* issued by the post-processing of a previous section. */
7800                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7801
7802                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
7803                     < 0) {
7804                         DEBUG(0, ("Failed to add a new service\n"));
7805                         return (false);
7806                 }
7807                 /* Clean all parametric options for service */
7808                 /* They will be added during parsing again */
7809                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
7810         }
7811
7812         return (bRetval);
7813 }
7814
7815
7816 /***************************************************************************
7817  Determine if a partcular base parameter is currentl set to the default value.
7818 ***************************************************************************/
7819
7820 static bool is_default(int i)
7821 {
7822         if (!defaults_saved)
7823                 return false;
7824         switch (parm_table[i].type) {
7825                 case P_LIST:
7826                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
7827                                               *(const char ***)lp_parm_ptr(NULL, 
7828                                                                            &parm_table[i]));
7829                 case P_STRING:
7830                 case P_USTRING:
7831                         return strequal(parm_table[i].def.svalue,
7832                                         *(char **)lp_parm_ptr(NULL, 
7833                                                               &parm_table[i]));
7834                 case P_BOOL:
7835                 case P_BOOLREV:
7836                         return parm_table[i].def.bvalue ==
7837                                 *(bool *)lp_parm_ptr(NULL, 
7838                                                      &parm_table[i]);
7839                 case P_CHAR:
7840                         return parm_table[i].def.cvalue ==
7841                                 *(char *)lp_parm_ptr(NULL, 
7842                                                      &parm_table[i]);
7843                 case P_INTEGER:
7844                 case P_OCTAL:
7845                 case P_ENUM:
7846                         return parm_table[i].def.ivalue ==
7847                                 *(int *)lp_parm_ptr(NULL, 
7848                                                     &parm_table[i]);
7849                 case P_SEP:
7850                         break;
7851         }
7852         return false;
7853 }
7854
7855 /***************************************************************************
7856 Display the contents of the global structure.
7857 ***************************************************************************/
7858
7859 static void dump_globals(FILE *f)
7860 {
7861         int i;
7862         struct param_opt_struct *data;
7863
7864         fprintf(f, "[global]\n");
7865
7866         for (i = 0; parm_table[i].label; i++)
7867                 if (parm_table[i].p_class == P_GLOBAL &&
7868                     !(parm_table[i].flags & FLAG_META) &&
7869                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
7870                         if (defaults_saved && is_default(i))
7871                                 continue;
7872                         fprintf(f, "\t%s = ", parm_table[i].label);
7873                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
7874                                                                     &parm_table[i]),
7875                                         f);
7876                         fprintf(f, "\n");
7877         }
7878         if (Globals.param_opt != NULL) {
7879                 data = Globals.param_opt;
7880                 while(data) {
7881                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7882                         data = data->next;
7883                 }
7884         }
7885
7886 }
7887
7888 /***************************************************************************
7889  Return true if a local parameter is currently set to the global default.
7890 ***************************************************************************/
7891
7892 bool lp_is_default(int snum, struct parm_struct *parm)
7893 {
7894         return equal_parameter(parm->type,
7895                                lp_parm_ptr(ServicePtrs[snum], parm),
7896                                lp_parm_ptr(NULL, parm));
7897 }
7898
7899 /***************************************************************************
7900  Display the contents of a single services record.
7901 ***************************************************************************/
7902
7903 static void dump_a_service(struct loadparm_service *pService, FILE * f)
7904 {
7905         int i;
7906         struct param_opt_struct *data;
7907
7908         if (pService != &sDefault)
7909                 fprintf(f, "[%s]\n", pService->szService);
7910
7911         for (i = 0; parm_table[i].label; i++) {
7912
7913                 if (parm_table[i].p_class == P_LOCAL &&
7914                     !(parm_table[i].flags & FLAG_META) &&
7915                     (*parm_table[i].label != '-') &&
7916                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7917                 {
7918                         if (pService == &sDefault) {
7919                                 if (defaults_saved && is_default(i))
7920                                         continue;
7921                         } else {
7922                                 if (equal_parameter(parm_table[i].type,
7923                                                     lp_parm_ptr(pService, &parm_table[i]),
7924                                                     lp_parm_ptr(NULL, &parm_table[i])))
7925                                         continue;
7926                         }
7927
7928                         fprintf(f, "\t%s = ", parm_table[i].label);
7929                         print_parameter(&parm_table[i],
7930                                         lp_parm_ptr(pService, &parm_table[i]),
7931                                         f);
7932                         fprintf(f, "\n");
7933                 }
7934         }
7935
7936                 if (pService->param_opt != NULL) {
7937                         data = pService->param_opt;
7938                         while(data) {
7939                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7940                                 data = data->next;
7941                         }
7942                 }
7943 }
7944
7945 /***************************************************************************
7946  Display the contents of a parameter of a single services record.
7947 ***************************************************************************/
7948
7949 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7950 {
7951         int i;
7952         bool result = false;
7953         parm_class p_class;
7954         unsigned flag = 0;
7955         fstring local_parm_name;
7956         char *parm_opt;
7957         const char *parm_opt_value;
7958
7959         /* check for parametrical option */
7960         fstrcpy( local_parm_name, parm_name);
7961         parm_opt = strchr( local_parm_name, ':');
7962
7963         if (parm_opt) {
7964                 *parm_opt = '\0';
7965                 parm_opt++;
7966                 if (strlen(parm_opt)) {
7967                         parm_opt_value = lp_parm_const_string( snum,
7968                                 local_parm_name, parm_opt, NULL);
7969                         if (parm_opt_value) {
7970                                 printf( "%s\n", parm_opt_value);
7971                                 result = true;
7972                         }
7973                 }
7974                 return result;
7975         }
7976
7977         /* check for a key and print the value */
7978         if (isGlobal) {
7979                 p_class = P_GLOBAL;
7980                 flag = FLAG_GLOBAL;
7981         } else
7982                 p_class = P_LOCAL;
7983
7984         for (i = 0; parm_table[i].label; i++) {
7985                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7986                     !(parm_table[i].flags & FLAG_META) &&
7987                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7988                     (*parm_table[i].label != '-') &&
7989                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7990                 {
7991                         void *ptr;
7992
7993                         if (isGlobal) {
7994                                 ptr = lp_parm_ptr(NULL, 
7995                                                   &parm_table[i]);
7996                         } else {
7997                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
7998                                                   &parm_table[i]);
7999                         }
8000
8001                         print_parameter(&parm_table[i],
8002                                         ptr, f);
8003                         fprintf(f, "\n");
8004                         result = true;
8005                         break;
8006                 }
8007         }
8008
8009         return result;
8010 }
8011
8012 /***************************************************************************
8013  Return info about the requested parameter (given as a string).
8014  Return NULL when the string is not a valid parameter name.
8015 ***************************************************************************/
8016
8017 struct parm_struct *lp_get_parameter(const char *param_name)
8018 {
8019         int num = map_parameter(param_name);
8020
8021         if (num < 0) {
8022                 return NULL;
8023         }
8024
8025         return &parm_table[num];
8026 }
8027
8028 /***************************************************************************
8029  Return info about the next parameter in a service.
8030  snum==GLOBAL_SECTION_SNUM gives the globals.
8031  Return NULL when out of parameters.
8032 ***************************************************************************/
8033
8034 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
8035 {
8036         if (snum < 0) {
8037                 /* do the globals */
8038                 for (; parm_table[*i].label; (*i)++) {
8039                         if (parm_table[*i].p_class == P_SEPARATOR)
8040                                 return &parm_table[(*i)++];
8041
8042                         if ((*parm_table[*i].label == '-'))
8043                                 continue;
8044
8045                         if ((*i) > 0
8046                             && (parm_table[*i].offset ==
8047                                 parm_table[(*i) - 1].offset))
8048                                 continue;
8049
8050                         if (is_default(*i) && !allparameters)
8051                                 continue;
8052
8053                         return &parm_table[(*i)++];
8054                 }
8055         } else {
8056                 struct loadparm_service *pService = ServicePtrs[snum];
8057
8058                 for (; parm_table[*i].label; (*i)++) {
8059                         if (parm_table[*i].p_class == P_SEPARATOR)
8060                                 return &parm_table[(*i)++];
8061
8062                         if (parm_table[*i].p_class == P_LOCAL &&
8063                             (*parm_table[*i].label != '-') &&
8064                             ((*i) == 0 ||
8065                              (parm_table[*i].offset !=
8066                               parm_table[(*i) - 1].offset)))
8067                         {
8068                                 if (allparameters ||
8069                                     !equal_parameter(parm_table[*i].type,
8070                                                      lp_parm_ptr(pService, 
8071                                                                  &parm_table[*i]),
8072                                                      lp_parm_ptr(NULL, 
8073                                                                  &parm_table[*i])))
8074                                 {
8075                                         return &parm_table[(*i)++];
8076                                 }
8077                         }
8078                 }
8079         }
8080
8081         return NULL;
8082 }
8083
8084
8085 #if 0
8086 /***************************************************************************
8087  Display the contents of a single copy structure.
8088 ***************************************************************************/
8089 static void dump_copy_map(bool *pcopymap)
8090 {
8091         int i;
8092         if (!pcopymap)
8093                 return;
8094
8095         printf("\n\tNon-Copied parameters:\n");
8096
8097         for (i = 0; parm_table[i].label; i++)
8098                 if (parm_table[i].p_class == P_LOCAL &&
8099                     parm_table[i].ptr && !pcopymap[i] &&
8100                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
8101                 {
8102                         printf("\t\t%s\n", parm_table[i].label);
8103                 }
8104 }
8105 #endif
8106
8107 /***************************************************************************
8108  Return TRUE if the passed service number is within range.
8109 ***************************************************************************/
8110
8111 bool lp_snum_ok(int iService)
8112 {
8113         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
8114 }
8115
8116 /***************************************************************************
8117  Auto-load some home services.
8118 ***************************************************************************/
8119
8120 static void lp_add_auto_services(char *str)
8121 {
8122         char *s;
8123         char *p;
8124         int homes;
8125         char *saveptr;
8126
8127         if (!str)
8128                 return;
8129
8130         s = SMB_STRDUP(str);
8131         if (!s)
8132                 return;
8133
8134         homes = lp_servicenumber(HOMES_NAME);
8135
8136         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
8137              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
8138                 char *home;
8139
8140                 if (lp_servicenumber(p) >= 0)
8141                         continue;
8142
8143                 home = get_user_home_dir(talloc_tos(), p);
8144
8145                 if (home && home[0] && homes >= 0)
8146                         lp_add_home(p, homes, p, home);
8147
8148                 TALLOC_FREE(home);
8149         }
8150         SAFE_FREE(s);
8151 }
8152
8153 /***************************************************************************
8154  Auto-load one printer.
8155 ***************************************************************************/
8156
8157 void lp_add_one_printer(const char *name, const char *comment,
8158                         const char *location, void *pdata)
8159 {
8160         int printers = lp_servicenumber(PRINTERS_NAME);
8161         int i;
8162
8163         if (lp_servicenumber(name) < 0) {
8164                 lp_add_printer(name, printers);
8165                 if ((i = lp_servicenumber(name)) >= 0) {
8166                         string_set(&ServicePtrs[i]->comment, comment);
8167                         ServicePtrs[i]->autoloaded = true;
8168                 }
8169         }
8170 }
8171
8172 /***************************************************************************
8173  Have we loaded a services file yet?
8174 ***************************************************************************/
8175
8176 bool lp_loaded(void)
8177 {
8178         return (bLoaded);
8179 }
8180
8181 /***************************************************************************
8182  Unload unused services.
8183 ***************************************************************************/
8184
8185 void lp_killunused(struct smbd_server_connection *sconn,
8186                    bool (*snumused) (struct smbd_server_connection *, int))
8187 {
8188         int i;
8189         for (i = 0; i < iNumServices; i++) {
8190                 if (!VALID(i))
8191                         continue;
8192
8193                 /* don't kill autoloaded or usershare services */
8194                 if ( ServicePtrs[i]->autoloaded ||
8195                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
8196                         continue;
8197                 }
8198
8199                 if (!snumused || !snumused(sconn, i)) {
8200                         free_service_byindex(i);
8201                 }
8202         }
8203 }
8204
8205 /**
8206  * Kill all except autoloaded and usershare services - convenience wrapper
8207  */
8208 void lp_kill_all_services(void)
8209 {
8210         lp_killunused(NULL, NULL);
8211 }
8212
8213 /***************************************************************************
8214  Unload a service.
8215 ***************************************************************************/
8216
8217 void lp_killservice(int iServiceIn)
8218 {
8219         if (VALID(iServiceIn)) {
8220                 free_service_byindex(iServiceIn);
8221         }
8222 }
8223
8224 /***************************************************************************
8225  Save the curent values of all global and sDefault parameters into the 
8226  defaults union. This allows swat and testparm to show only the
8227  changed (ie. non-default) parameters.
8228 ***************************************************************************/
8229
8230 static void lp_save_defaults(void)
8231 {
8232         int i;
8233         for (i = 0; parm_table[i].label; i++) {
8234                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset)
8235                         continue;
8236                 switch (parm_table[i].type) {
8237                         case P_LIST:
8238                                 parm_table[i].def.lvalue = str_list_copy(
8239                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
8240                                 break;
8241                         case P_STRING:
8242                         case P_USTRING:
8243                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
8244                                 break;
8245                         case P_BOOL:
8246                         case P_BOOLREV:
8247                                 parm_table[i].def.bvalue =
8248                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
8249                                 break;
8250                         case P_CHAR:
8251                                 parm_table[i].def.cvalue =
8252                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
8253                                 break;
8254                         case P_INTEGER:
8255                         case P_OCTAL:
8256                         case P_ENUM:
8257                                 parm_table[i].def.ivalue =
8258                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
8259                                 break;
8260                         case P_SEP:
8261                                 break;
8262                 }
8263         }
8264         defaults_saved = true;
8265 }
8266
8267 /***********************************************************
8268  If we should send plaintext/LANMAN passwords in the clinet
8269 ************************************************************/
8270
8271 static void set_allowed_client_auth(void)
8272 {
8273         if (Globals.bClientNTLMv2Auth) {
8274                 Globals.bClientLanManAuth = false;
8275         }
8276         if (!Globals.bClientLanManAuth) {
8277                 Globals.bClientPlaintextAuth = false;
8278         }
8279 }
8280
8281 /***************************************************************************
8282  JRA.
8283  The following code allows smbd to read a user defined share file.
8284  Yes, this is my intent. Yes, I'm comfortable with that...
8285
8286  THE FOLLOWING IS SECURITY CRITICAL CODE.
8287
8288  It washes your clothes, it cleans your house, it guards you while you sleep...
8289  Do not f%^k with it....
8290 ***************************************************************************/
8291
8292 #define MAX_USERSHARE_FILE_SIZE (10*1024)
8293
8294 /***************************************************************************
8295  Check allowed stat state of a usershare file.
8296  Ensure we print out who is dicking with us so the admin can
8297  get their sorry ass fired.
8298 ***************************************************************************/
8299
8300 static bool check_usershare_stat(const char *fname,
8301                                  const SMB_STRUCT_STAT *psbuf)
8302 {
8303         if (!S_ISREG(psbuf->st_ex_mode)) {
8304                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8305                         "not a regular file\n",
8306                         fname, (unsigned int)psbuf->st_ex_uid ));
8307                 return false;
8308         }
8309
8310         /* Ensure this doesn't have the other write bit set. */
8311         if (psbuf->st_ex_mode & S_IWOTH) {
8312                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
8313                         "public write. Refusing to allow as a usershare file.\n",
8314                         fname, (unsigned int)psbuf->st_ex_uid ));
8315                 return false;
8316         }
8317
8318         /* Should be 10k or less. */
8319         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
8320                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8321                         "too large (%u) to be a user share file.\n",
8322                         fname, (unsigned int)psbuf->st_ex_uid,
8323                         (unsigned int)psbuf->st_ex_size ));
8324                 return false;
8325         }
8326
8327         return true;
8328 }
8329
8330 /***************************************************************************
8331  Parse the contents of a usershare file.
8332 ***************************************************************************/
8333
8334 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8335                         SMB_STRUCT_STAT *psbuf,
8336                         const char *servicename,
8337                         int snum,
8338                         char **lines,
8339                         int numlines,
8340                         char **pp_sharepath,
8341                         char **pp_comment,
8342                         char **pp_cp_servicename,
8343                         struct security_descriptor **ppsd,
8344                         bool *pallow_guest)
8345 {
8346         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8347         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8348         int us_vers;
8349         SMB_STRUCT_DIR *dp;
8350         SMB_STRUCT_STAT sbuf;
8351         char *sharepath = NULL;
8352         char *comment = NULL;
8353
8354         *pp_sharepath = NULL;
8355         *pp_comment = NULL;
8356
8357         *pallow_guest = false;
8358
8359         if (numlines < 4) {
8360                 return USERSHARE_MALFORMED_FILE;
8361         }
8362
8363         if (strcmp(lines[0], "#VERSION 1") == 0) {
8364                 us_vers = 1;
8365         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8366                 us_vers = 2;
8367                 if (numlines < 5) {
8368                         return USERSHARE_MALFORMED_FILE;
8369                 }
8370         } else {
8371                 return USERSHARE_BAD_VERSION;
8372         }
8373
8374         if (strncmp(lines[1], "path=", 5) != 0) {
8375                 return USERSHARE_MALFORMED_PATH;
8376         }
8377
8378         sharepath = talloc_strdup(ctx, &lines[1][5]);
8379         if (!sharepath) {
8380                 return USERSHARE_POSIX_ERR;
8381         }
8382         trim_string(sharepath, " ", " ");
8383
8384         if (strncmp(lines[2], "comment=", 8) != 0) {
8385                 return USERSHARE_MALFORMED_COMMENT_DEF;
8386         }
8387
8388         comment = talloc_strdup(ctx, &lines[2][8]);
8389         if (!comment) {
8390                 return USERSHARE_POSIX_ERR;
8391         }
8392         trim_string(comment, " ", " ");
8393         trim_char(comment, '"', '"');
8394
8395         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8396                 return USERSHARE_MALFORMED_ACL_DEF;
8397         }
8398
8399         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8400                 return USERSHARE_ACL_ERR;
8401         }
8402
8403         if (us_vers == 2) {
8404                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8405                         return USERSHARE_MALFORMED_ACL_DEF;
8406                 }
8407                 if (lines[4][9] == 'y') {
8408                         *pallow_guest = true;
8409                 }
8410
8411                 /* Backwards compatible extension to file version #2. */
8412                 if (numlines > 5) {
8413                         if (strncmp(lines[5], "sharename=", 10) != 0) {
8414                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
8415                         }
8416                         if (!strequal(&lines[5][10], servicename)) {
8417                                 return USERSHARE_BAD_SHARENAME;
8418                         }
8419                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
8420                         if (!*pp_cp_servicename) {
8421                                 return USERSHARE_POSIX_ERR;
8422                         }
8423                 }
8424         }
8425
8426         if (*pp_cp_servicename == NULL) {
8427                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
8428                 if (!*pp_cp_servicename) {
8429                         return USERSHARE_POSIX_ERR;
8430                 }
8431         }
8432
8433         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8434                 /* Path didn't change, no checks needed. */
8435                 *pp_sharepath = sharepath;
8436                 *pp_comment = comment;
8437                 return USERSHARE_OK;
8438         }
8439
8440         /* The path *must* be absolute. */
8441         if (sharepath[0] != '/') {
8442                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8443                         servicename, sharepath));
8444                 return USERSHARE_PATH_NOT_ABSOLUTE;
8445         }
8446
8447         /* If there is a usershare prefix deny list ensure one of these paths
8448            doesn't match the start of the user given path. */
8449         if (prefixdenylist) {
8450                 int i;
8451                 for ( i=0; prefixdenylist[i]; i++ ) {
8452                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8453                                 servicename, i, prefixdenylist[i], sharepath ));
8454                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8455                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8456                                         "usershare prefix deny list entries.\n",
8457                                         servicename, sharepath));
8458                                 return USERSHARE_PATH_IS_DENIED;
8459                         }
8460                 }
8461         }
8462
8463         /* If there is a usershare prefix allow list ensure one of these paths
8464            does match the start of the user given path. */
8465
8466         if (prefixallowlist) {
8467                 int i;
8468                 for ( i=0; prefixallowlist[i]; i++ ) {
8469                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8470                                 servicename, i, prefixallowlist[i], sharepath ));
8471                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8472                                 break;
8473                         }
8474                 }
8475                 if (prefixallowlist[i] == NULL) {
8476                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8477                                 "usershare prefix allow list entries.\n",
8478                                 servicename, sharepath));
8479                         return USERSHARE_PATH_NOT_ALLOWED;
8480                 }
8481         }
8482
8483         /* Ensure this is pointing to a directory. */
8484         dp = sys_opendir(sharepath);
8485
8486         if (!dp) {
8487                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8488                         servicename, sharepath));
8489                 return USERSHARE_PATH_NOT_DIRECTORY;
8490         }
8491
8492         /* Ensure the owner of the usershare file has permission to share
8493            this directory. */
8494
8495         if (sys_stat(sharepath, &sbuf, false) == -1) {
8496                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8497                         servicename, sharepath, strerror(errno) ));
8498                 sys_closedir(dp);
8499                 return USERSHARE_POSIX_ERR;
8500         }
8501
8502         sys_closedir(dp);
8503
8504         if (!S_ISDIR(sbuf.st_ex_mode)) {
8505                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8506                         servicename, sharepath ));
8507                 return USERSHARE_PATH_NOT_DIRECTORY;
8508         }
8509
8510         /* Check if sharing is restricted to owner-only. */
8511         /* psbuf is the stat of the usershare definition file,
8512            sbuf is the stat of the target directory to be shared. */
8513
8514         if (lp_usershare_owner_only()) {
8515                 /* root can share anything. */
8516                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
8517                         return USERSHARE_PATH_NOT_ALLOWED;
8518                 }
8519         }
8520
8521         *pp_sharepath = sharepath;
8522         *pp_comment = comment;
8523         return USERSHARE_OK;
8524 }
8525
8526 /***************************************************************************
8527  Deal with a usershare file.
8528  Returns:
8529         >= 0 - snum
8530         -1 - Bad name, invalid contents.
8531            - service name already existed and not a usershare, problem
8532             with permissions to share directory etc.
8533 ***************************************************************************/
8534
8535 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8536 {
8537         SMB_STRUCT_STAT sbuf;
8538         SMB_STRUCT_STAT lsbuf;
8539         char *fname = NULL;
8540         char *sharepath = NULL;
8541         char *comment = NULL;
8542         char *cp_service_name = NULL;
8543         char **lines = NULL;
8544         int numlines = 0;
8545         int fd = -1;
8546         int iService = -1;
8547         TALLOC_CTX *ctx = talloc_stackframe();
8548         struct security_descriptor *psd = NULL;
8549         bool guest_ok = false;
8550         char *canon_name = NULL;
8551         bool added_service = false;
8552         int ret = -1;
8553
8554         /* Ensure share name doesn't contain invalid characters. */
8555         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8556                 DEBUG(0,("process_usershare_file: share name %s contains "
8557                         "invalid characters (any of %s)\n",
8558                         file_name, INVALID_SHARENAME_CHARS ));
8559                 goto out;
8560         }
8561
8562         canon_name = canonicalize_servicename(ctx, file_name);
8563         if (!canon_name) {
8564                 goto out;
8565         }
8566
8567         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
8568         if (!fname) {
8569                 goto out;
8570         }
8571
8572         /* Minimize the race condition by doing an lstat before we
8573            open and fstat. Ensure this isn't a symlink link. */
8574
8575         if (sys_lstat(fname, &lsbuf, false) != 0) {
8576                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8577                         fname, strerror(errno) ));
8578                 goto out;
8579         }
8580
8581         /* This must be a regular file, not a symlink, directory or
8582            other strange filetype. */
8583         if (!check_usershare_stat(fname, &lsbuf)) {
8584                 goto out;
8585         }
8586
8587         {
8588                 TDB_DATA data = dbwrap_fetch_bystring(
8589                         ServiceHash, canon_name, canon_name);
8590
8591                 iService = -1;
8592
8593                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
8594                         iService = *(int *)data.dptr;
8595                 }
8596         }
8597
8598         if (iService != -1 &&
8599             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
8600                              &lsbuf.st_ex_mtime) == 0) {
8601                 /* Nothing changed - Mark valid and return. */
8602                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8603                         canon_name ));
8604                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8605                 ret = iService;
8606                 goto out;
8607         }
8608
8609         /* Try and open the file read only - no symlinks allowed. */
8610 #ifdef O_NOFOLLOW
8611         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
8612 #else
8613         fd = sys_open(fname, O_RDONLY, 0);
8614 #endif
8615
8616         if (fd == -1) {
8617                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8618                         fname, strerror(errno) ));
8619                 goto out;
8620         }
8621
8622         /* Now fstat to be *SURE* it's a regular file. */
8623         if (sys_fstat(fd, &sbuf, false) != 0) {
8624                 close(fd);
8625                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8626                         fname, strerror(errno) ));
8627                 goto out;
8628         }
8629
8630         /* Is it the same dev/inode as was lstated ? */
8631         if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) {
8632                 close(fd);
8633                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8634                         "Symlink spoofing going on ?\n", fname ));
8635                 goto out;
8636         }
8637
8638         /* This must be a regular file, not a symlink, directory or
8639            other strange filetype. */
8640         if (!check_usershare_stat(fname, &sbuf)) {
8641                 goto out;
8642         }
8643
8644         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8645
8646         close(fd);
8647         if (lines == NULL) {
8648                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8649                         fname, (unsigned int)sbuf.st_ex_uid ));
8650                 goto out;
8651         }
8652
8653         if (parse_usershare_file(ctx, &sbuf, file_name,
8654                         iService, lines, numlines, &sharepath,
8655                         &comment, &cp_service_name,
8656                         &psd, &guest_ok) != USERSHARE_OK) {
8657                 goto out;
8658         }
8659
8660         /* Everything ok - add the service possibly using a template. */
8661         if (iService < 0) {
8662                 const struct loadparm_service *sp = &sDefault;
8663                 if (snum_template != -1) {
8664                         sp = ServicePtrs[snum_template];
8665                 }
8666
8667                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
8668                         DEBUG(0, ("process_usershare_file: Failed to add "
8669                                 "new service %s\n", cp_service_name));
8670                         goto out;
8671                 }
8672
8673                 added_service = true;
8674
8675                 /* Read only is controlled by usershare ACL below. */
8676                 ServicePtrs[iService]->bRead_only = false;
8677         }
8678
8679         /* Write the ACL of the new/modified share. */
8680         if (!set_share_security(canon_name, psd)) {
8681                  DEBUG(0, ("process_usershare_file: Failed to set share "
8682                         "security for user share %s\n",
8683                         canon_name ));
8684                 goto out;
8685         }
8686
8687         /* If from a template it may be marked invalid. */
8688         ServicePtrs[iService]->valid = true;
8689
8690         /* Set the service as a valid usershare. */
8691         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8692
8693         /* Set guest access. */
8694         if (lp_usershare_allow_guests()) {
8695                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8696         }
8697
8698         /* And note when it was loaded. */
8699         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
8700         string_set(&ServicePtrs[iService]->szPath, sharepath);
8701         string_set(&ServicePtrs[iService]->comment, comment);
8702
8703         ret = iService;
8704
8705   out:
8706
8707         if (ret == -1 && iService != -1 && added_service) {
8708                 lp_remove_service(iService);
8709         }
8710
8711         TALLOC_FREE(lines);
8712         TALLOC_FREE(ctx);
8713         return ret;
8714 }
8715
8716 /***************************************************************************
8717  Checks if a usershare entry has been modified since last load.
8718 ***************************************************************************/
8719
8720 static bool usershare_exists(int iService, struct timespec *last_mod)
8721 {
8722         SMB_STRUCT_STAT lsbuf;
8723         const char *usersharepath = Globals.szUsersharePath;
8724         char *fname;
8725
8726         if (asprintf(&fname, "%s/%s",
8727                                 usersharepath,
8728                                 ServicePtrs[iService]->szService) < 0) {
8729                 return false;
8730         }
8731
8732         if (sys_lstat(fname, &lsbuf, false) != 0) {
8733                 SAFE_FREE(fname);
8734                 return false;
8735         }
8736
8737         if (!S_ISREG(lsbuf.st_ex_mode)) {
8738                 SAFE_FREE(fname);
8739                 return false;
8740         }
8741
8742         SAFE_FREE(fname);
8743         *last_mod = lsbuf.st_ex_mtime;
8744         return true;
8745 }
8746
8747 /***************************************************************************
8748  Load a usershare service by name. Returns a valid servicenumber or -1.
8749 ***************************************************************************/
8750
8751 int load_usershare_service(const char *servicename)
8752 {
8753         SMB_STRUCT_STAT sbuf;
8754         const char *usersharepath = Globals.szUsersharePath;
8755         int max_user_shares = Globals.iUsershareMaxShares;
8756         int snum_template = -1;
8757
8758         if (*usersharepath == 0 ||  max_user_shares == 0) {
8759                 return -1;
8760         }
8761
8762         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8763                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8764                         usersharepath, strerror(errno) ));
8765                 return -1;
8766         }
8767
8768         if (!S_ISDIR(sbuf.st_ex_mode)) {
8769                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8770                         usersharepath ));
8771                 return -1;
8772         }
8773
8774         /*
8775          * This directory must be owned by root, and have the 't' bit set.
8776          * It also must not be writable by "other".
8777          */
8778
8779 #ifdef S_ISVTX
8780         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8781 #else
8782         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8783 #endif
8784                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8785                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8786                         usersharepath ));
8787                 return -1;
8788         }
8789
8790         /* Ensure the template share exists if it's set. */
8791         if (Globals.szUsershareTemplateShare[0]) {
8792                 /* We can't use lp_servicenumber here as we are recommending that
8793                    template shares have -valid=false set. */
8794                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8795                         if (ServicePtrs[snum_template]->szService &&
8796                                         strequal(ServicePtrs[snum_template]->szService,
8797                                                 Globals.szUsershareTemplateShare)) {
8798                                 break;
8799                         }
8800                 }
8801
8802                 if (snum_template == -1) {
8803                         DEBUG(0,("load_usershare_service: usershare template share %s "
8804                                 "does not exist.\n",
8805                                 Globals.szUsershareTemplateShare ));
8806                         return -1;
8807                 }
8808         }
8809
8810         return process_usershare_file(usersharepath, servicename, snum_template);
8811 }
8812
8813 /***************************************************************************
8814  Load all user defined shares from the user share directory.
8815  We only do this if we're enumerating the share list.
8816  This is the function that can delete usershares that have
8817  been removed.
8818 ***************************************************************************/
8819
8820 int load_usershare_shares(struct smbd_server_connection *sconn)
8821 {
8822         SMB_STRUCT_DIR *dp;
8823         SMB_STRUCT_STAT sbuf;
8824         SMB_STRUCT_DIRENT *de;
8825         int num_usershares = 0;
8826         int max_user_shares = Globals.iUsershareMaxShares;
8827         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8828         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8829         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8830         int iService;
8831         int snum_template = -1;
8832         const char *usersharepath = Globals.szUsersharePath;
8833         int ret = lp_numservices();
8834
8835         if (max_user_shares == 0 || *usersharepath == '\0') {
8836                 return lp_numservices();
8837         }
8838
8839         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8840                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8841                         usersharepath, strerror(errno) ));
8842                 return ret;
8843         }
8844
8845         /*
8846          * This directory must be owned by root, and have the 't' bit set.
8847          * It also must not be writable by "other".
8848          */
8849
8850 #ifdef S_ISVTX
8851         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8852 #else
8853         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8854 #endif
8855                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8856                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8857                         usersharepath ));
8858                 return ret;
8859         }
8860
8861         /* Ensure the template share exists if it's set. */
8862         if (Globals.szUsershareTemplateShare[0]) {
8863                 /* We can't use lp_servicenumber here as we are recommending that
8864                    template shares have -valid=false set. */
8865                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8866                         if (ServicePtrs[snum_template]->szService &&
8867                                         strequal(ServicePtrs[snum_template]->szService,
8868                                                 Globals.szUsershareTemplateShare)) {
8869                                 break;
8870                         }
8871                 }
8872
8873                 if (snum_template == -1) {
8874                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8875                                 "does not exist.\n",
8876                                 Globals.szUsershareTemplateShare ));
8877                         return ret;
8878                 }
8879         }
8880
8881         /* Mark all existing usershares as pending delete. */
8882         for (iService = iNumServices - 1; iService >= 0; iService--) {
8883                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8884                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8885                 }
8886         }
8887
8888         dp = sys_opendir(usersharepath);
8889         if (!dp) {
8890                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8891                         usersharepath, strerror(errno) ));
8892                 return ret;
8893         }
8894
8895         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8896                         (de = sys_readdir(dp));
8897                         num_dir_entries++ ) {
8898                 int r;
8899                 const char *n = de->d_name;
8900
8901                 /* Ignore . and .. */
8902                 if (*n == '.') {
8903                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8904                                 continue;
8905                         }
8906                 }
8907
8908                 if (n[0] == ':') {
8909                         /* Temporary file used when creating a share. */
8910                         num_tmp_dir_entries++;
8911                 }
8912
8913                 /* Allow 20% tmp entries. */
8914                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8915                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8916                                 "in directory %s\n",
8917                                 num_tmp_dir_entries, usersharepath));
8918                         break;
8919                 }
8920
8921                 r = process_usershare_file(usersharepath, n, snum_template);
8922                 if (r == 0) {
8923                         /* Update the services count. */
8924                         num_usershares++;
8925                         if (num_usershares >= max_user_shares) {
8926                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8927                                         "on file %s in directory %s\n",
8928                                         n, usersharepath ));
8929                                 break;
8930                         }
8931                 } else if (r == -1) {
8932                         num_bad_dir_entries++;
8933                 }
8934
8935                 /* Allow 20% bad entries. */
8936                 if (num_bad_dir_entries > allowed_bad_entries) {
8937                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8938                                 "in directory %s\n",
8939                                 num_bad_dir_entries, usersharepath));
8940                         break;
8941                 }
8942
8943                 /* Allow 20% bad entries. */
8944                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8945                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8946                         "in directory %s\n",
8947                         num_dir_entries, usersharepath));
8948                         break;
8949                 }
8950         }
8951
8952         sys_closedir(dp);
8953
8954         /* Sweep through and delete any non-refreshed usershares that are
8955            not currently in use. */
8956         for (iService = iNumServices - 1; iService >= 0; iService--) {
8957                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8958                         if (conn_snum_used(sconn, iService)) {
8959                                 continue;
8960                         }
8961                         /* Remove from the share ACL db. */
8962                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8963                                 lp_servicename(iService) ));
8964                         delete_share_security(lp_servicename(iService));
8965                         free_service_byindex(iService);
8966                 }
8967         }
8968
8969         return lp_numservices();
8970 }
8971
8972 /********************************************************
8973  Destroy global resources allocated in this file
8974 ********************************************************/
8975
8976 void gfree_loadparm(void)
8977 {
8978         int i;
8979
8980         free_file_list();
8981
8982         /* Free resources allocated to services */
8983
8984         for ( i = 0; i < iNumServices; i++ ) {
8985                 if ( VALID(i) ) {
8986                         free_service_byindex(i);
8987                 }
8988         }
8989
8990         SAFE_FREE( ServicePtrs );
8991         iNumServices = 0;
8992
8993         /* Now release all resources allocated to global
8994            parameters and the default service */
8995
8996         free_global_parameters();
8997 }
8998
8999
9000 /***************************************************************************
9001  Allow client apps to specify that they are a client
9002 ***************************************************************************/
9003 void lp_set_in_client(bool b)
9004 {
9005     in_client = b;
9006 }
9007
9008
9009 /***************************************************************************
9010  Determine if we're running in a client app
9011 ***************************************************************************/
9012 bool lp_is_in_client(void)
9013 {
9014     return in_client;
9015 }
9016
9017 /***************************************************************************
9018  Load the services array from the services file. Return true on success,
9019  false on failure.
9020 ***************************************************************************/
9021
9022 static bool lp_load_ex(const char *pszFname,
9023                        bool global_only,
9024                        bool save_defaults,
9025                        bool add_ipc,
9026                        bool initialize_globals,
9027                        bool allow_include_registry,
9028                        bool allow_registry_shares)
9029 {
9030         char *n2 = NULL;
9031         bool bRetval;
9032
9033         bRetval = false;
9034
9035         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
9036
9037         bInGlobalSection = true;
9038         bGlobalOnly = global_only;
9039         bAllowIncludeRegistry = allow_include_registry;
9040
9041         init_globals(initialize_globals);
9042
9043         free_file_list();
9044
9045         if (save_defaults) {
9046                 init_locals();
9047                 lp_save_defaults();
9048         }
9049
9050         free_param_opts(&Globals.param_opt);
9051
9052         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
9053
9054         /* We get sections first, so have to start 'behind' to make up */
9055         iServiceIndex = -1;
9056
9057         if (lp_config_backend_is_file()) {
9058                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
9059                                         current_user_info.domain,
9060                                         pszFname);
9061                 if (!n2) {
9062                         smb_panic("lp_load_ex: out of memory");
9063                 }
9064
9065                 add_to_file_list(pszFname, n2);
9066
9067                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
9068                 TALLOC_FREE(n2);
9069
9070                 /* finish up the last section */
9071                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
9072                 if (bRetval) {
9073                         if (iServiceIndex >= 0) {
9074                                 bRetval = service_ok(iServiceIndex);
9075                         }
9076                 }
9077
9078                 if (lp_config_backend_is_registry()) {
9079                         /* config backend changed to registry in config file */
9080                         /*
9081                          * We need to use this extra global variable here to
9082                          * survive restart: init_globals uses this as a default
9083                          * for ConfigBackend. Otherwise, init_globals would
9084                          *  send us into an endless loop here.
9085                          */
9086                         config_backend = CONFIG_BACKEND_REGISTRY;
9087                         /* start over */
9088                         DEBUG(1, ("lp_load_ex: changing to config backend "
9089                                   "registry\n"));
9090                         init_globals(true);
9091                         lp_kill_all_services();
9092                         return lp_load_ex(pszFname, global_only, save_defaults,
9093                                           add_ipc, initialize_globals,
9094                                           allow_include_registry,
9095                                           allow_registry_shares);
9096                 }
9097         } else if (lp_config_backend_is_registry()) {
9098                 bRetval = process_registry_globals();
9099         } else {
9100                 DEBUG(0, ("Illegal config  backend given: %d\n",
9101                           lp_config_backend()));
9102                 bRetval = false;
9103         }
9104
9105         if (bRetval && lp_registry_shares() && allow_registry_shares) {
9106                 bRetval = process_registry_shares();
9107         }
9108
9109         lp_add_auto_services(lp_auto_services());
9110
9111         if (add_ipc) {
9112                 /* When 'restrict anonymous = 2' guest connections to ipc$
9113                    are denied */
9114                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
9115                 if ( lp_enable_asu_support() ) {
9116                         lp_add_ipc("ADMIN$", false);
9117                 }
9118         }
9119
9120         set_server_role();
9121         set_allowed_client_auth();
9122
9123         if (lp_security() == SEC_SHARE) {
9124                 DEBUG(1, ("WARNING: The security=share option is deprecated\n"));
9125         } else if (lp_security() == SEC_SERVER) {
9126                 DEBUG(1, ("WARNING: The security=server option is deprecated\n"));
9127         }
9128
9129         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
9130                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
9131                           lp_passwordserver()));
9132         }
9133
9134         bLoaded = true;
9135
9136         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
9137         /* if bWINSsupport is true and we are in the client            */
9138         if (lp_is_in_client() && Globals.bWINSsupport) {
9139                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
9140         }
9141
9142         init_iconv();
9143
9144         fault_configure(smb_panic_s3);
9145
9146         bAllowIncludeRegistry = true;
9147
9148         return (bRetval);
9149 }
9150
9151 bool lp_load(const char *pszFname,
9152              bool global_only,
9153              bool save_defaults,
9154              bool add_ipc,
9155              bool initialize_globals)
9156 {
9157         return lp_load_ex(pszFname,
9158                           global_only,
9159                           save_defaults,
9160                           add_ipc,
9161                           initialize_globals,
9162                           true,   /* allow_include_registry */
9163                           false); /* allow_registry_shares*/
9164 }
9165
9166 bool lp_load_initial_only(const char *pszFname)
9167 {
9168         return lp_load_ex(pszFname,
9169                           true,   /* global only */
9170                           false,  /* save_defaults */
9171                           false,  /* add_ipc */
9172                           true,   /* initialize_globals */
9173                           false,  /* allow_include_registry */
9174                           false); /* allow_registry_shares*/
9175 }
9176
9177 bool lp_load_with_registry_shares(const char *pszFname,
9178                                   bool global_only,
9179                                   bool save_defaults,
9180                                   bool add_ipc,
9181                                   bool initialize_globals)
9182 {
9183         return lp_load_ex(pszFname,
9184                           global_only,
9185                           save_defaults,
9186                           add_ipc,
9187                           initialize_globals,
9188                           true,  /* allow_include_registry */
9189                           true); /* allow_registry_shares*/
9190 }
9191
9192 /***************************************************************************
9193  Return the max number of services.
9194 ***************************************************************************/
9195
9196 int lp_numservices(void)
9197 {
9198         return (iNumServices);
9199 }
9200
9201 /***************************************************************************
9202 Display the contents of the services array in human-readable form.
9203 ***************************************************************************/
9204
9205 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
9206 {
9207         int iService;
9208
9209         if (show_defaults)
9210                 defaults_saved = false;
9211
9212         dump_globals(f);
9213
9214         dump_a_service(&sDefault, f);
9215
9216         for (iService = 0; iService < maxtoprint; iService++) {
9217                 fprintf(f,"\n");
9218                 lp_dump_one(f, show_defaults, iService);
9219         }
9220 }
9221
9222 /***************************************************************************
9223 Display the contents of one service in human-readable form.
9224 ***************************************************************************/
9225
9226 void lp_dump_one(FILE * f, bool show_defaults, int snum)
9227 {
9228         if (VALID(snum)) {
9229                 if (ServicePtrs[snum]->szService[0] == '\0')
9230                         return;
9231                 dump_a_service(ServicePtrs[snum], f);
9232         }
9233 }
9234
9235 /***************************************************************************
9236 Return the number of the service with the given name, or -1 if it doesn't
9237 exist. Note that this is a DIFFERENT ANIMAL from the internal function
9238 getservicebyname()! This works ONLY if all services have been loaded, and
9239 does not copy the found service.
9240 ***************************************************************************/
9241
9242 int lp_servicenumber(const char *pszServiceName)
9243 {
9244         int iService;
9245         fstring serviceName;
9246
9247         if (!pszServiceName) {
9248                 return GLOBAL_SECTION_SNUM;
9249         }
9250
9251         for (iService = iNumServices - 1; iService >= 0; iService--) {
9252                 if (VALID(iService) && ServicePtrs[iService]->szService) {
9253                         /*
9254                          * The substitution here is used to support %U is
9255                          * service names
9256                          */
9257                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
9258                         standard_sub_basic(get_current_username(),
9259                                            current_user_info.domain,
9260                                            serviceName,sizeof(serviceName));
9261                         if (strequal(serviceName, pszServiceName)) {
9262                                 break;
9263                         }
9264                 }
9265         }
9266
9267         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
9268                 struct timespec last_mod;
9269
9270                 if (!usershare_exists(iService, &last_mod)) {
9271                         /* Remove the share security tdb entry for it. */
9272                         delete_share_security(lp_servicename(iService));
9273                         /* Remove it from the array. */
9274                         free_service_byindex(iService);
9275                         /* Doesn't exist anymore. */
9276                         return GLOBAL_SECTION_SNUM;
9277                 }
9278
9279                 /* Has it been modified ? If so delete and reload. */
9280                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
9281                                      &last_mod) < 0) {
9282                         /* Remove it from the array. */
9283                         free_service_byindex(iService);
9284                         /* and now reload it. */
9285                         iService = load_usershare_service(pszServiceName);
9286                 }
9287         }
9288
9289         if (iService < 0) {
9290                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9291                 return GLOBAL_SECTION_SNUM;
9292         }
9293
9294         return (iService);
9295 }
9296
9297 bool share_defined(const char *service_name)
9298 {
9299         return (lp_servicenumber(service_name) != -1);
9300 }
9301
9302 /*******************************************************************
9303  A useful volume label function. 
9304 ********************************************************************/
9305
9306 const char *volume_label(int snum)
9307 {
9308         char *ret;
9309         const char *label = lp_volume(snum);
9310         if (!*label) {
9311                 label = lp_servicename(snum);
9312         }
9313
9314         /* This returns a 33 byte guarenteed null terminated string. */
9315         ret = talloc_strndup(talloc_tos(), label, 32);
9316         if (!ret) {
9317                 return "";
9318         }               
9319         return ret;
9320 }
9321
9322 /*******************************************************************
9323  Get the default server type we will announce as via nmbd.
9324 ********************************************************************/
9325
9326 int lp_default_server_announce(void)
9327 {
9328         int default_server_announce = 0;
9329         default_server_announce |= SV_TYPE_WORKSTATION;
9330         default_server_announce |= SV_TYPE_SERVER;
9331         default_server_announce |= SV_TYPE_SERVER_UNIX;
9332
9333         /* note that the flag should be set only if we have a 
9334            printer service but nmbd doesn't actually load the 
9335            services so we can't tell   --jerry */
9336
9337         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9338
9339         default_server_announce |= SV_TYPE_SERVER_NT;
9340         default_server_announce |= SV_TYPE_NT;
9341
9342         switch (lp_server_role()) {
9343                 case ROLE_DOMAIN_MEMBER:
9344                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9345                         break;
9346                 case ROLE_DOMAIN_PDC:
9347                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9348                         break;
9349                 case ROLE_DOMAIN_BDC:
9350                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9351                         break;
9352                 case ROLE_STANDALONE:
9353                 default:
9354                         break;
9355         }
9356         if (lp_time_server())
9357                 default_server_announce |= SV_TYPE_TIME_SOURCE;
9358
9359         if (lp_host_msdfs())
9360                 default_server_announce |= SV_TYPE_DFS_SERVER;
9361
9362         return default_server_announce;
9363 }
9364
9365 /***********************************************************
9366  If we are PDC then prefer us as DMB
9367 ************************************************************/
9368
9369 bool lp_domain_master(void)
9370 {
9371         if (Globals.iDomainMaster == Auto)
9372                 return (lp_server_role() == ROLE_DOMAIN_PDC);
9373
9374         return (bool)Globals.iDomainMaster;
9375 }
9376
9377 /***********************************************************
9378  If we are PDC then prefer us as DMB
9379 ************************************************************/
9380
9381 bool lp_domain_master_true_or_auto(void)
9382 {
9383         if (Globals.iDomainMaster) /* auto or yes */
9384                 return true;
9385
9386         return false;
9387 }
9388
9389 /***********************************************************
9390  If we are DMB then prefer us as LMB
9391 ************************************************************/
9392
9393 bool lp_preferred_master(void)
9394 {
9395         if (Globals.iPreferredMaster == Auto)
9396                 return (lp_local_master() && lp_domain_master());
9397
9398         return (bool)Globals.iPreferredMaster;
9399 }
9400
9401 /*******************************************************************
9402  Remove a service.
9403 ********************************************************************/
9404
9405 void lp_remove_service(int snum)
9406 {
9407         ServicePtrs[snum]->valid = false;
9408         invalid_services[num_invalid_services++] = snum;
9409 }
9410
9411 /*******************************************************************
9412  Copy a service.
9413 ********************************************************************/
9414
9415 void lp_copy_service(int snum, const char *new_name)
9416 {
9417         do_section(new_name, NULL);
9418         if (snum >= 0) {
9419                 snum = lp_servicenumber(new_name);
9420                 if (snum >= 0)
9421                         lp_do_parameter(snum, "copy", lp_servicename(snum));
9422         }
9423 }
9424
9425
9426 /***********************************************************
9427  Set the global name resolution order (used in smbclient).
9428 ************************************************************/
9429
9430 void lp_set_name_resolve_order(const char *new_order)
9431 {
9432         string_set(&Globals.szNameResolveOrder, new_order);
9433 }
9434
9435 const char *lp_printername(int snum)
9436 {
9437         const char *ret = _lp_printername(snum);
9438         if (ret == NULL || (ret != NULL && *ret == '\0'))
9439                 ret = lp_const_servicename(snum);
9440
9441         return ret;
9442 }
9443
9444
9445 /***********************************************************
9446  Allow daemons such as winbindd to fix their logfile name.
9447 ************************************************************/
9448
9449 void lp_set_logfile(const char *name)
9450 {
9451         string_set(&Globals.szLogFile, name);
9452         debug_set_logfile(name);
9453 }
9454
9455 /*******************************************************************
9456  Return the max print jobs per queue.
9457 ********************************************************************/
9458
9459 int lp_maxprintjobs(int snum)
9460 {
9461         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9462         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9463                 maxjobs = PRINT_MAX_JOBID - 1;
9464
9465         return maxjobs;
9466 }
9467
9468 const char *lp_printcapname(void)
9469 {
9470         if ((Globals.szPrintcapname != NULL) &&
9471             (Globals.szPrintcapname[0] != '\0'))
9472                 return Globals.szPrintcapname;
9473
9474         if (sDefault.iPrinting == PRINT_CUPS) {
9475 #ifdef HAVE_CUPS
9476                 return "cups";
9477 #else
9478                 return "lpstat";
9479 #endif
9480         }
9481
9482         if (sDefault.iPrinting == PRINT_BSD)
9483                 return "/etc/printcap";
9484
9485         return PRINTCAP_NAME;
9486 }
9487
9488 static uint32 spoolss_state;
9489
9490 bool lp_disable_spoolss( void )
9491 {
9492         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9493                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9494
9495         return spoolss_state == SVCCTL_STOPPED ? true : false;
9496 }
9497
9498 void lp_set_spoolss_state( uint32 state )
9499 {
9500         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9501
9502         spoolss_state = state;
9503 }
9504
9505 uint32 lp_get_spoolss_state( void )
9506 {
9507         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9508 }
9509
9510 /*******************************************************************
9511  Ensure we don't use sendfile if server smb signing is active.
9512 ********************************************************************/
9513
9514 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
9515 {
9516         bool sign_active = false;
9517
9518         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9519         if (get_Protocol() < PROTOCOL_NT1) {
9520                 return false;
9521         }
9522         if (signing_state) {
9523                 sign_active = smb_signing_is_active(signing_state);
9524         }
9525         return (_lp_use_sendfile(snum) &&
9526                         (get_remote_arch() != RA_WIN95) &&
9527                         !sign_active);
9528 }
9529
9530 /*******************************************************************
9531  Turn off sendfile if we find the underlying OS doesn't support it.
9532 ********************************************************************/
9533
9534 void set_use_sendfile(int snum, bool val)
9535 {
9536         if (LP_SNUM_OK(snum))
9537                 ServicePtrs[snum]->bUseSendfile = val;
9538         else
9539                 sDefault.bUseSendfile = val;
9540 }
9541
9542 /*******************************************************************
9543  Turn off storing DOS attributes if this share doesn't support it.
9544 ********************************************************************/
9545
9546 void set_store_dos_attributes(int snum, bool val)
9547 {
9548         if (!LP_SNUM_OK(snum))
9549                 return;
9550         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9551 }
9552
9553 void lp_set_mangling_method(const char *new_method)
9554 {
9555         string_set(&Globals.szManglingMethod, new_method);
9556 }
9557
9558 /*******************************************************************
9559  Global state for POSIX pathname processing.
9560 ********************************************************************/
9561
9562 static bool posix_pathnames;
9563
9564 bool lp_posix_pathnames(void)
9565 {
9566         return posix_pathnames;
9567 }
9568
9569 /*******************************************************************
9570  Change everything needed to ensure POSIX pathname processing (currently
9571  not much).
9572 ********************************************************************/
9573
9574 void lp_set_posix_pathnames(void)
9575 {
9576         posix_pathnames = true;
9577 }
9578
9579 /*******************************************************************
9580  Global state for POSIX lock processing - CIFS unix extensions.
9581 ********************************************************************/
9582
9583 bool posix_default_lock_was_set;
9584 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9585
9586 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9587 {
9588         if (posix_default_lock_was_set) {
9589                 return posix_cifsx_locktype;
9590         } else {
9591                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9592         }
9593 }
9594
9595 /*******************************************************************
9596 ********************************************************************/
9597
9598 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9599 {
9600         posix_default_lock_was_set = true;
9601         posix_cifsx_locktype = val;
9602 }
9603
9604 int lp_min_receive_file_size(void)
9605 {
9606         if (Globals.iminreceivefile < 0) {
9607                 return 0;
9608         }
9609         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9610 }
9611
9612 /*******************************************************************
9613  If socket address is an empty character string, it is necessary to 
9614  define it as "0.0.0.0". 
9615 ********************************************************************/
9616
9617 const char *lp_socket_address(void)
9618 {
9619         char *sock_addr = Globals.szSocketAddress;
9620
9621         if (sock_addr[0] == '\0'){
9622                 string_set(&Globals.szSocketAddress, "0.0.0.0");
9623         }
9624         return  Globals.szSocketAddress;
9625 }
9626
9627 /*******************************************************************
9628  Safe wide links checks.
9629  This helper function always verify the validity of wide links,
9630  even after a configuration file reload.
9631 ********************************************************************/
9632
9633 static bool lp_widelinks_internal(int snum)
9634 {
9635         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
9636                         sDefault.bWidelinks);
9637 }
9638
9639 void widelinks_warning(int snum)
9640 {
9641         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
9642                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
9643                         "These parameters are incompatible. "
9644                         "Wide links will be disabled for this share.\n",
9645                         lp_servicename(snum) ));
9646         }
9647 }
9648
9649 bool lp_widelinks(int snum)
9650 {
9651         /* wide links is always incompatible with unix extensions */
9652         if (lp_unix_extensions()) {
9653                 return false;
9654         }
9655
9656         return lp_widelinks_internal(snum);
9657 }
9658
9659 bool lp_writeraw(void)
9660 {
9661         if (lp_async_smb_echo_handler()) {
9662                 return false;
9663         }
9664         return _lp_writeraw();
9665 }
9666
9667 bool lp_readraw(void)
9668 {
9669         if (lp_async_smb_echo_handler()) {
9670                 return false;
9671         }
9672         return _lp_readraw();
9673 }