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