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