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