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