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