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