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