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