12ba2f1d3b9a487a5b14ab82aa5109163af86c2d
[mat/samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "printing.h"
60 #include "lib/smbconf/smbconf.h"
61 #include "lib/smbconf/smbconf_init.h"
62 #include "lib/param/loadparm.h"
63
64 #include "ads.h"
65 #include "../librpc/gen_ndr/svcctl.h"
66 #include "intl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71 #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                 char *tmp;
4375
4376                 tdbfile = talloc_asprintf(
4377                         talloc_tos(), "tdbfile=%s",
4378                         lp_parm_const_string(-1, "vlp", "tdbfile",
4379                                              "/tmp/vlp.tdb"));
4380                 if (tdbfile == NULL) {
4381                         tdbfile="tdbfile=/tmp/vlp.tdb";
4382                 }
4383
4384                 tmp = talloc_asprintf(talloc_tos(), "vlp %s print %%p %%s",
4385                                       tdbfile);
4386                 string_set(&pService->szPrintcommand,
4387                            tmp ? tmp : "vlp print %p %s");
4388                 TALLOC_FREE(tmp);
4389
4390                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lpq %%p",
4391                                       tdbfile);
4392                 string_set(&pService->szLpqcommand,
4393                            tmp ? tmp : "vlp lpq %p");
4394                 TALLOC_FREE(tmp);
4395
4396                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lprm %%p %%j",
4397                                       tdbfile);
4398                 string_set(&pService->szLprmcommand,
4399                            tmp ? tmp : "vlp lprm %p %j");
4400                 TALLOC_FREE(tmp);
4401
4402                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lppause %%p %%j",
4403                                       tdbfile);
4404                 string_set(&pService->szLppausecommand,
4405                            tmp ? tmp : "vlp lppause %p %j");
4406                 TALLOC_FREE(tmp);
4407
4408                 tmp = talloc_asprintf(talloc_tos(), "vlp %s lpresume %%p %%j",
4409                                       tdbfile);
4410                 string_set(&pService->szLpresumecommand,
4411                            tmp ? tmp : "vlp lpresume %p %j");
4412                 TALLOC_FREE(tmp);
4413
4414                 tmp = talloc_asprintf(talloc_tos(), "vlp %s queuepause %%p",
4415                                       tdbfile);
4416                 string_set(&pService->szQueuepausecommand,
4417                            tmp ? tmp : "vlp queuepause %p");
4418                 TALLOC_FREE(tmp);
4419
4420                 tmp = talloc_asprintf(talloc_tos(), "vlp %s queueresume %%p",
4421                                       tdbfile);
4422                 string_set(&pService->szQueueresumecommand,
4423                            tmp ? tmp : "vlp queueresume %p");
4424                 TALLOC_FREE(tmp);
4425
4426                 break;
4427         }
4428 #endif /* DEVELOPER */
4429
4430         }
4431 }
4432 /**
4433  *  Function to return the default value for the maximum number of open
4434  *  file descriptors permitted.  This function tries to consult the
4435  *  kernel-level (sysctl) and ulimit (getrlimit()) values and goes
4436  *  the smaller of those.
4437  */
4438 static int max_open_files(void)
4439 {
4440         int sysctl_max = MAX_OPEN_FILES;
4441         int rlimit_max = MAX_OPEN_FILES;
4442
4443 #ifdef HAVE_SYSCTLBYNAME
4444         {
4445                 size_t size = sizeof(sysctl_max);
4446                 sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
4447                              0);
4448         }
4449 #endif
4450
4451 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
4452         {
4453                 struct rlimit rl;
4454
4455                 ZERO_STRUCT(rl);
4456
4457                 if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
4458                         rlimit_max = rl.rlim_cur;
4459
4460 #if defined(RLIM_INFINITY)
4461                 if(rl.rlim_cur == RLIM_INFINITY)
4462                         rlimit_max = MAX_OPEN_FILES;
4463 #endif
4464         }
4465 #endif
4466
4467         if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
4468                 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
4469                         "minimum Windows limit (%d)\n",
4470                         sysctl_max,
4471                         MIN_OPEN_FILES_WINDOWS));
4472                 sysctl_max = MIN_OPEN_FILES_WINDOWS;
4473         }
4474
4475         if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
4476                 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
4477                         "minimum Windows limit (%d)\n",
4478                         rlimit_max,
4479                         MIN_OPEN_FILES_WINDOWS));
4480                 rlimit_max = MIN_OPEN_FILES_WINDOWS;
4481         }
4482
4483         return MIN(sysctl_max, rlimit_max);
4484 }
4485
4486 /**
4487  * Common part of freeing allocated data for one parameter.
4488  */
4489 static void free_one_parameter_common(void *parm_ptr,
4490                                       struct parm_struct parm)
4491 {
4492         if ((parm.type == P_STRING) ||
4493             (parm.type == P_USTRING))
4494         {
4495                 string_free((char**)parm_ptr);
4496         } else if (parm.type == P_LIST) {
4497                 TALLOC_FREE(*((char***)parm_ptr));
4498         }
4499 }
4500
4501 /**
4502  * Free the allocated data for one parameter for a share
4503  * given as a service struct.
4504  */
4505 static void free_one_parameter(struct loadparm_service *service,
4506                                struct parm_struct parm)
4507 {
4508         void *parm_ptr;
4509
4510         if (parm.p_class != P_LOCAL) {
4511                 return;
4512         }
4513
4514         parm_ptr = lp_parm_ptr(service, &parm);
4515
4516         free_one_parameter_common(parm_ptr, parm);
4517 }
4518
4519 /**
4520  * Free the allocated parameter data of a share given
4521  * as a service struct.
4522  */
4523 static void free_parameters(struct loadparm_service *service)
4524 {
4525         uint32_t i;
4526
4527         for (i=0; parm_table[i].label; i++) {
4528                 free_one_parameter(service, parm_table[i]);
4529         }
4530 }
4531
4532 /**
4533  * Free the allocated data for one parameter for a given share
4534  * specified by an snum.
4535  */
4536 static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
4537 {
4538         void *parm_ptr;
4539
4540         if (snum < 0) {
4541                 parm_ptr = lp_parm_ptr(NULL, &parm);
4542         } else if (parm.p_class != P_LOCAL) {
4543                 return;
4544         } else {
4545                 parm_ptr = lp_local_ptr_by_snum(snum, &parm);
4546         }
4547
4548         free_one_parameter_common(parm_ptr, parm);
4549 }
4550
4551 /**
4552  * Free the allocated parameter data for a share specified
4553  * by an snum.
4554  */
4555 static void free_parameters_by_snum(int snum)
4556 {
4557         uint32_t i;
4558
4559         for (i=0; parm_table[i].label; i++) {
4560                 free_one_parameter_by_snum(snum, parm_table[i]);
4561         }
4562 }
4563
4564 /**
4565  * Free the allocated global parameters.
4566  */
4567 static void free_global_parameters(void)
4568 {
4569         free_param_opts(&Globals.param_opt);
4570         free_parameters_by_snum(GLOBAL_SECTION_SNUM);
4571 }
4572
4573 static int map_parameter(const char *pszParmName);
4574
4575 struct lp_stored_option {
4576         struct lp_stored_option *prev, *next;
4577         const char *label;
4578         const char *value;
4579 };
4580
4581 static struct lp_stored_option *stored_options;
4582
4583 /*
4584   save options set by lp_set_cmdline() into a list. This list is
4585   re-applied when we do a globals reset, so that cmdline set options
4586   are sticky across reloads of smb.conf
4587  */
4588 static bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
4589 {
4590         struct lp_stored_option *entry, *entry_next;
4591         for (entry = stored_options; entry != NULL; entry = entry_next) {
4592                 entry_next = entry->next;
4593                 if (strcmp(pszParmName, entry->label) == 0) {
4594                         DLIST_REMOVE(stored_options, entry);
4595                         talloc_free(entry);
4596                         break;
4597                 }
4598         }
4599
4600         entry = talloc(NULL, struct lp_stored_option);
4601         if (!entry) {
4602                 return false;
4603         }
4604
4605         entry->label = talloc_strdup(entry, pszParmName);
4606         if (!entry->label) {
4607                 talloc_free(entry);
4608                 return false;
4609         }
4610
4611         entry->value = talloc_strdup(entry, pszParmValue);
4612         if (!entry->value) {
4613                 talloc_free(entry);
4614                 return false;
4615         }
4616
4617         DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
4618
4619         return true;
4620 }
4621
4622 static bool apply_lp_set_cmdline(void)
4623 {
4624         struct lp_stored_option *entry = NULL;
4625         for (entry = stored_options; entry != NULL; entry = entry->next) {
4626                 if (!lp_set_cmdline_helper(entry->label, entry->value, false)) {
4627                         DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
4628                                   entry->label, entry->value));
4629                         return false;
4630                 }
4631         }
4632         return true;
4633 }
4634
4635 /***************************************************************************
4636  Initialise the global parameter structure.
4637 ***************************************************************************/
4638
4639 static void init_globals(bool reinit_globals)
4640 {
4641         static bool done_init = false;
4642         char *s = NULL;
4643         int i;
4644
4645         /* If requested to initialize only once and we've already done it... */
4646         if (!reinit_globals && done_init) {
4647                 /* ... then we have nothing more to do */
4648                 return;
4649         }
4650
4651         if (!done_init) {
4652                 /* The logfile can be set before this is invoked. Free it if so. */
4653                 if (Globals.logfile != NULL) {
4654                         string_free(&Globals.logfile);
4655                         Globals.logfile = NULL;
4656                 }
4657                 done_init = true;
4658         } else {
4659                 free_global_parameters();
4660         }
4661
4662         /* This memset and the free_global_parameters() above will
4663          * wipe out smb.conf options set with lp_set_cmdline().  The
4664          * apply_lp_set_cmdline() call puts these values back in the
4665          * table once the defaults are set */
4666         ZERO_STRUCT(Globals);
4667
4668         for (i = 0; parm_table[i].label; i++) {
4669                 if ((parm_table[i].type == P_STRING ||
4670                      parm_table[i].type == P_USTRING))
4671                 {
4672                         string_set((char **)lp_parm_ptr(NULL, &parm_table[i]), "");
4673                 }
4674         }
4675
4676
4677         string_set(&sDefault.fstype, FSTYPE_STRING);
4678         string_set(&sDefault.szPrintjobUsername, "%U");
4679
4680         init_printer_values(&sDefault);
4681
4682
4683         DEBUG(3, ("Initialising global parameters\n"));
4684
4685         /* Must manually force to upper case here, as this does not go via the handler */
4686         string_set(&Globals.szNetbiosName, myhostname_upper());
4687
4688         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
4689         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
4690
4691         /* use the new 'hash2' method by default, with a prefix of 1 */
4692         string_set(&Globals.szManglingMethod, "hash2");
4693         Globals.mangle_prefix = 1;
4694
4695         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
4696
4697         /* using UTF8 by default allows us to support all chars */
4698         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
4699
4700         /* Use codepage 850 as a default for the dos character set */
4701         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
4702
4703         /*
4704          * Allow the default PASSWD_CHAT to be overridden in local.h.
4705          */
4706         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
4707
4708         string_set(&Globals.szWorkgroup, DEFAULT_WORKGROUP);
4709
4710         string_set(&Globals.szPasswdProgram, "");
4711         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
4712         string_set(&Globals.szStateDir, get_dyn_STATEDIR());
4713         string_set(&Globals.szCacheDir, get_dyn_CACHEDIR());
4714         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
4715         string_set(&Globals.szSocketAddress, "0.0.0.0");
4716         /*
4717          * By default support explicit binding to broadcast
4718          * addresses.
4719          */
4720         Globals.bNmbdBindExplicitBroadcast = true;
4721
4722         if (asprintf(&s, "Samba %s", samba_version_string()) < 0) {
4723                 smb_panic("init_globals: ENOMEM");
4724         }
4725         string_set(&Globals.szServerString, s);
4726         SAFE_FREE(s);
4727 #ifdef DEVELOPER
4728         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
4729 #endif
4730
4731         string_set(&Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
4732
4733         string_set(&Globals.szLogonDrive, "");
4734         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
4735         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
4736         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
4737
4738         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
4739         string_set(&Globals.szPasswordServer, "*");
4740
4741         Globals.AlgorithmicRidBase = BASE_RID;
4742
4743         Globals.bLoadPrinters = true;
4744         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
4745
4746         Globals.ConfigBackend = config_backend;
4747         Globals.ServerRole = ROLE_AUTO;
4748
4749         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
4750         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
4751         Globals.max_xmit = 0x4104;
4752         Globals.max_mux = 50;   /* This is *needed* for profile support. */
4753         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
4754         Globals.bDisableSpoolss = false;
4755         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
4756         Globals.pwordlevel = 0;
4757         Globals.unamelevel = 0;
4758         Globals.deadtime = 0;
4759         Globals.getwd_cache = true;
4760         Globals.bLargeReadwrite = true;
4761         Globals.max_log_size = 5000;
4762         Globals.max_open_files = max_open_files();
4763         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
4764         Globals.srv_maxprotocol = PROTOCOL_SMB2_10;
4765         Globals.srv_minprotocol = PROTOCOL_LANMAN1;
4766         Globals.security = SEC_USER;
4767         Globals.paranoid_server_security = true;
4768         Globals.bEncryptPasswords = true;
4769         Globals.clientSchannel = Auto;
4770         Globals.serverSchannel = Auto;
4771         Globals.bReadRaw = true;
4772         Globals.bWriteRaw = true;
4773         Globals.bNullPasswords = false;
4774         Globals.bObeyPamRestrictions = false;
4775         Globals.syslog = 1;
4776         Globals.bSyslogOnly = false;
4777         Globals.bTimestampLogs = true;
4778         string_set(&Globals.szLogLevel, "0");
4779         Globals.bDebugPrefixTimestamp = false;
4780         Globals.bDebugHiresTimestamp = true;
4781         Globals.bDebugPid = false;
4782         Globals.bDebugUid = false;
4783         Globals.bDebugClass = false;
4784         Globals.bEnableCoreFiles = true;
4785         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
4786         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
4787         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
4788         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
4789         Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
4790         Globals.lm_interval = 60;
4791 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
4792         Globals.bNISHomeMap = false;
4793 #ifdef WITH_NISPLUS_HOME
4794         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
4795 #else
4796         string_set(&Globals.szNISHomeMapName, "auto.home");
4797 #endif
4798 #endif
4799         Globals.bTimeServer = false;
4800         Globals.bBindInterfacesOnly = false;
4801         Globals.bUnixPasswdSync = false;
4802         Globals.bPamPasswordChange = false;
4803         Globals.bPasswdChatDebug = false;
4804         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
4805         Globals.bNTPipeSupport = true;  /* Do NT pipes by default. */
4806         Globals.bNTStatusSupport = true; /* Use NT status by default. */
4807         Globals.bStatCache = true;      /* use stat cache by default */
4808         Globals.iMaxStatCacheSize = 256; /* 256k by default */
4809         Globals.restrict_anonymous = 0;
4810         Globals.bClientLanManAuth = false;      /* Do NOT use the LanMan hash if it is available */
4811         Globals.bClientPlaintextAuth = false;   /* Do NOT use a plaintext password even if is requested by the server */
4812         Globals.bLanmanAuth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
4813         Globals.bNTLMAuth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
4814         Globals.bClientNTLMv2Auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
4815         /* Note, that we will also use NTLM2 session security (which is different), if it is available */
4816
4817         Globals.map_to_guest = 0;       /* By Default, "Never" */
4818         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
4819         Globals.enhanced_browsing = true;
4820         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
4821 #ifdef MMAP_BLACKLIST
4822         Globals.bUseMmap = false;
4823 #else
4824         Globals.bUseMmap = true;
4825 #endif
4826         Globals.bUnixExtensions = true;
4827         Globals.bResetOnZeroVC = false;
4828         Globals.bLogWriteableFilesOnExit = false;
4829         Globals.bCreateKrb5Conf = true;
4830         Globals.winbindMaxDomainConnections = 1;
4831
4832         /* hostname lookups can be very expensive and are broken on
4833            a large number of sites (tridge) */
4834         Globals.bHostnameLookups = false;
4835
4836         string_set(&Globals.passdb_backend, "tdbsam");
4837         string_set(&Globals.szLdapSuffix, "");
4838         string_set(&Globals.szLdapMachineSuffix, "");
4839         string_set(&Globals.szLdapUserSuffix, "");
4840         string_set(&Globals.szLdapGroupSuffix, "");
4841         string_set(&Globals.szLdapIdmapSuffix, "");
4842
4843         string_set(&Globals.szLdapAdminDn, "");
4844         Globals.ldap_ssl = LDAP_SSL_START_TLS;
4845         Globals.ldap_ssl_ads = false;
4846         Globals.ldap_deref = -1;
4847         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
4848         Globals.ldap_delete_dn = false;
4849         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
4850         Globals.ldap_follow_referral = Auto;
4851         Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
4852         Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
4853         Globals.ldap_page_size = LDAP_PAGE_SIZE;
4854
4855         Globals.ldap_debug_level = 0;
4856         Globals.ldap_debug_threshold = 10;
4857
4858         /* This is what we tell the afs client. in reality we set the token 
4859          * to never expire, though, when this runs out the afs client will 
4860          * forget the token. Set to 0 to get NEVERDATE.*/
4861         Globals.iAfsTokenLifetime = 604800;
4862         Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
4863
4864 /* these parameters are set to defaults that are more appropriate
4865    for the increasing samba install base:
4866
4867    as a member of the workgroup, that will possibly become a
4868    _local_ master browser (lm = true).  this is opposed to a forced
4869    local master browser startup (pm = true).
4870
4871    doesn't provide WINS server service by default (wsupp = false),
4872    and doesn't provide domain master browser services by default, either.
4873
4874 */
4875
4876         Globals.bMsAddPrinterWizard = true;
4877         Globals.os_level = 20;
4878         Globals.bLocalMaster = true;
4879         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
4880         Globals.bDomainLogons = false;
4881         Globals.bBrowseList = true;
4882         Globals.bWINSsupport = false;
4883         Globals.bWINSproxy = false;
4884
4885         TALLOC_FREE(Globals.szInitLogonDelayedHosts);
4886         Globals.InitLogonDelay = 100; /* 100 ms default delay */
4887
4888         Globals.bWINSdnsProxy = true;
4889
4890         Globals.bAllowTrustedDomains = true;
4891         string_set(&Globals.szIdmapBackend, "tdb");
4892
4893         string_set(&Globals.szTemplateShell, "/bin/false");
4894         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
4895         string_set(&Globals.szWinbindSeparator, "\\");
4896
4897         string_set(&Globals.szCupsServer, "");
4898         string_set(&Globals.szIPrintServer, "");
4899
4900         string_set(&Globals.ctdbdSocket, "");
4901         Globals.szClusterAddresses = NULL;
4902         Globals.clustering = false;
4903         Globals.ctdb_timeout = 0;
4904         Globals.ctdb_locktime_warn_threshold = 0;
4905
4906         Globals.winbind_cache_time = 300;       /* 5 minutes */
4907         Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
4908         Globals.winbind_max_clients = 200;
4909         Globals.bWinbindEnumUsers = false;
4910         Globals.bWinbindEnumGroups = false;
4911         Globals.bWinbindUseDefaultDomain = false;
4912         Globals.bWinbindTrustedDomainsOnly = false;
4913         Globals.bWinbindNestedGroups = true;
4914         Globals.winbind_expand_groups = 1;
4915         Globals.szWinbindNssInfo = (const char **)str_list_make_v3(NULL, "template", NULL);
4916         Globals.bWinbindRefreshTickets = false;
4917         Globals.bWinbindOfflineLogon = false;
4918
4919         Globals.iIdmapCacheTime = 86400 * 7; /* a week by default */
4920         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
4921
4922         Globals.bPassdbExpandExplicit = false;
4923
4924         Globals.name_cache_timeout = 660; /* In seconds */
4925
4926         Globals.bUseSpnego = true;
4927         Globals.bClientUseSpnego = true;
4928
4929         Globals.client_signing = SMB_SIGNING_DEFAULT;
4930         Globals.server_signing = SMB_SIGNING_DEFAULT;
4931
4932         Globals.bDeferSharingViolations = true;
4933         string_set(&Globals.smb_ports, SMB_PORTS);
4934
4935         Globals.bEnablePrivileges = true;
4936         Globals.bHostMSDfs        = true;
4937         Globals.bASUSupport       = false;
4938
4939         /* User defined shares. */
4940         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
4941                 smb_panic("init_globals: ENOMEM");
4942         }
4943         string_set(&Globals.szUsersharePath, s);
4944         SAFE_FREE(s);
4945         string_set(&Globals.szUsershareTemplateShare, "");
4946         Globals.iUsershareMaxShares = 0;
4947         /* By default disallow sharing of directories not owned by the sharer. */
4948         Globals.bUsershareOwnerOnly = true;
4949         /* By default disallow guest access to usershares. */
4950         Globals.bUsershareAllowGuests = false;
4951
4952         Globals.iKeepalive = DEFAULT_KEEPALIVE;
4953
4954         /* By default no shares out of the registry */
4955         Globals.bRegistryShares = false;
4956
4957         Globals.iminreceivefile = 0;
4958
4959         Globals.bMapUntrustedToDomain = false;
4960         Globals.bMulticastDnsRegister = true;
4961
4962         Globals.ismb2_max_read = DEFAULT_SMB2_MAX_READ;
4963         Globals.ismb2_max_write = DEFAULT_SMB2_MAX_WRITE;
4964         Globals.ismb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
4965         Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
4966
4967         string_set(&Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
4968
4969         /* Now put back the settings that were set with lp_set_cmdline() */
4970         apply_lp_set_cmdline();
4971 }
4972
4973 /*******************************************************************
4974  Convenience routine to grab string parameters into temporary memory
4975  and run standard_sub_basic on them. The buffers can be written to by
4976  callers without affecting the source string.
4977 ********************************************************************/
4978
4979 static char *lp_string(const char *s)
4980 {
4981         char *ret;
4982         TALLOC_CTX *ctx = talloc_tos();
4983
4984         /* The follow debug is useful for tracking down memory problems
4985            especially if you have an inner loop that is calling a lp_*()
4986            function that returns a string.  Perhaps this debug should be
4987            present all the time? */
4988
4989 #if 0
4990         DEBUG(10, ("lp_string(%s)\n", s));
4991 #endif
4992         if (!s) {
4993                 return NULL;
4994         }
4995
4996         ret = talloc_sub_basic(ctx,
4997                         get_current_username(),
4998                         current_user_info.domain,
4999                         s);
5000         if (trim_char(ret, '\"', '\"')) {
5001                 if (strchr(ret,'\"') != NULL) {
5002                         TALLOC_FREE(ret);
5003                         ret = talloc_sub_basic(ctx,
5004                                         get_current_username(),
5005                                         current_user_info.domain,
5006                                         s);
5007                 }
5008         }
5009         return ret;
5010 }
5011
5012 /*
5013    In this section all the functions that are used to access the
5014    parameters from the rest of the program are defined
5015 */
5016
5017 #define FN_GLOBAL_STRING(fn_name,ptr) \
5018  char *lp_ ## fn_name(void) {return(lp_string(*(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
5019 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
5020  const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
5021 #define FN_GLOBAL_LIST(fn_name,ptr) \
5022  const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
5023 #define FN_GLOBAL_BOOL(fn_name,ptr) \
5024  bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
5025 #define FN_GLOBAL_CHAR(fn_name,ptr) \
5026  char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
5027 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
5028  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
5029
5030 #define FN_LOCAL_STRING(fn_name,val) \
5031  char *lp_ ## fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
5032 #define FN_LOCAL_CONST_STRING(fn_name,val) \
5033  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
5034 #define FN_LOCAL_LIST(fn_name,val) \
5035  const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5036 #define FN_LOCAL_BOOL(fn_name,val) \
5037  bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5038 #define FN_LOCAL_INTEGER(fn_name,val) \
5039  int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
5040
5041 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
5042  bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5043 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
5044  int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5045 #define FN_LOCAL_CHAR(fn_name,val) \
5046  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
5047
5048
5049 static FN_GLOBAL_BOOL(domain_logons, bDomainLogons)
5050 static FN_GLOBAL_BOOL(_readraw, bReadRaw)
5051 static FN_GLOBAL_BOOL(time_server, bTimeServer)
5052 static FN_GLOBAL_BOOL(_writeraw, bWriteRaw)
5053 static FN_GLOBAL_CONST_STRING(_ctdbd_socket, ctdbdSocket)
5054 static FN_GLOBAL_INTEGER(_server_role, ServerRole)
5055
5056 /* If lp_statedir() and lp_cachedir() are explicitely set during the
5057  * build process or in smb.conf, we use that value.  Otherwise they
5058  * default to the value of lp_lockdir(). */
5059 const char *lp_statedir(void) {
5060         if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
5061             (strcmp(get_dyn_STATEDIR(), Globals.szStateDir) != 0))
5062                 return(*(char **)(&Globals.szStateDir) ?
5063                        *(char **)(&Globals.szStateDir) : "");
5064         else
5065                 return(*(char **)(&Globals.szLockDir) ?
5066                        *(char **)(&Globals.szLockDir) : "");
5067 }
5068 const char *lp_cachedir(void) {
5069         if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
5070             (strcmp(get_dyn_CACHEDIR(), Globals.szCacheDir) != 0))
5071                 return(*(char **)(&Globals.szCacheDir) ?
5072                        *(char **)(&Globals.szCacheDir) : "");
5073         else
5074                 return(*(char **)(&Globals.szLockDir) ?
5075                        *(char **)(&Globals.szLockDir) : "");
5076 }
5077 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
5078                   winbindMaxDomainConnections)
5079
5080 int lp_winbind_max_domain_connections(void)
5081 {
5082         if (lp_winbind_offline_logon() &&
5083             lp_winbind_max_domain_connections_int() > 1) {
5084                 DEBUG(1, ("offline logons active, restricting max domain "
5085                           "connections to 1\n"));
5086                 return 1;
5087         }
5088         return MAX(1, lp_winbind_max_domain_connections_int());
5089 }
5090
5091 int lp_smb2_max_credits(void)
5092 {
5093         if (Globals.ismb2_max_credits == 0) {
5094                 Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
5095         }
5096         return Globals.ismb2_max_credits;
5097 }
5098 int lp_cups_encrypt(void)
5099 {
5100         int result = 0;
5101 #ifdef HAVE_HTTPCONNECTENCRYPT
5102         switch (Globals.CupsEncrypt) {
5103                 case Auto:
5104                         result = HTTP_ENCRYPT_REQUIRED;
5105                         break;
5106                 case true:
5107                         result = HTTP_ENCRYPT_ALWAYS;
5108                         break;
5109                 case false:
5110                         result = HTTP_ENCRYPT_NEVER;
5111                         break;
5112         }
5113 #endif
5114         return result;
5115 }
5116
5117 /* These functions remain in source3/param for now */
5118
5119 FN_GLOBAL_CONST_STRING(name_resolve_order, szNameResolveOrder)
5120 FN_GLOBAL_CONST_STRING(smb_ports, smb_ports)
5121 FN_GLOBAL_INTEGER(security, security)
5122 FN_GLOBAL_INTEGER(usershare_max_shares, iUsershareMaxShares)
5123 FN_GLOBAL_STRING(configfile, szConfigFile)
5124
5125 #include "lib/param/param_functions.c"
5126
5127 FN_LOCAL_STRING(servicename, szService)
5128 FN_LOCAL_CONST_STRING(const_servicename, szService)
5129
5130 /* local prototypes */
5131
5132 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5133 static const char *get_boolean(bool bool_value);
5134 static int getservicebyname(const char *pszServiceName,
5135                             struct loadparm_service *pserviceDest);
5136 static void copy_service(struct loadparm_service *pserviceDest,
5137                          struct loadparm_service *pserviceSource,
5138                          struct bitmap *pcopymapDest);
5139 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5140                          void *userdata);
5141 static bool do_section(const char *pszSectionName, void *userdata);
5142 static void init_copymap(struct loadparm_service *pservice);
5143 static bool hash_a_service(const char *name, int number);
5144 static void free_service_byindex(int iService);
5145 static void show_parameter(int parmIndex);
5146 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5147
5148 /*
5149  * This is a helper function for parametrical options support.  It returns a
5150  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5151  * parametrical functions are quite simple
5152  */
5153 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
5154                                                            const char *option)
5155 {
5156         bool global_section = false;
5157         char* param_key;
5158         struct parmlist_entry *data;
5159
5160         if (service == NULL) {
5161                 data = Globals.param_opt;
5162                 global_section = true;
5163         } else {
5164                 data = service->param_opt;
5165         }
5166
5167         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
5168                 DEBUG(0,("asprintf failed!\n"));
5169                 return NULL;
5170         }
5171
5172         while (data) {
5173                 if (strwicmp(data->key, param_key) == 0) {
5174                         string_free(&param_key);
5175                         return data;
5176                 }
5177                 data = data->next;
5178         }
5179
5180         if (!global_section) {
5181                 /* Try to fetch the same option but from globals */
5182                 /* but only if we are not already working with Globals */
5183                 data = Globals.param_opt;
5184                 while (data) {
5185                         if (strwicmp(data->key, param_key) == 0) {
5186                                 string_free(&param_key);
5187                                 return data;
5188                         }
5189                         data = data->next;
5190                 }
5191         }
5192
5193         string_free(&param_key);
5194
5195         return NULL;
5196 }
5197
5198 /*
5199  * This is a helper function for parametrical options support.  It returns a
5200  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5201  * parametrical functions are quite simple
5202  */
5203 static struct parmlist_entry *get_parametrics(int snum, const char *type,
5204                                                 const char *option)
5205 {
5206         if (snum >= iNumServices) return NULL;
5207
5208         if (snum < 0) {
5209                 return get_parametrics_by_service(NULL, type, option);
5210         } else {
5211                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
5212         }
5213 }
5214
5215
5216 #define MISSING_PARAMETER(name) \
5217     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5218
5219 /*******************************************************************
5220 convenience routine to return int parameters.
5221 ********************************************************************/
5222 static int lp_int(const char *s)
5223 {
5224
5225         if (!s || !*s) {
5226                 MISSING_PARAMETER(lp_int);
5227                 return (-1);
5228         }
5229
5230         return (int)strtol(s, NULL, 0);
5231 }
5232
5233 /*******************************************************************
5234 convenience routine to return unsigned long parameters.
5235 ********************************************************************/
5236 static unsigned long lp_ulong(const char *s)
5237 {
5238
5239         if (!s || !*s) {
5240                 MISSING_PARAMETER(lp_ulong);
5241                 return (0);
5242         }
5243
5244         return strtoul(s, NULL, 0);
5245 }
5246
5247 /*******************************************************************
5248 convenience routine to return boolean parameters.
5249 ********************************************************************/
5250 static bool lp_bool(const char *s)
5251 {
5252         bool ret = false;
5253
5254         if (!s || !*s) {
5255                 MISSING_PARAMETER(lp_bool);
5256                 return false;
5257         }
5258
5259         if (!set_boolean(s, &ret)) {
5260                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5261                 return false;
5262         }
5263
5264         return ret;
5265 }
5266
5267 /*******************************************************************
5268 convenience routine to return enum parameters.
5269 ********************************************************************/
5270 static int lp_enum(const char *s,const struct enum_list *_enum)
5271 {
5272         int i;
5273
5274         if (!s || !*s || !_enum) {
5275                 MISSING_PARAMETER(lp_enum);
5276                 return (-1);
5277         }
5278
5279         for (i=0; _enum[i].name; i++) {
5280                 if (strequal(_enum[i].name,s))
5281                         return _enum[i].value;
5282         }
5283
5284         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5285         return (-1);
5286 }
5287
5288 #undef MISSING_PARAMETER
5289
5290 /* Return parametric option from a given service. Type is a part of option before ':' */
5291 /* Parametric option has following syntax: 'Type: option = value' */
5292 /* the returned value is talloced on the talloc_tos() */
5293 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
5294 {
5295         struct parmlist_entry *data = get_parametrics(snum, type, option);
5296
5297         if (data == NULL||data->value==NULL) {
5298                 if (def) {
5299                         return lp_string(def);
5300                 } else {
5301                         return NULL;
5302                 }
5303         }
5304
5305         return lp_string(data->value);
5306 }
5307
5308 /* Return parametric option from a given service. Type is a part of option before ':' */
5309 /* Parametric option has following syntax: 'Type: option = value' */
5310 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5311 {
5312         struct parmlist_entry *data = get_parametrics(snum, type, option);
5313
5314         if (data == NULL||data->value==NULL)
5315                 return def;
5316
5317         return data->value;
5318 }
5319
5320 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
5321 {
5322         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
5323
5324         if (data == NULL||data->value==NULL)
5325                 return NULL;
5326
5327         return data->value;
5328 }
5329
5330
5331 /* Return parametric option from a given service. Type is a part of option before ':' */
5332 /* Parametric option has following syntax: 'Type: option = value' */
5333
5334 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5335 {
5336         struct parmlist_entry *data = get_parametrics(snum, type, option);
5337
5338         if (data == NULL||data->value==NULL)
5339                 return (const char **)def;
5340
5341         if (data->list==NULL) {
5342                 data->list = str_list_make_v3(NULL, data->value, NULL);
5343         }
5344
5345         return (const char **)data->list;
5346 }
5347
5348 /* Return parametric option from a given service. Type is a part of option before ':' */
5349 /* Parametric option has following syntax: 'Type: option = value' */
5350
5351 int lp_parm_int(int snum, const char *type, const char *option, int def)
5352 {
5353         struct parmlist_entry *data = get_parametrics(snum, type, option);
5354
5355         if (data && data->value && *data->value)
5356                 return lp_int(data->value);
5357
5358         return def;
5359 }
5360
5361 /* Return parametric option from a given service. Type is a part of option before ':' */
5362 /* Parametric option has following syntax: 'Type: option = value' */
5363
5364 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5365 {
5366         struct parmlist_entry *data = get_parametrics(snum, type, option);
5367
5368         if (data && data->value && *data->value)
5369                 return lp_ulong(data->value);
5370
5371         return def;
5372 }
5373
5374 /* Return parametric option from a given service. Type is a part of option before ':' */
5375 /* Parametric option has following syntax: 'Type: option = value' */
5376
5377 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5378 {
5379         struct parmlist_entry *data = get_parametrics(snum, type, option);
5380
5381         if (data && data->value && *data->value)
5382                 return lp_bool(data->value);
5383
5384         return def;
5385 }
5386
5387 /* Return parametric option from a given service. Type is a part of option before ':' */
5388 /* Parametric option has following syntax: 'Type: option = value' */
5389
5390 int lp_parm_enum(int snum, const char *type, const char *option,
5391                  const struct enum_list *_enum, int def)
5392 {
5393         struct parmlist_entry *data = get_parametrics(snum, type, option);
5394
5395         if (data && data->value && *data->value && _enum)
5396                 return lp_enum(data->value, _enum);
5397
5398         return def;
5399 }
5400
5401
5402 /***************************************************************************
5403  Initialise a service to the defaults.
5404 ***************************************************************************/
5405
5406 static void init_service(struct loadparm_service *pservice)
5407 {
5408         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
5409         copy_service(pservice, &sDefault, NULL);
5410 }
5411
5412
5413 /**
5414  * free a param_opts structure.
5415  * param_opts handling should be moved to talloc;
5416  * then this whole functions reduces to a TALLOC_FREE().
5417  */
5418
5419 static void free_param_opts(struct parmlist_entry **popts)
5420 {
5421         struct parmlist_entry *opt, *next_opt;
5422
5423         if (popts == NULL) {
5424                 return;
5425         }
5426
5427         if (*popts != NULL) {
5428                 DEBUG(5, ("Freeing parametrics:\n"));
5429         }
5430         opt = *popts;
5431         while (opt != NULL) {
5432                 string_free(&opt->key);
5433                 string_free(&opt->value);
5434                 TALLOC_FREE(opt->list);
5435                 next_opt = opt->next;
5436                 SAFE_FREE(opt);
5437                 opt = next_opt;
5438         }
5439         *popts = NULL;
5440 }
5441
5442 /***************************************************************************
5443  Free the dynamically allocated parts of a service struct.
5444 ***************************************************************************/
5445
5446 static void free_service(struct loadparm_service *pservice)
5447 {
5448         if (!pservice)
5449                 return;
5450
5451         if (pservice->szService)
5452                 DEBUG(5, ("free_service: Freeing service %s\n",
5453                        pservice->szService));
5454
5455         free_parameters(pservice);
5456
5457         string_free(&pservice->szService);
5458         TALLOC_FREE(pservice->copymap);
5459
5460         free_param_opts(&pservice->param_opt);
5461
5462         ZERO_STRUCTP(pservice);
5463 }
5464
5465
5466 /***************************************************************************
5467  remove a service indexed in the ServicePtrs array from the ServiceHash
5468  and free the dynamically allocated parts
5469 ***************************************************************************/
5470
5471 static void free_service_byindex(int idx)
5472 {
5473         if ( !LP_SNUM_OK(idx) ) 
5474                 return;
5475
5476         ServicePtrs[idx]->valid = false;
5477         invalid_services[num_invalid_services++] = idx;
5478
5479         /* we have to cleanup the hash record */
5480
5481         if (ServicePtrs[idx]->szService) {
5482                 char *canon_name = canonicalize_servicename(
5483                         talloc_tos(),
5484                         ServicePtrs[idx]->szService );
5485
5486                 dbwrap_delete_bystring(ServiceHash, canon_name );
5487                 TALLOC_FREE(canon_name);
5488         }
5489
5490         free_service(ServicePtrs[idx]);
5491 }
5492
5493 /***************************************************************************
5494  Add a new service to the services array initialising it with the given 
5495  service. 
5496 ***************************************************************************/
5497
5498 static int add_a_service(const struct loadparm_service *pservice, const char *name)
5499 {
5500         int i;
5501         struct loadparm_service tservice;
5502         int num_to_alloc = iNumServices + 1;
5503
5504         tservice = *pservice;
5505
5506         /* it might already exist */
5507         if (name) {
5508                 i = getservicebyname(name, NULL);
5509                 if (i >= 0) {
5510                         return (i);
5511                 }
5512         }
5513
5514         /* find an invalid one */
5515         i = iNumServices;
5516         if (num_invalid_services > 0) {
5517                 i = invalid_services[--num_invalid_services];
5518         }
5519
5520         /* if not, then create one */
5521         if (i == iNumServices) {
5522                 struct loadparm_service **tsp;
5523                 int *tinvalid;
5524
5525                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
5526                 if (tsp == NULL) {
5527                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5528                         return (-1);
5529                 }
5530                 ServicePtrs = tsp;
5531                 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
5532                 if (!ServicePtrs[iNumServices]) {
5533                         DEBUG(0,("add_a_service: out of memory!\n"));
5534                         return (-1);
5535                 }
5536                 iNumServices++;
5537
5538                 /* enlarge invalid_services here for now... */
5539                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5540                                              num_to_alloc);
5541                 if (tinvalid == NULL) {
5542                         DEBUG(0,("add_a_service: failed to enlarge "
5543                                  "invalid_services!\n"));
5544                         return (-1);
5545                 }
5546                 invalid_services = tinvalid;
5547         } else {
5548                 free_service_byindex(i);
5549         }
5550
5551         ServicePtrs[i]->valid = true;
5552
5553         init_service(ServicePtrs[i]);
5554         copy_service(ServicePtrs[i], &tservice, NULL);
5555         if (name)
5556                 string_set(&ServicePtrs[i]->szService, name);
5557
5558         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
5559                 i, ServicePtrs[i]->szService));
5560
5561         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5562                 return (-1);
5563         }
5564
5565         return (i);
5566 }
5567
5568 /***************************************************************************
5569   Convert a string to uppercase and remove whitespaces.
5570 ***************************************************************************/
5571
5572 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
5573 {
5574         char *result;
5575
5576         if ( !src ) {
5577                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5578                 return NULL;
5579         }
5580
5581         result = talloc_strdup(ctx, src);
5582         SMB_ASSERT(result != NULL);
5583
5584         strlower_m(result);
5585         return result;
5586 }
5587
5588 /***************************************************************************
5589   Add a name/index pair for the services array to the hash table.
5590 ***************************************************************************/
5591
5592 static bool hash_a_service(const char *name, int idx)
5593 {
5594         char *canon_name;
5595
5596         if ( !ServiceHash ) {
5597                 DEBUG(10,("hash_a_service: creating servicehash\n"));
5598                 ServiceHash = db_open_rbt(NULL);
5599                 if ( !ServiceHash ) {
5600                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5601                         return false;
5602                 }
5603         }
5604
5605         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5606                 idx, name));
5607
5608         canon_name = canonicalize_servicename(talloc_tos(), name );
5609
5610         dbwrap_store_bystring(ServiceHash, canon_name,
5611                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
5612                               TDB_REPLACE);
5613
5614         TALLOC_FREE(canon_name);
5615
5616         return true;
5617 }
5618
5619 /***************************************************************************
5620  Add a new home service, with the specified home directory, defaults coming
5621  from service ifrom.
5622 ***************************************************************************/
5623
5624 bool lp_add_home(const char *pszHomename, int iDefaultService,
5625                  const char *user, const char *pszHomedir)
5626 {
5627         int i;
5628
5629         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
5630                         pszHomedir[0] == '\0') {
5631                 return false;
5632         }
5633
5634         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5635
5636         if (i < 0)
5637                 return false;
5638
5639         if (!(*(ServicePtrs[iDefaultService]->szPath))
5640             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
5641                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5642         }
5643
5644         if (!(*(ServicePtrs[i]->comment))) {
5645                 char *comment = NULL;
5646                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5647                         return false;
5648                 }
5649                 string_set(&ServicePtrs[i]->comment, comment);
5650                 SAFE_FREE(comment);
5651         }
5652
5653         /* set the browseable flag from the global default */
5654
5655         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5656         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
5657
5658         ServicePtrs[i]->autoloaded = true;
5659
5660         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
5661                user, ServicePtrs[i]->szPath ));
5662
5663         return true;
5664 }
5665
5666 /***************************************************************************
5667  Add a new service, based on an old one.
5668 ***************************************************************************/
5669
5670 int lp_add_service(const char *pszService, int iDefaultService)
5671 {
5672         if (iDefaultService < 0) {
5673                 return add_a_service(&sDefault, pszService);
5674         }
5675
5676         return (add_a_service(ServicePtrs[iDefaultService], pszService));
5677 }
5678
5679 /***************************************************************************
5680  Add the IPC service.
5681 ***************************************************************************/
5682
5683 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5684 {
5685         char *comment = NULL;
5686         int i = add_a_service(&sDefault, ipc_name);
5687
5688         if (i < 0)
5689                 return false;
5690
5691         if (asprintf(&comment, "IPC Service (%s)",
5692                                 Globals.szServerString) < 0) {
5693                 return false;
5694         }
5695
5696         string_set(&ServicePtrs[i]->szPath, tmpdir());
5697         string_set(&ServicePtrs[i]->szUsername, "");
5698         string_set(&ServicePtrs[i]->comment, comment);
5699         string_set(&ServicePtrs[i]->fstype, "IPC");
5700         ServicePtrs[i]->iMaxConnections = 0;
5701         ServicePtrs[i]->bAvailable = true;
5702         ServicePtrs[i]->bRead_only = true;
5703         ServicePtrs[i]->bGuest_only = false;
5704         ServicePtrs[i]->bAdministrative_share = true;
5705         ServicePtrs[i]->bGuest_ok = guest_ok;
5706         ServicePtrs[i]->bPrint_ok = false;
5707         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5708
5709         DEBUG(3, ("adding IPC service\n"));
5710
5711         SAFE_FREE(comment);
5712         return true;
5713 }
5714
5715 /***************************************************************************
5716  Add a new printer service, with defaults coming from service iFrom.
5717 ***************************************************************************/
5718
5719 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
5720 {
5721         const char *comment = "From Printcap";
5722         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
5723
5724         if (i < 0)
5725                 return false;
5726
5727         /* note that we do NOT default the availability flag to true - */
5728         /* we take it from the default service passed. This allows all */
5729         /* dynamic printers to be disabled by disabling the [printers] */
5730         /* entry (if/when the 'available' keyword is implemented!).    */
5731
5732         /* the printer name is set to the service name. */
5733         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
5734         string_set(&ServicePtrs[i]->comment, comment);
5735
5736         /* set the browseable flag from the gloabl default */
5737         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5738
5739         /* Printers cannot be read_only. */
5740         ServicePtrs[i]->bRead_only = false;
5741         /* No share modes on printer services. */
5742         ServicePtrs[i]->bShareModes = false;
5743         /* No oplocks on printer services. */
5744         ServicePtrs[i]->bOpLocks = false;
5745         /* Printer services must be printable. */
5746         ServicePtrs[i]->bPrint_ok = true;
5747
5748         DEBUG(3, ("adding printer service %s\n", pszPrintername));
5749
5750         return true;
5751 }
5752
5753
5754 /***************************************************************************
5755  Check whether the given parameter name is valid.
5756  Parametric options (names containing a colon) are considered valid.
5757 ***************************************************************************/
5758
5759 bool lp_parameter_is_valid(const char *pszParmName)
5760 {
5761         return ((map_parameter(pszParmName) != -1) ||
5762                 (strchr(pszParmName, ':') != NULL));
5763 }
5764
5765 /***************************************************************************
5766  Check whether the given name is the name of a global parameter.
5767  Returns true for strings belonging to parameters of class
5768  P_GLOBAL, false for all other strings, also for parametric options
5769  and strings not belonging to any option.
5770 ***************************************************************************/
5771
5772 bool lp_parameter_is_global(const char *pszParmName)
5773 {
5774         int num = map_parameter(pszParmName);
5775
5776         if (num >= 0) {
5777                 return (parm_table[num].p_class == P_GLOBAL);
5778         }
5779
5780         return false;
5781 }
5782
5783 /**************************************************************************
5784  Check whether the given name is the canonical name of a parameter.
5785  Returns false if it is not a valid parameter Name.
5786  For parametric options, true is returned.
5787 **************************************************************************/
5788
5789 bool lp_parameter_is_canonical(const char *parm_name)
5790 {
5791         if (!lp_parameter_is_valid(parm_name)) {
5792                 return false;
5793         }
5794
5795         return (map_parameter(parm_name) ==
5796                 map_parameter_canonical(parm_name, NULL));
5797 }
5798
5799 /**************************************************************************
5800  Determine the canonical name for a parameter.
5801  Indicate when it is an inverse (boolean) synonym instead of a
5802  "usual" synonym.
5803 **************************************************************************/
5804
5805 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
5806                                bool *inverse)
5807 {
5808         int num;
5809
5810         if (!lp_parameter_is_valid(parm_name)) {
5811                 *canon_parm = NULL;
5812                 return false;
5813         }
5814
5815         num = map_parameter_canonical(parm_name, inverse);
5816         if (num < 0) {
5817                 /* parametric option */
5818                 *canon_parm = parm_name;
5819         } else {
5820                 *canon_parm = parm_table[num].label;
5821         }
5822
5823         return true;
5824
5825 }
5826
5827 /**************************************************************************
5828  Determine the canonical name for a parameter.
5829  Turn the value given into the inverse boolean expression when
5830  the synonym is an invers boolean synonym.
5831
5832  Return true if parm_name is a valid parameter name and
5833  in case it is an invers boolean synonym, if the val string could
5834  successfully be converted to the reverse bool.
5835  Return false in all other cases.
5836 **************************************************************************/
5837
5838 bool lp_canonicalize_parameter_with_value(const char *parm_name,
5839                                           const char *val,
5840                                           const char **canon_parm,
5841                                           const char **canon_val)
5842 {
5843         int num;
5844         bool inverse;
5845
5846         if (!lp_parameter_is_valid(parm_name)) {
5847                 *canon_parm = NULL;
5848                 *canon_val = NULL;
5849                 return false;
5850         }
5851
5852         num = map_parameter_canonical(parm_name, &inverse);
5853         if (num < 0) {
5854                 /* parametric option */
5855                 *canon_parm = parm_name;
5856                 *canon_val = val;
5857         } else {
5858                 *canon_parm = parm_table[num].label;
5859                 if (inverse) {
5860                         if (!lp_invert_boolean(val, canon_val)) {
5861                                 *canon_val = NULL;
5862                                 return false;
5863                         }
5864                 } else {
5865                         *canon_val = val;
5866                 }
5867         }
5868
5869         return true;
5870 }
5871
5872 /***************************************************************************
5873  Map a parameter's string representation to something we can use. 
5874  Returns false if the parameter string is not recognised, else TRUE.
5875 ***************************************************************************/
5876
5877 static int map_parameter(const char *pszParmName)
5878 {
5879         int iIndex;
5880
5881         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
5882                 return (-1);
5883
5884         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
5885                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
5886                         return (iIndex);
5887
5888         /* Warn only if it isn't parametric option */
5889         if (strchr(pszParmName, ':') == NULL)
5890                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
5891         /* We do return 'fail' for parametric options as well because they are
5892            stored in different storage
5893          */
5894         return (-1);
5895 }
5896
5897 /***************************************************************************
5898  Map a parameter's string representation to the index of the canonical
5899  form of the parameter (it might be a synonym).
5900  Returns -1 if the parameter string is not recognised.
5901 ***************************************************************************/
5902
5903 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
5904 {
5905         int parm_num, canon_num;
5906         bool loc_inverse = false;
5907
5908         parm_num = map_parameter(pszParmName);
5909         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
5910                 /* invalid, parametric or no canidate for synonyms ... */
5911                 goto done;
5912         }
5913
5914         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
5915                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
5916                         parm_num = canon_num;
5917                         goto done;
5918                 }
5919         }
5920
5921 done:
5922         if (inverse != NULL) {
5923                 *inverse = loc_inverse;
5924         }
5925         return parm_num;
5926 }
5927
5928 /***************************************************************************
5929  return true if parameter number parm1 is a synonym of parameter
5930  number parm2 (parm2 being the principal name).
5931  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
5932  false otherwise.
5933 ***************************************************************************/
5934
5935 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
5936 {
5937         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
5938             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
5939             (parm_table[parm1].flags & FLAG_HIDE) &&
5940             !(parm_table[parm2].flags & FLAG_HIDE))
5941         {
5942                 if (inverse != NULL) {
5943                         if ((parm_table[parm1].type == P_BOOLREV) &&
5944                             (parm_table[parm2].type == P_BOOL))
5945                         {
5946                                 *inverse = true;
5947                         } else {
5948                                 *inverse = false;
5949                         }
5950                 }
5951                 return true;
5952         }
5953         return false;
5954 }
5955
5956 /***************************************************************************
5957  Show one parameter's name, type, [values,] and flags.
5958  (helper functions for show_parameter_list)
5959 ***************************************************************************/
5960
5961 static void show_parameter(int parmIndex)
5962 {
5963         int enumIndex, flagIndex;
5964         int parmIndex2;
5965         bool hadFlag;
5966         bool hadSyn;
5967         bool inverse;
5968         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
5969                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
5970                 "P_ENUM", "P_SEP"};
5971         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
5972                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
5973                 FLAG_HIDE};
5974         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
5975                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
5976                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
5977
5978         printf("%s=%s", parm_table[parmIndex].label,
5979                type[parm_table[parmIndex].type]);
5980         if (parm_table[parmIndex].type == P_ENUM) {
5981                 printf(",");
5982                 for (enumIndex=0;
5983                      parm_table[parmIndex].enum_list[enumIndex].name;
5984                      enumIndex++)
5985                 {
5986                         printf("%s%s",
5987                                enumIndex ? "|" : "",
5988                                parm_table[parmIndex].enum_list[enumIndex].name);
5989                 }
5990         }
5991         printf(",");
5992         hadFlag = false;
5993         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
5994                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
5995                         printf("%s%s",
5996                                 hadFlag ? "|" : "",
5997                                 flag_names[flagIndex]);
5998                         hadFlag = true;
5999                 }
6000         }
6001
6002         /* output synonyms */
6003         hadSyn = false;
6004         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6005                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6006                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6007                                parm_table[parmIndex2].label);
6008                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6009                         if (!hadSyn) {
6010                                 printf(" (synonyms: ");
6011                                 hadSyn = true;
6012                         } else {
6013                                 printf(", ");
6014                         }
6015                         printf("%s%s", parm_table[parmIndex2].label,
6016                                inverse ? "[i]" : "");
6017                 }
6018         }
6019         if (hadSyn) {
6020                 printf(")");
6021         }
6022
6023         printf("\n");
6024 }
6025
6026 /***************************************************************************
6027  Show all parameter's name, type, [values,] and flags.
6028 ***************************************************************************/
6029
6030 void show_parameter_list(void)
6031 {
6032         int classIndex, parmIndex;
6033         const char *section_names[] = { "local", "global", NULL};
6034
6035         for (classIndex=0; section_names[classIndex]; classIndex++) {
6036                 printf("[%s]\n", section_names[classIndex]);
6037                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6038                         if (parm_table[parmIndex].p_class == classIndex) {
6039                                 show_parameter(parmIndex);
6040                         }
6041                 }
6042         }
6043 }
6044
6045 /***************************************************************************
6046  Check if a given string correctly represents a boolean value.
6047 ***************************************************************************/
6048
6049 bool lp_string_is_valid_boolean(const char *parm_value)
6050 {
6051         return set_boolean(parm_value, NULL);
6052 }
6053
6054 /***************************************************************************
6055  Get the standard string representation of a boolean value ("yes" or "no")
6056 ***************************************************************************/
6057
6058 static const char *get_boolean(bool bool_value)
6059 {
6060         static const char *yes_str = "yes";
6061         static const char *no_str = "no";
6062
6063         return (bool_value ? yes_str : no_str);
6064 }
6065
6066 /***************************************************************************
6067  Provide the string of the negated boolean value associated to the boolean
6068  given as a string. Returns false if the passed string does not correctly
6069  represent a boolean.
6070 ***************************************************************************/
6071
6072 bool lp_invert_boolean(const char *str, const char **inverse_str)
6073 {
6074         bool val;
6075
6076         if (!set_boolean(str, &val)) {
6077                 return false;
6078         }
6079
6080         *inverse_str = get_boolean(!val);
6081         return true;
6082 }
6083
6084 /***************************************************************************
6085  Provide the canonical string representation of a boolean value given
6086  as a string. Return true on success, false if the string given does
6087  not correctly represent a boolean.
6088 ***************************************************************************/
6089
6090 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6091 {
6092         bool val;
6093
6094         if (!set_boolean(str, &val)) {
6095                 return false;
6096         }
6097
6098         *canon_str = get_boolean(val);
6099         return true;
6100 }
6101
6102 /***************************************************************************
6103 Find a service by name. Otherwise works like get_service.
6104 ***************************************************************************/
6105
6106 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
6107 {
6108         int iService = -1;
6109         char *canon_name;
6110         TDB_DATA data;
6111         NTSTATUS status;
6112
6113         if (ServiceHash == NULL) {
6114                 return -1;
6115         }
6116
6117         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
6118
6119         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
6120                                        &data);
6121
6122         if (NT_STATUS_IS_OK(status) &&
6123             (data.dptr != NULL) &&
6124             (data.dsize == sizeof(iService)))
6125         {
6126                 iService = *(int *)data.dptr;
6127         }
6128
6129         TALLOC_FREE(canon_name);
6130
6131         if ((iService != -1) && (LP_SNUM_OK(iService))
6132             && (pserviceDest != NULL)) {
6133                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6134         }
6135
6136         return (iService);
6137 }
6138
6139 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
6140 struct loadparm_service *lp_service(const char *pszServiceName)
6141 {
6142         int iService = getservicebyname(pszServiceName, NULL);
6143         if (iService == -1 || !LP_SNUM_OK(iService)) {
6144                 return NULL;
6145         }
6146         return ServicePtrs[iService];
6147 }
6148
6149 struct loadparm_service *lp_servicebynum(int snum)
6150 {
6151         if ((snum == -1) || !LP_SNUM_OK(snum)) {
6152                 return NULL;
6153         }
6154         return ServicePtrs[snum];
6155 }
6156
6157 struct loadparm_service *lp_default_loadparm_service()
6158 {
6159         return &sDefault;
6160 }
6161
6162
6163 /***************************************************************************
6164  Copy a service structure to another.
6165  If pcopymapDest is NULL then copy all fields
6166 ***************************************************************************/
6167
6168 /**
6169  * Add a parametric option to a parmlist_entry,
6170  * replacing old value, if already present.
6171  */
6172 static void set_param_opt(struct parmlist_entry **opt_list,
6173                           const char *opt_name,
6174                           const char *opt_value,
6175                           unsigned priority)
6176 {
6177         struct parmlist_entry *new_opt, *opt;
6178         bool not_added;
6179
6180         if (opt_list == NULL) {
6181                 return;
6182         }
6183
6184         opt = *opt_list;
6185         not_added = true;
6186
6187         /* Traverse destination */
6188         while (opt) {
6189                 /* If we already have same option, override it */
6190                 if (strwicmp(opt->key, opt_name) == 0) {
6191                         if ((opt->priority & FLAG_CMDLINE) &&
6192                             !(priority & FLAG_CMDLINE)) {
6193                                 /* it's been marked as not to be
6194                                    overridden */
6195                                 return;
6196                         }
6197                         string_free(&opt->value);
6198                         TALLOC_FREE(opt->list);
6199                         opt->value = SMB_STRDUP(opt_value);
6200                         opt->priority = priority;
6201                         not_added = false;
6202                         break;
6203                 }
6204                 opt = opt->next;
6205         }
6206         if (not_added) {
6207             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
6208             new_opt->key = SMB_STRDUP(opt_name);
6209             new_opt->value = SMB_STRDUP(opt_value);
6210             new_opt->list = NULL;
6211             new_opt->priority = priority;
6212             DLIST_ADD(*opt_list, new_opt);
6213         }
6214 }
6215
6216 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
6217                          struct bitmap *pcopymapDest)
6218 {
6219         int i;
6220         bool bcopyall = (pcopymapDest == NULL);
6221         struct parmlist_entry *data;
6222
6223         for (i = 0; parm_table[i].label; i++)
6224                 if (parm_table[i].p_class == P_LOCAL &&
6225                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6226                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
6227                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
6228
6229                         switch (parm_table[i].type) {
6230                                 case P_BOOL:
6231                                 case P_BOOLREV:
6232                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6233                                         break;
6234
6235                                 case P_INTEGER:
6236                                 case P_ENUM:
6237                                 case P_OCTAL:
6238                                 case P_BYTES:
6239                                         *(int *)dest_ptr = *(int *)src_ptr;
6240                                         break;
6241
6242                                 case P_CHAR:
6243                                         *(char *)dest_ptr = *(char *)src_ptr;
6244                                         break;
6245
6246                                 case P_STRING:
6247                                         string_set((char **)dest_ptr,
6248                                                    *(char **)src_ptr);
6249                                         break;
6250
6251                                 case P_USTRING:
6252                                 {
6253                                         char *upper_string = strupper_talloc(talloc_tos(), 
6254                                                                              *(char **)src_ptr);
6255                                         string_set((char **)dest_ptr,
6256                                                    upper_string);
6257                                         TALLOC_FREE(upper_string);
6258                                         break;
6259                                 }
6260                                 case P_LIST:
6261                                         TALLOC_FREE(*((char ***)dest_ptr));
6262                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6263                                                       *(const char ***)src_ptr);
6264                                         break;
6265                                 default:
6266                                         break;
6267                         }
6268                 }
6269
6270         if (bcopyall) {
6271                 init_copymap(pserviceDest);
6272                 if (pserviceSource->copymap)
6273                         bitmap_copy(pserviceDest->copymap,
6274                                     pserviceSource->copymap);
6275         }
6276
6277         data = pserviceSource->param_opt;
6278         while (data) {
6279                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
6280                 data = data->next;
6281         }
6282 }
6283
6284 /***************************************************************************
6285 Check a service for consistency. Return false if the service is in any way
6286 incomplete or faulty, else true.
6287 ***************************************************************************/
6288
6289 bool service_ok(int iService)
6290 {
6291         bool bRetval;
6292
6293         bRetval = true;
6294         if (ServicePtrs[iService]->szService[0] == '\0') {
6295                 DEBUG(0, ("The following message indicates an internal error:\n"));
6296                 DEBUG(0, ("No service name in service entry.\n"));
6297                 bRetval = false;
6298         }
6299
6300         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6301         /* I can't see why you'd want a non-printable printer service...        */
6302         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6303                 if (!ServicePtrs[iService]->bPrint_ok) {
6304                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6305                                ServicePtrs[iService]->szService));
6306                         ServicePtrs[iService]->bPrint_ok = true;
6307                 }
6308                 /* [printers] service must also be non-browsable. */
6309                 if (ServicePtrs[iService]->bBrowseable)
6310                         ServicePtrs[iService]->bBrowseable = false;
6311         }
6312
6313         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6314             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6315             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6316             ) {
6317                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6318                         ServicePtrs[iService]->szService));
6319                 ServicePtrs[iService]->bAvailable = false;
6320         }
6321
6322         /* If a service is flagged unavailable, log the fact at level 1. */
6323         if (!ServicePtrs[iService]->bAvailable)
6324                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6325                           ServicePtrs[iService]->szService));
6326
6327         return (bRetval);
6328 }
6329
6330 static struct smbconf_ctx *lp_smbconf_ctx(void)
6331 {
6332         sbcErr err;
6333         static struct smbconf_ctx *conf_ctx = NULL;
6334
6335         if (conf_ctx == NULL) {
6336                 err = smbconf_init(NULL, &conf_ctx, "registry:");
6337                 if (!SBC_ERROR_IS_OK(err)) {
6338                         DEBUG(1, ("error initializing registry configuration: "
6339                                   "%s\n", sbcErrorString(err)));
6340                         conf_ctx = NULL;
6341                 }
6342         }
6343
6344         return conf_ctx;
6345 }
6346
6347 static bool process_smbconf_service(struct smbconf_service *service)
6348 {
6349         uint32_t count;
6350         bool ret;
6351
6352         if (service == NULL) {
6353                 return false;
6354         }
6355
6356         ret = do_section(service->name, NULL);
6357         if (ret != true) {
6358                 return false;
6359         }
6360         for (count = 0; count < service->num_params; count++) {
6361                 ret = do_parameter(service->param_names[count],
6362                                    service->param_values[count],
6363                                    NULL);
6364                 if (ret != true) {
6365                         return false;
6366                 }
6367         }
6368         if (iServiceIndex >= 0) {
6369                 return service_ok(iServiceIndex);
6370         }
6371         return true;
6372 }
6373
6374 /**
6375  * load a service from registry and activate it
6376  */
6377 bool process_registry_service(const char *service_name)
6378 {
6379         sbcErr err;
6380         struct smbconf_service *service = NULL;
6381         TALLOC_CTX *mem_ctx = talloc_stackframe();
6382         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6383         bool ret = false;
6384
6385         if (conf_ctx == NULL) {
6386                 goto done;
6387         }
6388
6389         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
6390
6391         if (!smbconf_share_exists(conf_ctx, service_name)) {
6392                 /*
6393                  * Registry does not contain data for this service (yet),
6394                  * but make sure lp_load doesn't return false.
6395                  */
6396                 ret = true;
6397                 goto done;
6398         }
6399
6400         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
6401         if (!SBC_ERROR_IS_OK(err)) {
6402                 goto done;
6403         }
6404
6405         ret = process_smbconf_service(service);
6406         if (!ret) {
6407                 goto done;
6408         }
6409
6410         /* store the csn */
6411         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6412
6413 done:
6414         TALLOC_FREE(mem_ctx);
6415         return ret;
6416 }
6417
6418 /*
6419  * process_registry_globals
6420  */
6421 static bool process_registry_globals(void)
6422 {
6423         bool ret;
6424
6425         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
6426
6427         ret = do_parameter("registry shares", "yes", NULL);
6428         if (!ret) {
6429                 return ret;
6430         }
6431
6432         return process_registry_service(GLOBAL_NAME);
6433 }
6434
6435 bool process_registry_shares(void)
6436 {
6437         sbcErr err;
6438         uint32_t count;
6439         struct smbconf_service **service = NULL;
6440         uint32_t num_shares = 0;
6441         TALLOC_CTX *mem_ctx = talloc_stackframe();
6442         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6443         bool ret = false;
6444
6445         if (conf_ctx == NULL) {
6446                 goto done;
6447         }
6448
6449         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6450         if (!SBC_ERROR_IS_OK(err)) {
6451                 goto done;
6452         }
6453
6454         ret = true;
6455
6456         for (count = 0; count < num_shares; count++) {
6457                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6458                         continue;
6459                 }
6460                 ret = process_smbconf_service(service[count]);
6461                 if (!ret) {
6462                         goto done;
6463                 }
6464         }
6465
6466         /* store the csn */
6467         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6468
6469 done:
6470         TALLOC_FREE(mem_ctx);
6471         return ret;
6472 }
6473
6474 /**
6475  * reload those shares from registry that are already
6476  * activated in the services array.
6477  */
6478 static bool reload_registry_shares(void)
6479 {
6480         int i;
6481         bool ret = true;
6482
6483         for (i = 0; i < iNumServices; i++) {
6484                 if (!VALID(i)) {
6485                         continue;
6486                 }
6487
6488                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
6489                         continue;
6490                 }
6491
6492                 ret = process_registry_service(ServicePtrs[i]->szService);
6493                 if (!ret) {
6494                         goto done;
6495                 }
6496         }
6497
6498 done:
6499         return ret;
6500 }
6501
6502
6503 #define MAX_INCLUDE_DEPTH 100
6504
6505 static uint8_t include_depth;
6506
6507 static struct file_lists {
6508         struct file_lists *next;
6509         char *name;
6510         char *subfname;
6511         time_t modtime;
6512 } *file_lists = NULL;
6513
6514 /*******************************************************************
6515  Keep a linked list of all config files so we know when one has changed 
6516  it's date and needs to be reloaded.
6517 ********************************************************************/
6518
6519 static void add_to_file_list(const char *fname, const char *subfname)
6520 {
6521         struct file_lists *f = file_lists;
6522
6523         while (f) {
6524                 if (f->name && !strcmp(f->name, fname))
6525                         break;
6526                 f = f->next;
6527         }
6528
6529         if (!f) {
6530                 f = SMB_MALLOC_P(struct file_lists);
6531                 if (!f)
6532                         return;
6533                 f->next = file_lists;
6534                 f->name = SMB_STRDUP(fname);
6535                 if (!f->name) {
6536                         SAFE_FREE(f);
6537                         return;
6538                 }
6539                 f->subfname = SMB_STRDUP(subfname);
6540                 if (!f->subfname) {
6541                         SAFE_FREE(f->name);
6542                         SAFE_FREE(f);
6543                         return;
6544                 }
6545                 file_lists = f;
6546                 f->modtime = file_modtime(subfname);
6547         } else {
6548                 time_t t = file_modtime(subfname);
6549                 if (t)
6550                         f->modtime = t;
6551         }
6552         return;
6553 }
6554
6555 /**
6556  * Free the file lists
6557  */
6558 static void free_file_list(void)
6559 {
6560         struct file_lists *f;
6561         struct file_lists *next;
6562
6563         f = file_lists;
6564         while( f ) {
6565                 next = f->next;
6566                 SAFE_FREE( f->name );
6567                 SAFE_FREE( f->subfname );
6568                 SAFE_FREE( f );
6569                 f = next;
6570         }
6571         file_lists = NULL;
6572 }
6573
6574
6575 /**
6576  * Utility function for outsiders to check if we're running on registry.
6577  */
6578 bool lp_config_backend_is_registry(void)
6579 {
6580         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6581 }
6582
6583 /**
6584  * Utility function to check if the config backend is FILE.
6585  */
6586 bool lp_config_backend_is_file(void)
6587 {
6588         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6589 }
6590
6591 /*******************************************************************
6592  Check if a config file has changed date.
6593 ********************************************************************/
6594
6595 bool lp_file_list_changed(void)
6596 {
6597         struct file_lists *f = file_lists;
6598
6599         DEBUG(6, ("lp_file_list_changed()\n"));
6600
6601         while (f) {
6602                 time_t mod_time;
6603
6604                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
6605                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6606
6607                         if (conf_ctx == NULL) {
6608                                 return false;
6609                         }
6610                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
6611                                             NULL))
6612                         {
6613                                 DEBUGADD(6, ("registry config changed\n"));
6614                                 return true;
6615                         }
6616                 } else {
6617                         char *n2 = NULL;
6618                         n2 = talloc_sub_basic(talloc_tos(),
6619                                               get_current_username(),
6620                                               current_user_info.domain,
6621                                               f->name);
6622                         if (!n2) {
6623                                 return false;
6624                         }
6625                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
6626                                      f->name, n2, ctime(&f->modtime)));
6627
6628                         mod_time = file_modtime(n2);
6629
6630                         if (mod_time &&
6631                             ((f->modtime != mod_time) ||
6632                              (f->subfname == NULL) ||
6633                              (strcmp(n2, f->subfname) != 0)))
6634                         {
6635                                 DEBUGADD(6,
6636                                          ("file %s modified: %s\n", n2,
6637                                           ctime(&mod_time)));
6638                                 f->modtime = mod_time;
6639                                 SAFE_FREE(f->subfname);
6640                                 f->subfname = SMB_STRDUP(n2);
6641                                 TALLOC_FREE(n2);
6642                                 return true;
6643                         }
6644                         TALLOC_FREE(n2);
6645                 }
6646                 f = f->next;
6647         }
6648         return false;
6649 }
6650
6651
6652 /**
6653  * Initialize iconv conversion descriptors.
6654  *
6655  * This is called the first time it is needed, and also called again
6656  * every time the configuration is reloaded, because the charset or
6657  * codepage might have changed.
6658  **/
6659 static void init_iconv(void)
6660 {
6661         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
6662                                                       lp_unix_charset(),
6663                                                       true, global_iconv_handle);
6664 }
6665
6666 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6667 {
6668         if (strcmp(*ptr, pszParmValue) != 0) {
6669                 string_set(ptr, pszParmValue);
6670                 init_iconv();
6671         }
6672         return true;
6673 }
6674
6675 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6676 {
6677         bool is_utf8 = false;
6678         size_t len = strlen(pszParmValue);
6679
6680         if (len == 4 || len == 5) {
6681                 /* Don't use StrCaseCmp here as we don't want to
6682                    initialize iconv. */
6683                 if ((toupper_m(pszParmValue[0]) == 'U') &&
6684                     (toupper_m(pszParmValue[1]) == 'T') &&
6685                     (toupper_m(pszParmValue[2]) == 'F')) {
6686                         if (len == 4) {
6687                                 if (pszParmValue[3] == '8') {
6688                                         is_utf8 = true;
6689                                 }
6690                         } else {
6691                                 if (pszParmValue[3] == '-' &&
6692                                     pszParmValue[4] == '8') {
6693                                         is_utf8 = true;
6694                                 }
6695                         }
6696                 }
6697         }
6698
6699         if (strcmp(*ptr, pszParmValue) != 0) {
6700                 if (is_utf8) {
6701                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
6702                                 "be UTF8, using (default value) %s instead.\n",
6703                                 DEFAULT_DOS_CHARSET));
6704                         pszParmValue = DEFAULT_DOS_CHARSET;
6705                 }
6706                 string_set(ptr, pszParmValue);
6707                 init_iconv();
6708         }
6709         return true;
6710 }
6711
6712 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6713 {
6714         bool ret = true;
6715         char *realm = strupper_talloc(talloc_tos(), pszParmValue);
6716         char *dnsdomain = strlower_talloc(talloc_tos(), pszParmValue);
6717
6718         ret &= string_set(&Globals.szRealm, pszParmValue);
6719         ret &= string_set(&Globals.szRealm_upper, realm);
6720         ret &= string_set(&Globals.szRealm_lower, dnsdomain);
6721         TALLOC_FREE(realm);
6722         TALLOC_FREE(dnsdomain);
6723
6724         return ret;
6725 }
6726
6727 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6728 {
6729         TALLOC_FREE(Globals.szNetbiosAliases);
6730         Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
6731         return set_netbios_aliases(Globals.szNetbiosAliases);
6732 }
6733
6734 /***************************************************************************
6735  Handle the include operation.
6736 ***************************************************************************/
6737 static bool bAllowIncludeRegistry = true;
6738
6739 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6740 {
6741         char *fname;
6742
6743         if (include_depth >= MAX_INCLUDE_DEPTH) {
6744                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
6745                           include_depth));
6746                 return false;
6747         }
6748
6749         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6750                 if (!bAllowIncludeRegistry) {
6751                         return true;
6752                 }
6753                 if (bInGlobalSection) {
6754                         bool ret;
6755                         include_depth++;
6756                         ret = process_registry_globals();
6757                         include_depth--;
6758                         return ret;
6759                 } else {
6760                         DEBUG(1, ("\"include = registry\" only effective "
6761                                   "in %s section\n", GLOBAL_NAME));
6762                         return false;
6763                 }
6764         }
6765
6766         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
6767                                  current_user_info.domain,
6768                                  pszParmValue);
6769
6770         add_to_file_list(pszParmValue, fname);
6771
6772         string_set(ptr, fname);
6773
6774         if (file_exist(fname)) {
6775                 bool ret;
6776                 include_depth++;
6777                 ret = pm_process(fname, do_section, do_parameter, NULL);
6778                 include_depth--;
6779                 TALLOC_FREE(fname);
6780                 return ret;
6781         }
6782
6783         DEBUG(2, ("Can't find include file %s\n", fname));
6784         TALLOC_FREE(fname);
6785         return true;
6786 }
6787
6788 /***************************************************************************
6789  Handle the interpretation of the copy parameter.
6790 ***************************************************************************/
6791
6792 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6793 {
6794         bool bRetval;
6795         int iTemp;
6796         struct loadparm_service serviceTemp;
6797
6798         string_set(ptr, pszParmValue);
6799
6800         init_service(&serviceTemp);
6801
6802         bRetval = false;
6803
6804         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
6805
6806         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
6807                 if (iTemp == iServiceIndex) {
6808                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
6809                 } else {
6810                         copy_service(ServicePtrs[iServiceIndex],
6811                                      &serviceTemp,
6812                                      ServicePtrs[iServiceIndex]->copymap);
6813                         bRetval = true;
6814                 }
6815         } else {
6816                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
6817                 bRetval = false;
6818         }
6819
6820         free_service(&serviceTemp);
6821         return (bRetval);
6822 }
6823
6824 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6825 {
6826         Globals.ldap_debug_level = lp_int(pszParmValue);
6827         init_ldap_debugging();
6828         return true;
6829 }
6830
6831 /***************************************************************************
6832  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
6833  parameters is:
6834
6835  [global]
6836
6837         idmap uid = 1000-1999
6838         idmap gid = 700-899
6839
6840  We only do simple parsing checks here.  The strings are parsed into useful
6841  structures in the idmap daemon code.
6842
6843 ***************************************************************************/
6844
6845 /* Some lp_ routines to return idmap [ug]id information */
6846
6847 static uid_t idmap_uid_low, idmap_uid_high;
6848 static gid_t idmap_gid_low, idmap_gid_high;
6849
6850 bool lp_idmap_uid(uid_t *low, uid_t *high)
6851 {
6852         if (idmap_uid_low == 0 || idmap_uid_high == 0)
6853                 return false;
6854
6855         if (low)
6856                 *low = idmap_uid_low;
6857
6858         if (high)
6859                 *high = idmap_uid_high;
6860
6861         return true;
6862 }
6863
6864 bool lp_idmap_gid(gid_t *low, gid_t *high)
6865 {
6866         if (idmap_gid_low == 0 || idmap_gid_high == 0)
6867                 return false;
6868
6869         if (low)
6870                 *low = idmap_gid_low;
6871
6872         if (high)
6873                 *high = idmap_gid_high;
6874
6875         return true;
6876 }
6877
6878 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6879 {
6880         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
6881
6882         return true;
6883 }
6884
6885 /* Do some simple checks on "idmap [ug]id" parameter values */
6886
6887 static bool handle_idmap_uid(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 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6895 {
6896         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
6897
6898         return true;
6899 }
6900
6901 /***************************************************************************
6902  Handle the DEBUG level list.
6903 ***************************************************************************/
6904
6905 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
6906 {
6907         string_set(ptr, pszParmValueIn);
6908         return debug_parse_levels(pszParmValueIn);
6909 }
6910
6911 /***************************************************************************
6912  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
6913 ***************************************************************************/
6914
6915 static const char *append_ldap_suffix( const char *str )
6916 {
6917         const char *suffix_string;
6918
6919
6920         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
6921                                         Globals.szLdapSuffix );
6922         if ( !suffix_string ) {
6923                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
6924                 return "";
6925         }
6926
6927         return suffix_string;
6928 }
6929
6930 const char *lp_ldap_machine_suffix(void)
6931 {
6932         if (Globals.szLdapMachineSuffix[0])
6933                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
6934
6935         return lp_string(Globals.szLdapSuffix);
6936 }
6937
6938 const char *lp_ldap_user_suffix(void)
6939 {
6940         if (Globals.szLdapUserSuffix[0])
6941                 return append_ldap_suffix(Globals.szLdapUserSuffix);
6942
6943         return lp_string(Globals.szLdapSuffix);
6944 }
6945
6946 const char *lp_ldap_group_suffix(void)
6947 {
6948         if (Globals.szLdapGroupSuffix[0])
6949                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
6950
6951         return lp_string(Globals.szLdapSuffix);
6952 }
6953
6954 const char *lp_ldap_idmap_suffix(void)
6955 {
6956         if (Globals.szLdapIdmapSuffix[0])
6957                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
6958
6959         return lp_string(Globals.szLdapSuffix);
6960 }
6961
6962 /****************************************************************************
6963  set the value for a P_ENUM
6964  ***************************************************************************/
6965
6966 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
6967                               int *ptr )
6968 {
6969         int i;
6970
6971         for (i = 0; parm->enum_list[i].name; i++) {
6972                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
6973                         *ptr = parm->enum_list[i].value;
6974                         return;
6975                 }
6976         }
6977         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
6978                   pszParmValue, parm->label));
6979 }
6980
6981 /***************************************************************************
6982 ***************************************************************************/
6983
6984 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6985 {
6986         static int parm_num = -1;
6987         struct loadparm_service *s;
6988
6989         if ( parm_num == -1 )
6990                 parm_num = map_parameter( "printing" );
6991
6992         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
6993
6994         if ( snum < 0 )
6995                 s = &sDefault;
6996         else
6997                 s = ServicePtrs[snum];
6998
6999         init_printer_values( s );
7000
7001         return true;
7002 }
7003
7004
7005 /***************************************************************************
7006  Initialise a copymap.
7007 ***************************************************************************/
7008
7009 static void init_copymap(struct loadparm_service *pservice)
7010 {
7011         int i;
7012
7013         TALLOC_FREE(pservice->copymap);
7014
7015         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
7016         if (!pservice->copymap)
7017                 DEBUG(0,
7018                       ("Couldn't allocate copymap!! (size %d)\n",
7019                        (int)NUMPARAMETERS));
7020         else
7021                 for (i = 0; i < NUMPARAMETERS; i++)
7022                         bitmap_set(pservice->copymap, i);
7023 }
7024
7025 /**
7026   return the parameter pointer for a parameter
7027 */
7028 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
7029 {
7030         if (service == NULL) {
7031                 if (parm->p_class == P_LOCAL)
7032                         return (void *)(((char *)&sDefault)+parm->offset);
7033                 else if (parm->p_class == P_GLOBAL)
7034                         return (void *)(((char *)&Globals)+parm->offset);
7035                 else return NULL;
7036         } else {
7037                 return (void *)(((char *)service) + parm->offset);
7038         }
7039 }
7040
7041 /***************************************************************************
7042  Return the local pointer to a parameter given the service number and parameter
7043 ***************************************************************************/
7044
7045 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
7046 {
7047         return lp_parm_ptr(ServicePtrs[snum], parm);
7048 }
7049
7050 /***************************************************************************
7051  Process a parameter for a particular service number. If snum < 0
7052  then assume we are in the globals.
7053 ***************************************************************************/
7054
7055 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7056 {
7057         int parmnum, i;
7058         void *parm_ptr = NULL;  /* where we are going to store the result */
7059         struct parmlist_entry **opt_list;
7060
7061         parmnum = map_parameter(pszParmName);
7062
7063         if (parmnum < 0) {
7064                 if (strchr(pszParmName, ':') == NULL) {
7065                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7066                                   pszParmName));
7067                         return true;
7068                 }
7069
7070                 /*
7071                  * We've got a parametric option
7072                  */
7073
7074                 opt_list = (snum < 0)
7075                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7076                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
7077
7078                 return true;
7079         }
7080
7081         /* if it's already been set by the command line, then we don't
7082            override here */
7083         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
7084                 return true;
7085         }
7086
7087         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7088                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7089                           pszParmName));
7090         }
7091
7092         /* we might point at a service, the default service or a global */
7093         if (snum < 0) {
7094                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
7095         } else {
7096                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7097                         DEBUG(0,
7098                               ("Global parameter %s found in service section!\n",
7099                                pszParmName));
7100                         return true;
7101                 }
7102                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
7103         }
7104
7105         if (snum >= 0) {
7106                 if (!ServicePtrs[snum]->copymap)
7107                         init_copymap(ServicePtrs[snum]);
7108
7109                 /* this handles the aliases - set the copymap for other entries with
7110                    the same data pointer */
7111                 for (i = 0; parm_table[i].label; i++) {
7112                         if ((parm_table[i].offset == parm_table[parmnum].offset)
7113                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
7114                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7115                         }
7116                 }
7117         }
7118
7119         /* if it is a special case then go ahead */
7120         if (parm_table[parmnum].special) {
7121                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
7122                                                    (char **)parm_ptr);
7123         }
7124
7125         /* now switch on the type of variable it is */
7126         switch (parm_table[parmnum].type)
7127         {
7128                 case P_BOOL:
7129                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7130                         break;
7131
7132                 case P_BOOLREV:
7133                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7134                         break;
7135
7136                 case P_INTEGER:
7137                         *(int *)parm_ptr = lp_int(pszParmValue);
7138                         break;
7139
7140                 case P_CHAR:
7141                         *(char *)parm_ptr = *pszParmValue;
7142                         break;
7143
7144                 case P_OCTAL:
7145                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7146                         if ( i != 1 ) {
7147                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7148                         }
7149                         break;
7150
7151                 case P_BYTES:
7152                 {
7153                         uint64_t val;
7154                         if (conv_str_size_error(pszParmValue, &val)) {
7155                                 if (val <= INT_MAX) {
7156                                         *(int *)parm_ptr = (int)val;
7157                                         break;
7158                                 }
7159                         }
7160
7161                         DEBUG(0,("lp_do_parameter(%s): value is not "
7162                             "a valid size specifier!\n", pszParmValue));
7163                         return false;
7164                 }
7165
7166                 case P_LIST:
7167                 case P_CMDLIST:
7168                         TALLOC_FREE(*((char ***)parm_ptr));
7169                         *(char ***)parm_ptr = str_list_make_v3(
7170                                 NULL, pszParmValue, NULL);
7171                         break;
7172
7173                 case P_STRING:
7174                         string_set((char **)parm_ptr, pszParmValue);
7175                         break;
7176
7177                 case P_USTRING:
7178                 {
7179                         char *upper_string = strupper_talloc(talloc_tos(), 
7180                                                              pszParmValue);
7181                         string_set((char **)parm_ptr, upper_string);
7182                         TALLOC_FREE(upper_string);
7183                         break;
7184                 }
7185                 case P_ENUM:
7186                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7187                         break;
7188                 case P_SEP:
7189                         break;
7190         }
7191
7192         return true;
7193 }
7194
7195 /***************************************************************************
7196 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
7197 FLAG_CMDLINE won't be overridden by loads from smb.conf.
7198 ***************************************************************************/
7199
7200 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
7201 {
7202         int parmnum, i;
7203         parmnum = map_parameter(pszParmName);
7204         if (parmnum >= 0) {
7205                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
7206                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
7207                         return false;
7208                 }
7209                 parm_table[parmnum].flags |= FLAG_CMDLINE;
7210
7211                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
7212                  * be grouped in the table, so we don't have to search the
7213                  * whole table */
7214                 for (i=parmnum-1;
7215                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
7216                              && parm_table[i].p_class == parm_table[parmnum].p_class;
7217                      i--) {
7218                         parm_table[i].flags |= FLAG_CMDLINE;
7219                 }
7220                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
7221                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
7222                         parm_table[i].flags |= FLAG_CMDLINE;
7223                 }
7224
7225                 if (store_values) {
7226                         store_lp_set_cmdline(pszParmName, pszParmValue);
7227                 }
7228                 return true;
7229         }
7230
7231         /* it might be parametric */
7232         if (strchr(pszParmName, ':') != NULL) {
7233                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
7234                 if (store_values) {
7235                         store_lp_set_cmdline(pszParmName, pszParmValue);
7236                 }
7237                 return true;
7238         }
7239
7240         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
7241         return true;
7242 }
7243
7244 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
7245 {
7246         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
7247 }
7248
7249 /***************************************************************************
7250  Process a parameter.
7251 ***************************************************************************/
7252
7253 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7254                          void *userdata)
7255 {
7256         if (!bInGlobalSection && bGlobalOnly)
7257                 return true;
7258
7259         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7260
7261         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7262                                 pszParmName, pszParmValue));
7263 }
7264
7265 /*
7266   set a option from the commandline in 'a=b' format. Use to support --option
7267 */
7268 bool lp_set_option(const char *option)
7269 {
7270         char *p, *s;
7271         bool ret;
7272
7273         s = talloc_strdup(NULL, option);
7274         if (!s) {
7275                 return false;
7276         }
7277
7278         p = strchr(s, '=');
7279         if (!p) {
7280                 talloc_free(s);
7281                 return false;
7282         }
7283
7284         *p = 0;
7285
7286         /* skip white spaces after the = sign */
7287         do {
7288                 p++;
7289         } while (*p == ' ');
7290
7291         ret = lp_set_cmdline(s, p);
7292         talloc_free(s);
7293         return ret;
7294 }
7295
7296 /**************************************************************************
7297  Print a parameter of the specified type.
7298 ***************************************************************************/
7299
7300 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7301 {
7302         /* For the seperation of lists values that we print below */
7303         const char *list_sep = ", ";
7304         int i;
7305         switch (p->type)
7306         {
7307                 case P_ENUM:
7308                         for (i = 0; p->enum_list[i].name; i++) {
7309                                 if (*(int *)ptr == p->enum_list[i].value) {
7310                                         fprintf(f, "%s",
7311                                                 p->enum_list[i].name);
7312                                         break;
7313                                 }
7314                         }
7315                         break;
7316
7317                 case P_BOOL:
7318                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7319                         break;
7320
7321                 case P_BOOLREV:
7322                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7323                         break;
7324
7325                 case P_INTEGER:
7326                 case P_BYTES:
7327                         fprintf(f, "%d", *(int *)ptr);
7328                         break;
7329
7330                 case P_CHAR:
7331                         fprintf(f, "%c", *(char *)ptr);
7332                         break;
7333
7334                 case P_OCTAL: {
7335                         int val = *(int *)ptr; 
7336                         if (val == -1) {
7337                                 fprintf(f, "-1");
7338                         } else {
7339                                 fprintf(f, "0%o", val);
7340                         }
7341                         break;
7342                 }
7343
7344                 case P_CMDLIST:
7345                         list_sep = " ";
7346                         /* fall through */
7347                 case P_LIST:
7348                         if ((char ***)ptr && *(char ***)ptr) {
7349                                 char **list = *(char ***)ptr;
7350                                 for (; *list; list++) {
7351                                         /* surround strings with whitespace in double quotes */
7352                                         if (*(list+1) == NULL) {
7353                                                 /* last item, no extra separator */
7354                                                 list_sep = "";
7355                                         }
7356                                         if ( strchr_m( *list, ' ' ) ) {
7357                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
7358                                         } else {
7359                                                 fprintf(f, "%s%s", *list, list_sep);
7360                                         }
7361                                 }
7362                         }
7363                         break;
7364
7365                 case P_STRING:
7366                 case P_USTRING:
7367                         if (*(char **)ptr) {
7368                                 fprintf(f, "%s", *(char **)ptr);
7369                         }
7370                         break;
7371                 case P_SEP:
7372                         break;
7373         }
7374 }
7375
7376 /***************************************************************************
7377  Check if two parameters are equal.
7378 ***************************************************************************/
7379
7380 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7381 {
7382         switch (type) {
7383                 case P_BOOL:
7384                 case P_BOOLREV:
7385                         return (*((bool *)ptr1) == *((bool *)ptr2));
7386
7387                 case P_INTEGER:
7388                 case P_ENUM:
7389                 case P_OCTAL:
7390                 case P_BYTES:
7391                         return (*((int *)ptr1) == *((int *)ptr2));
7392
7393                 case P_CHAR:
7394                         return (*((char *)ptr1) == *((char *)ptr2));
7395
7396                 case P_LIST:
7397                 case P_CMDLIST:
7398                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7399
7400                 case P_STRING:
7401                 case P_USTRING:
7402                 {
7403                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7404                         if (p1 && !*p1)
7405                                 p1 = NULL;
7406                         if (p2 && !*p2)
7407                                 p2 = NULL;
7408                         return (p1 == p2 || strequal(p1, p2));
7409                 }
7410                 case P_SEP:
7411                         break;
7412         }
7413         return false;
7414 }
7415
7416 /***************************************************************************
7417  Initialize any local varients in the sDefault table.
7418 ***************************************************************************/
7419
7420 void init_locals(void)
7421 {
7422         /* None as yet. */
7423 }
7424
7425 /***************************************************************************
7426  Process a new section (service). At this stage all sections are services.
7427  Later we'll have special sections that permit server parameters to be set.
7428  Returns true on success, false on failure.
7429 ***************************************************************************/
7430
7431 static bool do_section(const char *pszSectionName, void *userdata)
7432 {
7433         bool bRetval;
7434         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7435                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7436         bRetval = false;
7437
7438         /* if we were in a global section then do the local inits */
7439         if (bInGlobalSection && !isglobal)
7440                 init_locals();
7441
7442         /* if we've just struck a global section, note the fact. */
7443         bInGlobalSection = isglobal;
7444
7445         /* check for multiple global sections */
7446         if (bInGlobalSection) {
7447                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7448                 return true;
7449         }
7450
7451         if (!bInGlobalSection && bGlobalOnly)
7452                 return true;
7453
7454         /* if we have a current service, tidy it up before moving on */
7455         bRetval = true;
7456
7457         if (iServiceIndex >= 0)
7458                 bRetval = service_ok(iServiceIndex);
7459
7460         /* if all is still well, move to the next record in the services array */
7461         if (bRetval) {
7462                 /* We put this here to avoid an odd message order if messages are */
7463                 /* issued by the post-processing of a previous section. */
7464                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7465
7466                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
7467                 if (iServiceIndex < 0) {
7468                         DEBUG(0, ("Failed to add a new service\n"));
7469                         return false;
7470                 }
7471                 /* Clean all parametric options for service */
7472                 /* They will be added during parsing again */
7473                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
7474         }
7475
7476         return bRetval;
7477 }
7478
7479
7480 /***************************************************************************
7481  Determine if a partcular base parameter is currentl set to the default value.
7482 ***************************************************************************/
7483
7484 static bool is_default(int i)
7485 {
7486         if (!defaults_saved)
7487                 return false;
7488         switch (parm_table[i].type) {
7489                 case P_LIST:
7490                 case P_CMDLIST:
7491                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
7492                                               *(const char ***)lp_parm_ptr(NULL, 
7493                                                                            &parm_table[i]));
7494                 case P_STRING:
7495                 case P_USTRING:
7496                         return strequal(parm_table[i].def.svalue,
7497                                         *(char **)lp_parm_ptr(NULL, 
7498                                                               &parm_table[i]));
7499                 case P_BOOL:
7500                 case P_BOOLREV:
7501                         return parm_table[i].def.bvalue ==
7502                                 *(bool *)lp_parm_ptr(NULL, 
7503                                                      &parm_table[i]);
7504                 case P_CHAR:
7505                         return parm_table[i].def.cvalue ==
7506                                 *(char *)lp_parm_ptr(NULL, 
7507                                                      &parm_table[i]);
7508                 case P_INTEGER:
7509                 case P_OCTAL:
7510                 case P_ENUM:
7511                 case P_BYTES:
7512                         return parm_table[i].def.ivalue ==
7513                                 *(int *)lp_parm_ptr(NULL, 
7514                                                     &parm_table[i]);
7515                 case P_SEP:
7516                         break;
7517         }
7518         return false;
7519 }
7520
7521 /***************************************************************************
7522 Display the contents of the global structure.
7523 ***************************************************************************/
7524
7525 static void dump_globals(FILE *f)
7526 {
7527         int i;
7528         struct parmlist_entry *data;
7529
7530         fprintf(f, "[global]\n");
7531
7532         for (i = 0; parm_table[i].label; i++)
7533                 if (parm_table[i].p_class == P_GLOBAL &&
7534                     !(parm_table[i].flags & FLAG_META) &&
7535                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
7536                         if (defaults_saved && is_default(i))
7537                                 continue;
7538                         fprintf(f, "\t%s = ", parm_table[i].label);
7539                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
7540                                                                     &parm_table[i]),
7541                                         f);
7542                         fprintf(f, "\n");
7543         }
7544         if (Globals.param_opt != NULL) {
7545                 data = Globals.param_opt;
7546                 while(data) {
7547                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7548                         data = data->next;
7549                 }
7550         }
7551
7552 }
7553
7554 /***************************************************************************
7555  Return true if a local parameter is currently set to the global default.
7556 ***************************************************************************/
7557
7558 bool lp_is_default(int snum, struct parm_struct *parm)
7559 {
7560         return equal_parameter(parm->type,
7561                                lp_parm_ptr(ServicePtrs[snum], parm),
7562                                lp_parm_ptr(NULL, parm));
7563 }
7564
7565 /***************************************************************************
7566  Display the contents of a single services record.
7567 ***************************************************************************/
7568
7569 static void dump_a_service(struct loadparm_service *pService, FILE * f)
7570 {
7571         int i;
7572         struct parmlist_entry *data;
7573
7574         if (pService != &sDefault)
7575                 fprintf(f, "[%s]\n", pService->szService);
7576
7577         for (i = 0; parm_table[i].label; i++) {
7578
7579                 if (parm_table[i].p_class == P_LOCAL &&
7580                     !(parm_table[i].flags & FLAG_META) &&
7581                     (*parm_table[i].label != '-') &&
7582                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7583                 {
7584                         if (pService == &sDefault) {
7585                                 if (defaults_saved && is_default(i))
7586                                         continue;
7587                         } else {
7588                                 if (equal_parameter(parm_table[i].type,
7589                                                     lp_parm_ptr(pService, &parm_table[i]),
7590                                                     lp_parm_ptr(NULL, &parm_table[i])))
7591                                         continue;
7592                         }
7593
7594                         fprintf(f, "\t%s = ", parm_table[i].label);
7595                         print_parameter(&parm_table[i],
7596                                         lp_parm_ptr(pService, &parm_table[i]),
7597                                         f);
7598                         fprintf(f, "\n");
7599                 }
7600         }
7601
7602                 if (pService->param_opt != NULL) {
7603                         data = pService->param_opt;
7604                         while(data) {
7605                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7606                                 data = data->next;
7607                         }
7608                 }
7609 }
7610
7611 /***************************************************************************
7612  Display the contents of a parameter of a single services record.
7613 ***************************************************************************/
7614
7615 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7616 {
7617         int i;
7618         bool result = false;
7619         parm_class p_class;
7620         unsigned flag = 0;
7621         fstring local_parm_name;
7622         char *parm_opt;
7623         const char *parm_opt_value;
7624
7625         /* check for parametrical option */
7626         fstrcpy( local_parm_name, parm_name);
7627         parm_opt = strchr( local_parm_name, ':');
7628
7629         if (parm_opt) {
7630                 *parm_opt = '\0';
7631                 parm_opt++;
7632                 if (strlen(parm_opt)) {
7633                         parm_opt_value = lp_parm_const_string( snum,
7634                                 local_parm_name, parm_opt, NULL);
7635                         if (parm_opt_value) {
7636                                 printf( "%s\n", parm_opt_value);
7637                                 result = true;
7638                         }
7639                 }
7640                 return result;
7641         }
7642
7643         /* check for a key and print the value */
7644         if (isGlobal) {
7645                 p_class = P_GLOBAL;
7646                 flag = FLAG_GLOBAL;
7647         } else
7648                 p_class = P_LOCAL;
7649
7650         for (i = 0; parm_table[i].label; i++) {
7651                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7652                     !(parm_table[i].flags & FLAG_META) &&
7653                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7654                     (*parm_table[i].label != '-') &&
7655                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7656                 {
7657                         void *ptr;
7658
7659                         if (isGlobal) {
7660                                 ptr = lp_parm_ptr(NULL, 
7661                                                   &parm_table[i]);
7662                         } else {
7663                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
7664                                                   &parm_table[i]);
7665                         }
7666
7667                         print_parameter(&parm_table[i],
7668                                         ptr, f);
7669                         fprintf(f, "\n");
7670                         result = true;
7671                         break;
7672                 }
7673         }
7674
7675         return result;
7676 }
7677
7678 /***************************************************************************
7679  Return info about the requested parameter (given as a string).
7680  Return NULL when the string is not a valid parameter name.
7681 ***************************************************************************/
7682
7683 struct parm_struct *lp_get_parameter(const char *param_name)
7684 {
7685         int num = map_parameter(param_name);
7686
7687         if (num < 0) {
7688                 return NULL;
7689         }
7690
7691         return &parm_table[num];
7692 }
7693
7694 /***************************************************************************
7695  Return info about the next parameter in a service.
7696  snum==GLOBAL_SECTION_SNUM gives the globals.
7697  Return NULL when out of parameters.
7698 ***************************************************************************/
7699
7700 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7701 {
7702         if (snum < 0) {
7703                 /* do the globals */
7704                 for (; parm_table[*i].label; (*i)++) {
7705                         if (parm_table[*i].p_class == P_SEPARATOR)
7706                                 return &parm_table[(*i)++];
7707
7708                         if ((*parm_table[*i].label == '-'))
7709                                 continue;
7710
7711                         if ((*i) > 0
7712                             && (parm_table[*i].offset ==
7713                                 parm_table[(*i) - 1].offset)
7714                             && (parm_table[*i].p_class ==
7715                                 parm_table[(*i) - 1].p_class))
7716                                 continue;
7717
7718                         if (is_default(*i) && !allparameters)
7719                                 continue;
7720
7721                         return &parm_table[(*i)++];
7722                 }
7723         } else {
7724                 struct loadparm_service *pService = ServicePtrs[snum];
7725
7726                 for (; parm_table[*i].label; (*i)++) {
7727                         if (parm_table[*i].p_class == P_SEPARATOR)
7728                                 return &parm_table[(*i)++];
7729
7730                         if (parm_table[*i].p_class == P_LOCAL &&
7731                             (*parm_table[*i].label != '-') &&
7732                             ((*i) == 0 ||
7733                              (parm_table[*i].offset !=
7734                               parm_table[(*i) - 1].offset)))
7735                         {
7736                                 if (allparameters ||
7737                                     !equal_parameter(parm_table[*i].type,
7738                                                      lp_parm_ptr(pService, 
7739                                                                  &parm_table[*i]),
7740                                                      lp_parm_ptr(NULL, 
7741                                                                  &parm_table[*i])))
7742                                 {
7743                                         return &parm_table[(*i)++];
7744                                 }
7745                         }
7746                 }
7747         }
7748
7749         return NULL;
7750 }
7751
7752
7753 #if 0
7754 /***************************************************************************
7755  Display the contents of a single copy structure.
7756 ***************************************************************************/
7757 static void dump_copy_map(bool *pcopymap)
7758 {
7759         int i;
7760         if (!pcopymap)
7761                 return;
7762
7763         printf("\n\tNon-Copied parameters:\n");
7764
7765         for (i = 0; parm_table[i].label; i++)
7766                 if (parm_table[i].p_class == P_LOCAL &&
7767                     parm_table[i].ptr && !pcopymap[i] &&
7768                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
7769                 {
7770                         printf("\t\t%s\n", parm_table[i].label);
7771                 }
7772 }
7773 #endif
7774
7775 /***************************************************************************
7776  Return TRUE if the passed service number is within range.
7777 ***************************************************************************/
7778
7779 bool lp_snum_ok(int iService)
7780 {
7781         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
7782 }
7783
7784 /***************************************************************************
7785  Auto-load some home services.
7786 ***************************************************************************/
7787
7788 static void lp_add_auto_services(char *str)
7789 {
7790         char *s;
7791         char *p;
7792         int homes;
7793         char *saveptr;
7794
7795         if (!str)
7796                 return;
7797
7798         s = SMB_STRDUP(str);
7799         if (!s)
7800                 return;
7801
7802         homes = lp_servicenumber(HOMES_NAME);
7803
7804         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
7805              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
7806                 char *home;
7807
7808                 if (lp_servicenumber(p) >= 0)
7809                         continue;
7810
7811                 home = get_user_home_dir(talloc_tos(), p);
7812
7813                 if (home && home[0] && homes >= 0)
7814                         lp_add_home(p, homes, p, home);
7815
7816                 TALLOC_FREE(home);
7817         }
7818         SAFE_FREE(s);
7819 }
7820
7821 /***************************************************************************
7822  Auto-load one printer.
7823 ***************************************************************************/
7824
7825 void lp_add_one_printer(const char *name, const char *comment,
7826                         const char *location, void *pdata)
7827 {
7828         int printers = lp_servicenumber(PRINTERS_NAME);
7829         int i;
7830
7831         if (lp_servicenumber(name) < 0) {
7832                 lp_add_printer(name, printers);
7833                 if ((i = lp_servicenumber(name)) >= 0) {
7834                         string_set(&ServicePtrs[i]->comment, comment);
7835                         ServicePtrs[i]->autoloaded = true;
7836                 }
7837         }
7838 }
7839
7840 /***************************************************************************
7841  Have we loaded a services file yet?
7842 ***************************************************************************/
7843
7844 bool lp_loaded(void)
7845 {
7846         return (bLoaded);
7847 }
7848
7849 /***************************************************************************
7850  Unload unused services.
7851 ***************************************************************************/
7852
7853 void lp_killunused(struct smbd_server_connection *sconn,
7854                    bool (*snumused) (struct smbd_server_connection *, int))
7855 {
7856         int i;
7857         for (i = 0; i < iNumServices; i++) {
7858                 if (!VALID(i))
7859                         continue;
7860
7861                 /* don't kill autoloaded or usershare services */
7862                 if ( ServicePtrs[i]->autoloaded ||
7863                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
7864                         continue;
7865                 }
7866
7867                 if (!snumused || !snumused(sconn, i)) {
7868                         free_service_byindex(i);
7869                 }
7870         }
7871 }
7872
7873 /**
7874  * Kill all except autoloaded and usershare services - convenience wrapper
7875  */
7876 void lp_kill_all_services(void)
7877 {
7878         lp_killunused(NULL, NULL);
7879 }
7880
7881 /***************************************************************************
7882  Unload a service.
7883 ***************************************************************************/
7884
7885 void lp_killservice(int iServiceIn)
7886 {
7887         if (VALID(iServiceIn)) {
7888                 free_service_byindex(iServiceIn);
7889         }
7890 }
7891
7892 /***************************************************************************
7893  Save the curent values of all global and sDefault parameters into the 
7894  defaults union. This allows swat and testparm to show only the
7895  changed (ie. non-default) parameters.
7896 ***************************************************************************/
7897
7898 static void lp_save_defaults(void)
7899 {
7900         int i;
7901         for (i = 0; parm_table[i].label; i++) {
7902                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
7903                     && parm_table[i].p_class == parm_table[i - 1].p_class)
7904                         continue;
7905                 switch (parm_table[i].type) {
7906                         case P_LIST:
7907                         case P_CMDLIST:
7908                                 parm_table[i].def.lvalue = str_list_copy(
7909                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
7910                                 break;
7911                         case P_STRING:
7912                         case P_USTRING:
7913                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
7914                                 break;
7915                         case P_BOOL:
7916                         case P_BOOLREV:
7917                                 parm_table[i].def.bvalue =
7918                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
7919                                 break;
7920                         case P_CHAR:
7921                                 parm_table[i].def.cvalue =
7922                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
7923                                 break;
7924                         case P_INTEGER:
7925                         case P_OCTAL:
7926                         case P_ENUM:
7927                         case P_BYTES:
7928                                 parm_table[i].def.ivalue =
7929                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
7930                                 break;
7931                         case P_SEP:
7932                                 break;
7933                 }
7934         }
7935         defaults_saved = true;
7936 }
7937
7938 /***********************************************************
7939  If we should send plaintext/LANMAN passwords in the clinet
7940 ************************************************************/
7941
7942 static void set_allowed_client_auth(void)
7943 {
7944         if (Globals.bClientNTLMv2Auth) {
7945                 Globals.bClientLanManAuth = false;
7946         }
7947         if (!Globals.bClientLanManAuth) {
7948                 Globals.bClientPlaintextAuth = false;
7949         }
7950 }
7951
7952 /***************************************************************************
7953  JRA.
7954  The following code allows smbd to read a user defined share file.
7955  Yes, this is my intent. Yes, I'm comfortable with that...
7956
7957  THE FOLLOWING IS SECURITY CRITICAL CODE.
7958
7959  It washes your clothes, it cleans your house, it guards you while you sleep...
7960  Do not f%^k with it....
7961 ***************************************************************************/
7962
7963 #define MAX_USERSHARE_FILE_SIZE (10*1024)
7964
7965 /***************************************************************************
7966  Check allowed stat state of a usershare file.
7967  Ensure we print out who is dicking with us so the admin can
7968  get their sorry ass fired.
7969 ***************************************************************************/
7970
7971 static bool check_usershare_stat(const char *fname,
7972                                  const SMB_STRUCT_STAT *psbuf)
7973 {
7974         if (!S_ISREG(psbuf->st_ex_mode)) {
7975                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
7976                         "not a regular file\n",
7977                         fname, (unsigned int)psbuf->st_ex_uid ));
7978                 return false;
7979         }
7980
7981         /* Ensure this doesn't have the other write bit set. */
7982         if (psbuf->st_ex_mode & S_IWOTH) {
7983                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
7984                         "public write. Refusing to allow as a usershare file.\n",
7985                         fname, (unsigned int)psbuf->st_ex_uid ));
7986                 return false;
7987         }
7988
7989         /* Should be 10k or less. */
7990         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
7991                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
7992                         "too large (%u) to be a user share file.\n",
7993                         fname, (unsigned int)psbuf->st_ex_uid,
7994                         (unsigned int)psbuf->st_ex_size ));
7995                 return false;
7996         }
7997
7998         return true;
7999 }
8000
8001 /***************************************************************************
8002  Parse the contents of a usershare file.
8003 ***************************************************************************/
8004
8005 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8006                         SMB_STRUCT_STAT *psbuf,
8007                         const char *servicename,
8008                         int snum,
8009                         char **lines,
8010                         int numlines,
8011                         char **pp_sharepath,
8012                         char **pp_comment,
8013                         char **pp_cp_servicename,
8014                         struct security_descriptor **ppsd,
8015                         bool *pallow_guest)
8016 {
8017         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8018         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8019         int us_vers;
8020         DIR *dp;
8021         SMB_STRUCT_STAT sbuf;
8022         char *sharepath = NULL;
8023         char *comment = NULL;
8024
8025         *pp_sharepath = NULL;
8026         *pp_comment = NULL;
8027
8028         *pallow_guest = false;
8029
8030         if (numlines < 4) {
8031                 return USERSHARE_MALFORMED_FILE;
8032         }
8033
8034         if (strcmp(lines[0], "#VERSION 1") == 0) {
8035                 us_vers = 1;
8036         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8037                 us_vers = 2;
8038                 if (numlines < 5) {
8039                         return USERSHARE_MALFORMED_FILE;
8040                 }
8041         } else {
8042                 return USERSHARE_BAD_VERSION;
8043         }
8044
8045         if (strncmp(lines[1], "path=", 5) != 0) {
8046                 return USERSHARE_MALFORMED_PATH;
8047         }
8048
8049         sharepath = talloc_strdup(ctx, &lines[1][5]);
8050         if (!sharepath) {
8051                 return USERSHARE_POSIX_ERR;
8052         }
8053         trim_string(sharepath, " ", " ");
8054
8055         if (strncmp(lines[2], "comment=", 8) != 0) {
8056                 return USERSHARE_MALFORMED_COMMENT_DEF;
8057         }
8058
8059         comment = talloc_strdup(ctx, &lines[2][8]);
8060         if (!comment) {
8061                 return USERSHARE_POSIX_ERR;
8062         }
8063         trim_string(comment, " ", " ");
8064         trim_char(comment, '"', '"');
8065
8066         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8067                 return USERSHARE_MALFORMED_ACL_DEF;
8068         }
8069
8070         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8071                 return USERSHARE_ACL_ERR;
8072         }
8073
8074         if (us_vers == 2) {
8075                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8076                         return USERSHARE_MALFORMED_ACL_DEF;
8077                 }
8078                 if (lines[4][9] == 'y') {
8079                         *pallow_guest = true;
8080                 }
8081
8082                 /* Backwards compatible extension to file version #2. */
8083                 if (numlines > 5) {
8084                         if (strncmp(lines[5], "sharename=", 10) != 0) {
8085                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
8086                         }
8087                         if (!strequal(&lines[5][10], servicename)) {
8088                                 return USERSHARE_BAD_SHARENAME;
8089                         }
8090                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
8091                         if (!*pp_cp_servicename) {
8092                                 return USERSHARE_POSIX_ERR;
8093                         }
8094                 }
8095         }
8096
8097         if (*pp_cp_servicename == NULL) {
8098                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
8099                 if (!*pp_cp_servicename) {
8100                         return USERSHARE_POSIX_ERR;
8101                 }
8102         }
8103
8104         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8105                 /* Path didn't change, no checks needed. */
8106                 *pp_sharepath = sharepath;
8107                 *pp_comment = comment;
8108                 return USERSHARE_OK;
8109         }
8110
8111         /* The path *must* be absolute. */
8112         if (sharepath[0] != '/') {
8113                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8114                         servicename, sharepath));
8115                 return USERSHARE_PATH_NOT_ABSOLUTE;
8116         }
8117
8118         /* If there is a usershare prefix deny list ensure one of these paths
8119            doesn't match the start of the user given path. */
8120         if (prefixdenylist) {
8121                 int i;
8122                 for ( i=0; prefixdenylist[i]; i++ ) {
8123                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8124                                 servicename, i, prefixdenylist[i], sharepath ));
8125                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8126                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8127                                         "usershare prefix deny list entries.\n",
8128                                         servicename, sharepath));
8129                                 return USERSHARE_PATH_IS_DENIED;
8130                         }
8131                 }
8132         }
8133
8134         /* If there is a usershare prefix allow list ensure one of these paths
8135            does match the start of the user given path. */
8136
8137         if (prefixallowlist) {
8138                 int i;
8139                 for ( i=0; prefixallowlist[i]; i++ ) {
8140                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8141                                 servicename, i, prefixallowlist[i], sharepath ));
8142                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8143                                 break;
8144                         }
8145                 }
8146                 if (prefixallowlist[i] == NULL) {
8147                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8148                                 "usershare prefix allow list entries.\n",
8149                                 servicename, sharepath));
8150                         return USERSHARE_PATH_NOT_ALLOWED;
8151                 }
8152         }
8153
8154         /* Ensure this is pointing to a directory. */
8155         dp = opendir(sharepath);
8156
8157         if (!dp) {
8158                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8159                         servicename, sharepath));
8160                 return USERSHARE_PATH_NOT_DIRECTORY;
8161         }
8162
8163         /* Ensure the owner of the usershare file has permission to share
8164            this directory. */
8165
8166         if (sys_stat(sharepath, &sbuf, false) == -1) {
8167                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8168                         servicename, sharepath, strerror(errno) ));
8169                 closedir(dp);
8170                 return USERSHARE_POSIX_ERR;
8171         }
8172
8173         closedir(dp);
8174
8175         if (!S_ISDIR(sbuf.st_ex_mode)) {
8176                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8177                         servicename, sharepath ));
8178                 return USERSHARE_PATH_NOT_DIRECTORY;
8179         }
8180
8181         /* Check if sharing is restricted to owner-only. */
8182         /* psbuf is the stat of the usershare definition file,
8183            sbuf is the stat of the target directory to be shared. */
8184
8185         if (lp_usershare_owner_only()) {
8186                 /* root can share anything. */
8187                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
8188                         return USERSHARE_PATH_NOT_ALLOWED;
8189                 }
8190         }
8191
8192         *pp_sharepath = sharepath;
8193         *pp_comment = comment;
8194         return USERSHARE_OK;
8195 }
8196
8197 /***************************************************************************
8198  Deal with a usershare file.
8199  Returns:
8200         >= 0 - snum
8201         -1 - Bad name, invalid contents.
8202            - service name already existed and not a usershare, problem
8203             with permissions to share directory etc.
8204 ***************************************************************************/
8205
8206 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8207 {
8208         SMB_STRUCT_STAT sbuf;
8209         SMB_STRUCT_STAT lsbuf;
8210         char *fname = NULL;
8211         char *sharepath = NULL;
8212         char *comment = NULL;
8213         char *cp_service_name = NULL;
8214         char **lines = NULL;
8215         int numlines = 0;
8216         int fd = -1;
8217         int iService = -1;
8218         TALLOC_CTX *ctx = talloc_stackframe();
8219         struct security_descriptor *psd = NULL;
8220         bool guest_ok = false;
8221         char *canon_name = NULL;
8222         bool added_service = false;
8223         int ret = -1;
8224
8225         /* Ensure share name doesn't contain invalid characters. */
8226         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8227                 DEBUG(0,("process_usershare_file: share name %s contains "
8228                         "invalid characters (any of %s)\n",
8229                         file_name, INVALID_SHARENAME_CHARS ));
8230                 goto out;
8231         }
8232
8233         canon_name = canonicalize_servicename(ctx, file_name);
8234         if (!canon_name) {
8235                 goto out;
8236         }
8237
8238         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
8239         if (!fname) {
8240                 goto out;
8241         }
8242
8243         /* Minimize the race condition by doing an lstat before we
8244            open and fstat. Ensure this isn't a symlink link. */
8245
8246         if (sys_lstat(fname, &lsbuf, false) != 0) {
8247                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8248                         fname, strerror(errno) ));
8249                 goto out;
8250         }
8251
8252         /* This must be a regular file, not a symlink, directory or
8253            other strange filetype. */
8254         if (!check_usershare_stat(fname, &lsbuf)) {
8255                 goto out;
8256         }
8257
8258         {
8259                 TDB_DATA data;
8260                 NTSTATUS status;
8261
8262                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
8263                                                canon_name, &data);
8264
8265                 iService = -1;
8266
8267                 if (NT_STATUS_IS_OK(status) &&
8268                     (data.dptr != NULL) &&
8269                     (data.dsize == sizeof(iService))) {
8270                         memcpy(&iService, data.dptr, sizeof(iService));
8271                 }
8272         }
8273
8274         if (iService != -1 &&
8275             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
8276                              &lsbuf.st_ex_mtime) == 0) {
8277                 /* Nothing changed - Mark valid and return. */
8278                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8279                         canon_name ));
8280                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8281                 ret = iService;
8282                 goto out;
8283         }
8284
8285         /* Try and open the file read only - no symlinks allowed. */
8286 #ifdef O_NOFOLLOW
8287         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
8288 #else
8289         fd = open(fname, O_RDONLY, 0);
8290 #endif
8291
8292         if (fd == -1) {
8293                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8294                         fname, strerror(errno) ));
8295                 goto out;
8296         }
8297
8298         /* Now fstat to be *SURE* it's a regular file. */
8299         if (sys_fstat(fd, &sbuf, false) != 0) {
8300                 close(fd);
8301                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8302                         fname, strerror(errno) ));
8303                 goto out;
8304         }
8305
8306         /* Is it the same dev/inode as was lstated ? */
8307         if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) {
8308                 close(fd);
8309                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8310                         "Symlink spoofing going on ?\n", fname ));
8311                 goto out;
8312         }
8313
8314         /* This must be a regular file, not a symlink, directory or
8315            other strange filetype. */
8316         if (!check_usershare_stat(fname, &sbuf)) {
8317                 goto out;
8318         }
8319
8320         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8321
8322         close(fd);
8323         if (lines == NULL) {
8324                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8325                         fname, (unsigned int)sbuf.st_ex_uid ));
8326                 goto out;
8327         }
8328
8329         if (parse_usershare_file(ctx, &sbuf, file_name,
8330                         iService, lines, numlines, &sharepath,
8331                         &comment, &cp_service_name,
8332                         &psd, &guest_ok) != USERSHARE_OK) {
8333                 goto out;
8334         }
8335
8336         /* Everything ok - add the service possibly using a template. */
8337         if (iService < 0) {
8338                 const struct loadparm_service *sp = &sDefault;
8339                 if (snum_template != -1) {
8340                         sp = ServicePtrs[snum_template];
8341                 }
8342
8343                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
8344                         DEBUG(0, ("process_usershare_file: Failed to add "
8345                                 "new service %s\n", cp_service_name));
8346                         goto out;
8347                 }
8348
8349                 added_service = true;
8350
8351                 /* Read only is controlled by usershare ACL below. */
8352                 ServicePtrs[iService]->bRead_only = false;
8353         }
8354
8355         /* Write the ACL of the new/modified share. */
8356         if (!set_share_security(canon_name, psd)) {
8357                  DEBUG(0, ("process_usershare_file: Failed to set share "
8358                         "security for user share %s\n",
8359                         canon_name ));
8360                 goto out;
8361         }
8362
8363         /* If from a template it may be marked invalid. */
8364         ServicePtrs[iService]->valid = true;
8365
8366         /* Set the service as a valid usershare. */
8367         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8368
8369         /* Set guest access. */
8370         if (lp_usershare_allow_guests()) {
8371                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8372         }
8373
8374         /* And note when it was loaded. */
8375         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
8376         string_set(&ServicePtrs[iService]->szPath, sharepath);
8377         string_set(&ServicePtrs[iService]->comment, comment);
8378
8379         ret = iService;
8380
8381   out:
8382
8383         if (ret == -1 && iService != -1 && added_service) {
8384                 lp_remove_service(iService);
8385         }
8386
8387         TALLOC_FREE(lines);
8388         TALLOC_FREE(ctx);
8389         return ret;
8390 }
8391
8392 /***************************************************************************
8393  Checks if a usershare entry has been modified since last load.
8394 ***************************************************************************/
8395
8396 static bool usershare_exists(int iService, struct timespec *last_mod)
8397 {
8398         SMB_STRUCT_STAT lsbuf;
8399         const char *usersharepath = Globals.szUsersharePath;
8400         char *fname;
8401
8402         if (asprintf(&fname, "%s/%s",
8403                                 usersharepath,
8404                                 ServicePtrs[iService]->szService) < 0) {
8405                 return false;
8406         }
8407
8408         if (sys_lstat(fname, &lsbuf, false) != 0) {
8409                 SAFE_FREE(fname);
8410                 return false;
8411         }
8412
8413         if (!S_ISREG(lsbuf.st_ex_mode)) {
8414                 SAFE_FREE(fname);
8415                 return false;
8416         }
8417
8418         SAFE_FREE(fname);
8419         *last_mod = lsbuf.st_ex_mtime;
8420         return true;
8421 }
8422
8423 /***************************************************************************
8424  Load a usershare service by name. Returns a valid servicenumber or -1.
8425 ***************************************************************************/
8426
8427 int load_usershare_service(const char *servicename)
8428 {
8429         SMB_STRUCT_STAT sbuf;
8430         const char *usersharepath = Globals.szUsersharePath;
8431         int max_user_shares = Globals.iUsershareMaxShares;
8432         int snum_template = -1;
8433
8434         if (*usersharepath == 0 ||  max_user_shares == 0) {
8435                 return -1;
8436         }
8437
8438         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8439                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8440                         usersharepath, strerror(errno) ));
8441                 return -1;
8442         }
8443
8444         if (!S_ISDIR(sbuf.st_ex_mode)) {
8445                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8446                         usersharepath ));
8447                 return -1;
8448         }
8449
8450         /*
8451          * This directory must be owned by root, and have the 't' bit set.
8452          * It also must not be writable by "other".
8453          */
8454
8455 #ifdef S_ISVTX
8456         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8457 #else
8458         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8459 #endif
8460                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8461                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8462                         usersharepath ));
8463                 return -1;
8464         }
8465
8466         /* Ensure the template share exists if it's set. */
8467         if (Globals.szUsershareTemplateShare[0]) {
8468                 /* We can't use lp_servicenumber here as we are recommending that
8469                    template shares have -valid=false set. */
8470                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8471                         if (ServicePtrs[snum_template]->szService &&
8472                                         strequal(ServicePtrs[snum_template]->szService,
8473                                                 Globals.szUsershareTemplateShare)) {
8474                                 break;
8475                         }
8476                 }
8477
8478                 if (snum_template == -1) {
8479                         DEBUG(0,("load_usershare_service: usershare template share %s "
8480                                 "does not exist.\n",
8481                                 Globals.szUsershareTemplateShare ));
8482                         return -1;
8483                 }
8484         }
8485
8486         return process_usershare_file(usersharepath, servicename, snum_template);
8487 }
8488
8489 /***************************************************************************
8490  Load all user defined shares from the user share directory.
8491  We only do this if we're enumerating the share list.
8492  This is the function that can delete usershares that have
8493  been removed.
8494 ***************************************************************************/
8495
8496 int load_usershare_shares(struct smbd_server_connection *sconn,
8497                           bool (*snumused) (struct smbd_server_connection *, int))
8498 {
8499         DIR *dp;
8500         SMB_STRUCT_STAT sbuf;
8501         struct dirent *de;
8502         int num_usershares = 0;
8503         int max_user_shares = Globals.iUsershareMaxShares;
8504         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8505         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8506         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8507         int iService;
8508         int snum_template = -1;
8509         const char *usersharepath = Globals.szUsersharePath;
8510         int ret = lp_numservices();
8511
8512         if (max_user_shares == 0 || *usersharepath == '\0') {
8513                 return lp_numservices();
8514         }
8515
8516         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8517                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8518                         usersharepath, strerror(errno) ));
8519                 return ret;
8520         }
8521
8522         /*
8523          * This directory must be owned by root, and have the 't' bit set.
8524          * It also must not be writable by "other".
8525          */
8526
8527 #ifdef S_ISVTX
8528         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8529 #else
8530         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8531 #endif
8532                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8533                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8534                         usersharepath ));
8535                 return ret;
8536         }
8537
8538         /* Ensure the template share exists if it's set. */
8539         if (Globals.szUsershareTemplateShare[0]) {
8540                 /* We can't use lp_servicenumber here as we are recommending that
8541                    template shares have -valid=false set. */
8542                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8543                         if (ServicePtrs[snum_template]->szService &&
8544                                         strequal(ServicePtrs[snum_template]->szService,
8545                                                 Globals.szUsershareTemplateShare)) {
8546                                 break;
8547                         }
8548                 }
8549
8550                 if (snum_template == -1) {
8551                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8552                                 "does not exist.\n",
8553                                 Globals.szUsershareTemplateShare ));
8554                         return ret;
8555                 }
8556         }
8557
8558         /* Mark all existing usershares as pending delete. */
8559         for (iService = iNumServices - 1; iService >= 0; iService--) {
8560                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8561                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8562                 }
8563         }
8564
8565         dp = opendir(usersharepath);
8566         if (!dp) {
8567                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8568                         usersharepath, strerror(errno) ));
8569                 return ret;
8570         }
8571
8572         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8573                         (de = readdir(dp));
8574                         num_dir_entries++ ) {
8575                 int r;
8576                 const char *n = de->d_name;
8577
8578                 /* Ignore . and .. */
8579                 if (*n == '.') {
8580                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8581                                 continue;
8582                         }
8583                 }
8584
8585                 if (n[0] == ':') {
8586                         /* Temporary file used when creating a share. */
8587                         num_tmp_dir_entries++;
8588                 }
8589
8590                 /* Allow 20% tmp entries. */
8591                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8592                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8593                                 "in directory %s\n",
8594                                 num_tmp_dir_entries, usersharepath));
8595                         break;
8596                 }
8597
8598                 r = process_usershare_file(usersharepath, n, snum_template);
8599                 if (r == 0) {
8600                         /* Update the services count. */
8601                         num_usershares++;
8602                         if (num_usershares >= max_user_shares) {
8603                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8604                                         "on file %s in directory %s\n",
8605                                         n, usersharepath ));
8606                                 break;
8607                         }
8608                 } else if (r == -1) {
8609                         num_bad_dir_entries++;
8610                 }
8611
8612                 /* Allow 20% bad entries. */
8613                 if (num_bad_dir_entries > allowed_bad_entries) {
8614                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8615                                 "in directory %s\n",
8616                                 num_bad_dir_entries, usersharepath));
8617                         break;
8618                 }
8619
8620                 /* Allow 20% bad entries. */
8621                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8622                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8623                         "in directory %s\n",
8624                         num_dir_entries, usersharepath));
8625                         break;
8626                 }
8627         }
8628
8629         closedir(dp);
8630
8631         /* Sweep through and delete any non-refreshed usershares that are
8632            not currently in use. */
8633         for (iService = iNumServices - 1; iService >= 0; iService--) {
8634                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8635                         if (snumused && snumused(sconn, iService)) {
8636                                 continue;
8637                         }
8638                         /* Remove from the share ACL db. */
8639                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8640                                 lp_servicename(iService) ));
8641                         delete_share_security(lp_servicename(iService));
8642                         free_service_byindex(iService);
8643                 }
8644         }
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();
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(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(int snum)
9033 {
9034         char *ret;
9035         const char *label = lp_volume(snum);
9036         if (!*label) {
9037                 label = lp_servicename(snum);
9038         }
9039
9040         /* This returns a 33 byte guarenteed null terminated string. */
9041         ret = talloc_strndup(talloc_tos(), 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                         lp_do_parameter(snum, "copy", lp_servicename(snum));
9148         }
9149 }
9150
9151
9152 /***********************************************************
9153  Set the global name resolution order (used in smbclient).
9154 ************************************************************/
9155
9156 void lp_set_name_resolve_order(const char *new_order)
9157 {
9158         string_set(&Globals.szNameResolveOrder, new_order);
9159 }
9160
9161 const char *lp_printername(int snum)
9162 {
9163         const char *ret = lp__printername(snum);
9164         if (ret == NULL || (ret != NULL && *ret == '\0'))
9165                 ret = lp_const_servicename(snum);
9166
9167         return ret;
9168 }
9169
9170
9171 /***********************************************************
9172  Allow daemons such as winbindd to fix their logfile name.
9173 ************************************************************/
9174
9175 void lp_set_logfile(const char *name)
9176 {
9177         string_set(&Globals.logfile, name);
9178         debug_set_logfile(name);
9179 }
9180
9181 /*******************************************************************
9182  Return the max print jobs per queue.
9183 ********************************************************************/
9184
9185 int lp_maxprintjobs(int snum)
9186 {
9187         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9188         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9189                 maxjobs = PRINT_MAX_JOBID - 1;
9190
9191         return maxjobs;
9192 }
9193
9194 const char *lp_printcapname(void)
9195 {
9196         if ((Globals.szPrintcapname != NULL) &&
9197             (Globals.szPrintcapname[0] != '\0'))
9198                 return Globals.szPrintcapname;
9199
9200         if (sDefault.iPrinting == PRINT_CUPS) {
9201 #ifdef HAVE_CUPS
9202                 return "cups";
9203 #else
9204                 return "lpstat";
9205 #endif
9206         }
9207
9208         if (sDefault.iPrinting == PRINT_BSD)
9209                 return "/etc/printcap";
9210
9211         return PRINTCAP_NAME;
9212 }
9213
9214 static uint32 spoolss_state;
9215
9216 bool lp_disable_spoolss( void )
9217 {
9218         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9219                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9220
9221         return spoolss_state == SVCCTL_STOPPED ? true : false;
9222 }
9223
9224 void lp_set_spoolss_state( uint32 state )
9225 {
9226         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9227
9228         spoolss_state = state;
9229 }
9230
9231 uint32 lp_get_spoolss_state( void )
9232 {
9233         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9234 }
9235
9236 /*******************************************************************
9237  Ensure we don't use sendfile if server smb signing is active.
9238 ********************************************************************/
9239
9240 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
9241 {
9242         bool sign_active = false;
9243
9244         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9245         if (get_Protocol() < PROTOCOL_NT1) {
9246                 return false;
9247         }
9248         if (signing_state) {
9249                 sign_active = smb_signing_is_active(signing_state);
9250         }
9251         return (lp__use_sendfile(snum) &&
9252                         (get_remote_arch() != RA_WIN95) &&
9253                         !sign_active);
9254 }
9255
9256 /*******************************************************************
9257  Turn off sendfile if we find the underlying OS doesn't support it.
9258 ********************************************************************/
9259
9260 void set_use_sendfile(int snum, bool val)
9261 {
9262         if (LP_SNUM_OK(snum))
9263                 ServicePtrs[snum]->bUseSendfile = val;
9264         else
9265                 sDefault.bUseSendfile = val;
9266 }
9267
9268 /*******************************************************************
9269  Turn off storing DOS attributes if this share doesn't support it.
9270 ********************************************************************/
9271
9272 void set_store_dos_attributes(int snum, bool val)
9273 {
9274         if (!LP_SNUM_OK(snum))
9275                 return;
9276         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9277 }
9278
9279 void lp_set_mangling_method(const char *new_method)
9280 {
9281         string_set(&Globals.szManglingMethod, new_method);
9282 }
9283
9284 /*******************************************************************
9285  Global state for POSIX pathname processing.
9286 ********************************************************************/
9287
9288 static bool posix_pathnames;
9289
9290 bool lp_posix_pathnames(void)
9291 {
9292         return posix_pathnames;
9293 }
9294
9295 /*******************************************************************
9296  Change everything needed to ensure POSIX pathname processing (currently
9297  not much).
9298 ********************************************************************/
9299
9300 void lp_set_posix_pathnames(void)
9301 {
9302         posix_pathnames = true;
9303 }
9304
9305 /*******************************************************************
9306  Global state for POSIX lock processing - CIFS unix extensions.
9307 ********************************************************************/
9308
9309 bool posix_default_lock_was_set;
9310 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9311
9312 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9313 {
9314         if (posix_default_lock_was_set) {
9315                 return posix_cifsx_locktype;
9316         } else {
9317                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9318         }
9319 }
9320
9321 /*******************************************************************
9322 ********************************************************************/
9323
9324 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9325 {
9326         posix_default_lock_was_set = true;
9327         posix_cifsx_locktype = val;
9328 }
9329
9330 int lp_min_receive_file_size(void)
9331 {
9332         if (Globals.iminreceivefile < 0) {
9333                 return 0;
9334         }
9335         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9336 }
9337
9338 /*******************************************************************
9339  If socket address is an empty character string, it is necessary to 
9340  define it as "0.0.0.0". 
9341 ********************************************************************/
9342
9343 const char *lp_socket_address(void)
9344 {
9345         char *sock_addr = Globals.szSocketAddress;
9346
9347         if (sock_addr[0] == '\0'){
9348                 string_set(&Globals.szSocketAddress, "0.0.0.0");
9349         }
9350         return  Globals.szSocketAddress;
9351 }
9352
9353 /*******************************************************************
9354  Safe wide links checks.
9355  This helper function always verify the validity of wide links,
9356  even after a configuration file reload.
9357 ********************************************************************/
9358
9359 static bool lp_widelinks_internal(int snum)
9360 {
9361         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
9362                         sDefault.bWidelinks);
9363 }
9364
9365 void widelinks_warning(int snum)
9366 {
9367         if (lp_allow_insecure_widelinks()) {
9368                 return;
9369         }
9370
9371         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
9372                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
9373                         "These parameters are incompatible. "
9374                         "Wide links will be disabled for this share.\n",
9375                         lp_servicename(snum) ));
9376         }
9377 }
9378
9379 bool lp_widelinks(int snum)
9380 {
9381         /* wide links is always incompatible with unix extensions */
9382         if (lp_unix_extensions()) {
9383                 /*
9384                  * Unless we have "allow insecure widelinks"
9385                  * turned on.
9386                  */
9387                 if (!lp_allow_insecure_widelinks()) {
9388                         return false;
9389                 }
9390         }
9391
9392         return lp_widelinks_internal(snum);
9393 }
9394
9395 bool lp_writeraw(void)
9396 {
9397         if (lp_async_smb_echo_handler()) {
9398                 return false;
9399         }
9400         return lp__writeraw();
9401 }
9402
9403 bool lp_readraw(void)
9404 {
9405         if (lp_async_smb_echo_handler()) {
9406                 return false;
9407         }
9408         return lp__readraw();
9409 }
9410
9411 int lp_server_role(void)
9412 {
9413         return lp_find_server_role(lp__server_role(),
9414                                    lp_security(),
9415                                    lp_domain_logons(),
9416                                    lp_domain_master_true_or_auto());
9417 }
9418
9419 const char *lp_ctdbd_socket(void)
9420 {
9421         const char *result = lp__ctdbd_socket();
9422
9423 #ifdef CLUSTER_SUPPORT
9424         if ((result == NULL) || (*result == '\0')) {
9425                 return CTDB_PATH;
9426         }
9427 #endif
9428         return result;
9429 }