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