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