lib/param: Make lp_usershare_max_shares() a common parameter
[metze/samba/wip.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    Copyright (C) Michael Adam 2008
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011
15
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *  
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55
56 #include "includes.h"
57 #include "system/filesys.h"
58 #include "util_tdb.h"
59 #include "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_STRING(configfile, szConfigFile)
5269
5270 #include "lib/param/param_functions.c"
5271
5272 FN_LOCAL_STRING(servicename, szService)
5273 FN_LOCAL_CONST_STRING(const_servicename, szService)
5274
5275 /* local prototypes */
5276
5277 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
5278 static const char *get_boolean(bool bool_value);
5279 static int getservicebyname(const char *pszServiceName,
5280                             struct loadparm_service *pserviceDest);
5281 static void copy_service(struct loadparm_service *pserviceDest,
5282                          struct loadparm_service *pserviceSource,
5283                          struct bitmap *pcopymapDest);
5284 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
5285                          void *userdata);
5286 static bool do_section(const char *pszSectionName, void *userdata);
5287 static void init_copymap(struct loadparm_service *pservice);
5288 static bool hash_a_service(const char *name, int number);
5289 static void free_service_byindex(int iService);
5290 static void show_parameter(int parmIndex);
5291 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
5292
5293 /*
5294  * This is a helper function for parametrical options support.  It returns a
5295  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5296  * parametrical functions are quite simple
5297  */
5298 static struct parmlist_entry *get_parametrics_by_service(struct loadparm_service *service, const char *type,
5299                                                            const char *option)
5300 {
5301         bool global_section = false;
5302         char* param_key;
5303         struct parmlist_entry *data;
5304
5305         if (service == NULL) {
5306                 data = Globals.param_opt;
5307                 global_section = true;
5308         } else {
5309                 data = service->param_opt;
5310         }
5311
5312         if (asprintf(&param_key, "%s:%s", type, option) == -1) {
5313                 DEBUG(0,("asprintf failed!\n"));
5314                 return NULL;
5315         }
5316
5317         while (data) {
5318                 if (strwicmp(data->key, param_key) == 0) {
5319                         string_free(&param_key);
5320                         return data;
5321                 }
5322                 data = data->next;
5323         }
5324
5325         if (!global_section) {
5326                 /* Try to fetch the same option but from globals */
5327                 /* but only if we are not already working with Globals */
5328                 data = Globals.param_opt;
5329                 while (data) {
5330                         if (strwicmp(data->key, param_key) == 0) {
5331                                 string_free(&param_key);
5332                                 return data;
5333                         }
5334                         data = data->next;
5335                 }
5336         }
5337
5338         string_free(&param_key);
5339
5340         return NULL;
5341 }
5342
5343 /*
5344  * This is a helper function for parametrical options support.  It returns a
5345  * pointer to parametrical option value if it exists or NULL otherwise. Actual
5346  * parametrical functions are quite simple
5347  */
5348 static struct parmlist_entry *get_parametrics(int snum, const char *type,
5349                                                 const char *option)
5350 {
5351         if (snum >= iNumServices) return NULL;
5352
5353         if (snum < 0) {
5354                 return get_parametrics_by_service(NULL, type, option);
5355         } else {
5356                 return get_parametrics_by_service(ServicePtrs[snum], type, option);
5357         }
5358 }
5359
5360
5361 #define MISSING_PARAMETER(name) \
5362     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
5363
5364 /*******************************************************************
5365 convenience routine to return int parameters.
5366 ********************************************************************/
5367 static int lp_int(const char *s)
5368 {
5369
5370         if (!s || !*s) {
5371                 MISSING_PARAMETER(lp_int);
5372                 return (-1);
5373         }
5374
5375         return (int)strtol(s, NULL, 0);
5376 }
5377
5378 /*******************************************************************
5379 convenience routine to return unsigned long parameters.
5380 ********************************************************************/
5381 static unsigned long lp_ulong(const char *s)
5382 {
5383
5384         if (!s || !*s) {
5385                 MISSING_PARAMETER(lp_ulong);
5386                 return (0);
5387         }
5388
5389         return strtoul(s, NULL, 0);
5390 }
5391
5392 /*******************************************************************
5393 convenience routine to return boolean parameters.
5394 ********************************************************************/
5395 static bool lp_bool(const char *s)
5396 {
5397         bool ret = false;
5398
5399         if (!s || !*s) {
5400                 MISSING_PARAMETER(lp_bool);
5401                 return false;
5402         }
5403
5404         if (!set_boolean(s, &ret)) {
5405                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
5406                 return false;
5407         }
5408
5409         return ret;
5410 }
5411
5412 /*******************************************************************
5413 convenience routine to return enum parameters.
5414 ********************************************************************/
5415 static int lp_enum(const char *s,const struct enum_list *_enum)
5416 {
5417         int i;
5418
5419         if (!s || !*s || !_enum) {
5420                 MISSING_PARAMETER(lp_enum);
5421                 return (-1);
5422         }
5423
5424         for (i=0; _enum[i].name; i++) {
5425                 if (strequal(_enum[i].name,s))
5426                         return _enum[i].value;
5427         }
5428
5429         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
5430         return (-1);
5431 }
5432
5433 #undef MISSING_PARAMETER
5434
5435 /* Return parametric option from a given service. Type is a part of option before ':' */
5436 /* Parametric option has following syntax: 'Type: option = value' */
5437 char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
5438 {
5439         struct parmlist_entry *data = get_parametrics(snum, type, option);
5440
5441         if (data == NULL||data->value==NULL) {
5442                 if (def) {
5443                         return lp_string(ctx, def);
5444                 } else {
5445                         return NULL;
5446                 }
5447         }
5448
5449         return lp_string(ctx, data->value);
5450 }
5451
5452 /* Return parametric option from a given service. Type is a part of option before ':' */
5453 /* Parametric option has following syntax: 'Type: option = value' */
5454 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
5455 {
5456         struct parmlist_entry *data = get_parametrics(snum, type, option);
5457
5458         if (data == NULL||data->value==NULL)
5459                 return def;
5460
5461         return data->value;
5462 }
5463
5464 const char *lp_parm_const_string_service(struct loadparm_service *service, const char *type, const char *option)
5465 {
5466         struct parmlist_entry *data = get_parametrics_by_service(service, type, option);
5467
5468         if (data == NULL||data->value==NULL)
5469                 return NULL;
5470
5471         return data->value;
5472 }
5473
5474
5475 /* Return parametric option from a given service. Type is a part of option before ':' */
5476 /* Parametric option has following syntax: 'Type: option = value' */
5477
5478 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
5479 {
5480         struct parmlist_entry *data = get_parametrics(snum, type, option);
5481
5482         if (data == NULL||data->value==NULL)
5483                 return (const char **)def;
5484
5485         if (data->list==NULL) {
5486                 data->list = str_list_make_v3(NULL, data->value, NULL);
5487         }
5488
5489         return (const char **)data->list;
5490 }
5491
5492 /* Return parametric option from a given service. Type is a part of option before ':' */
5493 /* Parametric option has following syntax: 'Type: option = value' */
5494
5495 int lp_parm_int(int snum, const char *type, const char *option, int def)
5496 {
5497         struct parmlist_entry *data = get_parametrics(snum, type, option);
5498
5499         if (data && data->value && *data->value)
5500                 return lp_int(data->value);
5501
5502         return def;
5503 }
5504
5505 /* Return parametric option from a given service. Type is a part of option before ':' */
5506 /* Parametric option has following syntax: 'Type: option = value' */
5507
5508 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
5509 {
5510         struct parmlist_entry *data = get_parametrics(snum, type, option);
5511
5512         if (data && data->value && *data->value)
5513                 return lp_ulong(data->value);
5514
5515         return def;
5516 }
5517
5518 /* Return parametric option from a given service. Type is a part of option before ':' */
5519 /* Parametric option has following syntax: 'Type: option = value' */
5520
5521 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
5522 {
5523         struct parmlist_entry *data = get_parametrics(snum, type, option);
5524
5525         if (data && data->value && *data->value)
5526                 return lp_bool(data->value);
5527
5528         return def;
5529 }
5530
5531 /* Return parametric option from a given service. Type is a part of option before ':' */
5532 /* Parametric option has following syntax: 'Type: option = value' */
5533
5534 int lp_parm_enum(int snum, const char *type, const char *option,
5535                  const struct enum_list *_enum, int def)
5536 {
5537         struct parmlist_entry *data = get_parametrics(snum, type, option);
5538
5539         if (data && data->value && *data->value && _enum)
5540                 return lp_enum(data->value, _enum);
5541
5542         return def;
5543 }
5544
5545
5546 /***************************************************************************
5547  Initialise a service to the defaults.
5548 ***************************************************************************/
5549
5550 static void init_service(struct loadparm_service *pservice)
5551 {
5552         memset((char *)pservice, '\0', sizeof(struct loadparm_service));
5553         copy_service(pservice, &sDefault, NULL);
5554 }
5555
5556
5557 /**
5558  * free a param_opts structure.
5559  * param_opts handling should be moved to talloc;
5560  * then this whole functions reduces to a TALLOC_FREE().
5561  */
5562
5563 static void free_param_opts(struct parmlist_entry **popts)
5564 {
5565         struct parmlist_entry *opt, *next_opt;
5566
5567         if (popts == NULL) {
5568                 return;
5569         }
5570
5571         if (*popts != NULL) {
5572                 DEBUG(5, ("Freeing parametrics:\n"));
5573         }
5574         opt = *popts;
5575         while (opt != NULL) {
5576                 string_free(&opt->key);
5577                 string_free(&opt->value);
5578                 TALLOC_FREE(opt->list);
5579                 next_opt = opt->next;
5580                 SAFE_FREE(opt);
5581                 opt = next_opt;
5582         }
5583         *popts = NULL;
5584 }
5585
5586 /***************************************************************************
5587  Free the dynamically allocated parts of a service struct.
5588 ***************************************************************************/
5589
5590 static void free_service(struct loadparm_service *pservice)
5591 {
5592         if (!pservice)
5593                 return;
5594
5595         if (pservice->szService)
5596                 DEBUG(5, ("free_service: Freeing service %s\n",
5597                        pservice->szService));
5598
5599         free_parameters(pservice);
5600
5601         string_free(&pservice->szService);
5602         TALLOC_FREE(pservice->copymap);
5603
5604         free_param_opts(&pservice->param_opt);
5605
5606         ZERO_STRUCTP(pservice);
5607 }
5608
5609
5610 /***************************************************************************
5611  remove a service indexed in the ServicePtrs array from the ServiceHash
5612  and free the dynamically allocated parts
5613 ***************************************************************************/
5614
5615 static void free_service_byindex(int idx)
5616 {
5617         if ( !LP_SNUM_OK(idx) ) 
5618                 return;
5619
5620         ServicePtrs[idx]->valid = false;
5621         invalid_services[num_invalid_services++] = idx;
5622
5623         /* we have to cleanup the hash record */
5624
5625         if (ServicePtrs[idx]->szService) {
5626                 char *canon_name = canonicalize_servicename(
5627                         talloc_tos(),
5628                         ServicePtrs[idx]->szService );
5629
5630                 dbwrap_delete_bystring(ServiceHash, canon_name );
5631                 TALLOC_FREE(canon_name);
5632         }
5633
5634         free_service(ServicePtrs[idx]);
5635 }
5636
5637 /***************************************************************************
5638  Add a new service to the services array initialising it with the given 
5639  service. 
5640 ***************************************************************************/
5641
5642 static int add_a_service(const struct loadparm_service *pservice, const char *name)
5643 {
5644         int i;
5645         struct loadparm_service tservice;
5646         int num_to_alloc = iNumServices + 1;
5647
5648         tservice = *pservice;
5649
5650         /* it might already exist */
5651         if (name) {
5652                 i = getservicebyname(name, NULL);
5653                 if (i >= 0) {
5654                         return (i);
5655                 }
5656         }
5657
5658         /* find an invalid one */
5659         i = iNumServices;
5660         if (num_invalid_services > 0) {
5661                 i = invalid_services[--num_invalid_services];
5662         }
5663
5664         /* if not, then create one */
5665         if (i == iNumServices) {
5666                 struct loadparm_service **tsp;
5667                 int *tinvalid;
5668
5669                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, struct loadparm_service *, num_to_alloc);
5670                 if (tsp == NULL) {
5671                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
5672                         return (-1);
5673                 }
5674                 ServicePtrs = tsp;
5675                 ServicePtrs[iNumServices] = SMB_MALLOC_P(struct loadparm_service);
5676                 if (!ServicePtrs[iNumServices]) {
5677                         DEBUG(0,("add_a_service: out of memory!\n"));
5678                         return (-1);
5679                 }
5680                 iNumServices++;
5681
5682                 /* enlarge invalid_services here for now... */
5683                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
5684                                              num_to_alloc);
5685                 if (tinvalid == NULL) {
5686                         DEBUG(0,("add_a_service: failed to enlarge "
5687                                  "invalid_services!\n"));
5688                         return (-1);
5689                 }
5690                 invalid_services = tinvalid;
5691         } else {
5692                 free_service_byindex(i);
5693         }
5694
5695         ServicePtrs[i]->valid = true;
5696
5697         init_service(ServicePtrs[i]);
5698         copy_service(ServicePtrs[i], &tservice, NULL);
5699         if (name)
5700                 string_set(&ServicePtrs[i]->szService, name);
5701
5702         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
5703                 i, ServicePtrs[i]->szService));
5704
5705         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
5706                 return (-1);
5707         }
5708
5709         return (i);
5710 }
5711
5712 /***************************************************************************
5713   Convert a string to uppercase and remove whitespaces.
5714 ***************************************************************************/
5715
5716 char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
5717 {
5718         char *result;
5719
5720         if ( !src ) {
5721                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
5722                 return NULL;
5723         }
5724
5725         result = talloc_strdup(ctx, src);
5726         SMB_ASSERT(result != NULL);
5727
5728         strlower_m(result);
5729         return result;
5730 }
5731
5732 /***************************************************************************
5733   Add a name/index pair for the services array to the hash table.
5734 ***************************************************************************/
5735
5736 static bool hash_a_service(const char *name, int idx)
5737 {
5738         char *canon_name;
5739
5740         if ( !ServiceHash ) {
5741                 DEBUG(10,("hash_a_service: creating servicehash\n"));
5742                 ServiceHash = db_open_rbt(NULL);
5743                 if ( !ServiceHash ) {
5744                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
5745                         return false;
5746                 }
5747         }
5748
5749         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
5750                 idx, name));
5751
5752         canon_name = canonicalize_servicename(talloc_tos(), name );
5753
5754         dbwrap_store_bystring(ServiceHash, canon_name,
5755                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
5756                               TDB_REPLACE);
5757
5758         TALLOC_FREE(canon_name);
5759
5760         return true;
5761 }
5762
5763 /***************************************************************************
5764  Add a new home service, with the specified home directory, defaults coming
5765  from service ifrom.
5766 ***************************************************************************/
5767
5768 bool lp_add_home(const char *pszHomename, int iDefaultService,
5769                  const char *user, const char *pszHomedir)
5770 {
5771         int i;
5772
5773         if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
5774                         pszHomedir[0] == '\0') {
5775                 return false;
5776         }
5777
5778         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
5779
5780         if (i < 0)
5781                 return false;
5782
5783         if (!(*(ServicePtrs[iDefaultService]->szPath))
5784             || strequal(ServicePtrs[iDefaultService]->szPath,
5785                         lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM))) {
5786                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
5787         }
5788
5789         if (!(*(ServicePtrs[i]->comment))) {
5790                 char *comment = NULL;
5791                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
5792                         return false;
5793                 }
5794                 string_set(&ServicePtrs[i]->comment, comment);
5795                 SAFE_FREE(comment);
5796         }
5797
5798         /* set the browseable flag from the global default */
5799
5800         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5801         ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
5802
5803         ServicePtrs[i]->autoloaded = true;
5804
5805         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
5806                user, ServicePtrs[i]->szPath ));
5807
5808         return true;
5809 }
5810
5811 /***************************************************************************
5812  Add a new service, based on an old one.
5813 ***************************************************************************/
5814
5815 int lp_add_service(const char *pszService, int iDefaultService)
5816 {
5817         if (iDefaultService < 0) {
5818                 return add_a_service(&sDefault, pszService);
5819         }
5820
5821         return (add_a_service(ServicePtrs[iDefaultService], pszService));
5822 }
5823
5824 /***************************************************************************
5825  Add the IPC service.
5826 ***************************************************************************/
5827
5828 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
5829 {
5830         char *comment = NULL;
5831         int i = add_a_service(&sDefault, ipc_name);
5832
5833         if (i < 0)
5834                 return false;
5835
5836         if (asprintf(&comment, "IPC Service (%s)",
5837                                 Globals.szServerString) < 0) {
5838                 return false;
5839         }
5840
5841         string_set(&ServicePtrs[i]->szPath, tmpdir());
5842         string_set(&ServicePtrs[i]->szUsername, "");
5843         string_set(&ServicePtrs[i]->comment, comment);
5844         string_set(&ServicePtrs[i]->fstype, "IPC");
5845         ServicePtrs[i]->iMaxConnections = 0;
5846         ServicePtrs[i]->bAvailable = true;
5847         ServicePtrs[i]->bRead_only = true;
5848         ServicePtrs[i]->bGuest_only = false;
5849         ServicePtrs[i]->bAdministrative_share = true;
5850         ServicePtrs[i]->bGuest_ok = guest_ok;
5851         ServicePtrs[i]->bPrint_ok = false;
5852         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5853
5854         DEBUG(3, ("adding IPC service\n"));
5855
5856         SAFE_FREE(comment);
5857         return true;
5858 }
5859
5860 /***************************************************************************
5861  Add a new printer service, with defaults coming from service iFrom.
5862 ***************************************************************************/
5863
5864 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
5865 {
5866         const char *comment = "From Printcap";
5867         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
5868
5869         if (i < 0)
5870                 return false;
5871
5872         /* note that we do NOT default the availability flag to true - */
5873         /* we take it from the default service passed. This allows all */
5874         /* dynamic printers to be disabled by disabling the [printers] */
5875         /* entry (if/when the 'available' keyword is implemented!).    */
5876
5877         /* the printer name is set to the service name. */
5878         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
5879         string_set(&ServicePtrs[i]->comment, comment);
5880
5881         /* set the browseable flag from the gloabl default */
5882         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
5883
5884         /* Printers cannot be read_only. */
5885         ServicePtrs[i]->bRead_only = false;
5886         /* No share modes on printer services. */
5887         ServicePtrs[i]->bShareModes = false;
5888         /* No oplocks on printer services. */
5889         ServicePtrs[i]->bOpLocks = false;
5890         /* Printer services must be printable. */
5891         ServicePtrs[i]->bPrint_ok = true;
5892
5893         DEBUG(3, ("adding printer service %s\n", pszPrintername));
5894
5895         return true;
5896 }
5897
5898
5899 /***************************************************************************
5900  Check whether the given parameter name is valid.
5901  Parametric options (names containing a colon) are considered valid.
5902 ***************************************************************************/
5903
5904 bool lp_parameter_is_valid(const char *pszParmName)
5905 {
5906         return ((map_parameter(pszParmName) != -1) ||
5907                 (strchr(pszParmName, ':') != NULL));
5908 }
5909
5910 /***************************************************************************
5911  Check whether the given name is the name of a global parameter.
5912  Returns true for strings belonging to parameters of class
5913  P_GLOBAL, false for all other strings, also for parametric options
5914  and strings not belonging to any option.
5915 ***************************************************************************/
5916
5917 bool lp_parameter_is_global(const char *pszParmName)
5918 {
5919         int num = map_parameter(pszParmName);
5920
5921         if (num >= 0) {
5922                 return (parm_table[num].p_class == P_GLOBAL);
5923         }
5924
5925         return false;
5926 }
5927
5928 /**************************************************************************
5929  Check whether the given name is the canonical name of a parameter.
5930  Returns false if it is not a valid parameter Name.
5931  For parametric options, true is returned.
5932 **************************************************************************/
5933
5934 bool lp_parameter_is_canonical(const char *parm_name)
5935 {
5936         if (!lp_parameter_is_valid(parm_name)) {
5937                 return false;
5938         }
5939
5940         return (map_parameter(parm_name) ==
5941                 map_parameter_canonical(parm_name, NULL));
5942 }
5943
5944 /**************************************************************************
5945  Determine the canonical name for a parameter.
5946  Indicate when it is an inverse (boolean) synonym instead of a
5947  "usual" synonym.
5948 **************************************************************************/
5949
5950 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
5951                                bool *inverse)
5952 {
5953         int num;
5954
5955         if (!lp_parameter_is_valid(parm_name)) {
5956                 *canon_parm = NULL;
5957                 return false;
5958         }
5959
5960         num = map_parameter_canonical(parm_name, inverse);
5961         if (num < 0) {
5962                 /* parametric option */
5963                 *canon_parm = parm_name;
5964         } else {
5965                 *canon_parm = parm_table[num].label;
5966         }
5967
5968         return true;
5969
5970 }
5971
5972 /**************************************************************************
5973  Determine the canonical name for a parameter.
5974  Turn the value given into the inverse boolean expression when
5975  the synonym is an invers boolean synonym.
5976
5977  Return true if parm_name is a valid parameter name and
5978  in case it is an invers boolean synonym, if the val string could
5979  successfully be converted to the reverse bool.
5980  Return false in all other cases.
5981 **************************************************************************/
5982
5983 bool lp_canonicalize_parameter_with_value(const char *parm_name,
5984                                           const char *val,
5985                                           const char **canon_parm,
5986                                           const char **canon_val)
5987 {
5988         int num;
5989         bool inverse;
5990
5991         if (!lp_parameter_is_valid(parm_name)) {
5992                 *canon_parm = NULL;
5993                 *canon_val = NULL;
5994                 return false;
5995         }
5996
5997         num = map_parameter_canonical(parm_name, &inverse);
5998         if (num < 0) {
5999                 /* parametric option */
6000                 *canon_parm = parm_name;
6001                 *canon_val = val;
6002         } else {
6003                 *canon_parm = parm_table[num].label;
6004                 if (inverse) {
6005                         if (!lp_invert_boolean(val, canon_val)) {
6006                                 *canon_val = NULL;
6007                                 return false;
6008                         }
6009                 } else {
6010                         *canon_val = val;
6011                 }
6012         }
6013
6014         return true;
6015 }
6016
6017 /***************************************************************************
6018  Map a parameter's string representation to something we can use. 
6019  Returns false if the parameter string is not recognised, else TRUE.
6020 ***************************************************************************/
6021
6022 static int map_parameter(const char *pszParmName)
6023 {
6024         int iIndex;
6025
6026         if (*pszParmName == '-' && !strequal(pszParmName, "-valid"))
6027                 return (-1);
6028
6029         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
6030                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
6031                         return (iIndex);
6032
6033         /* Warn only if it isn't parametric option */
6034         if (strchr(pszParmName, ':') == NULL)
6035                 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
6036         /* We do return 'fail' for parametric options as well because they are
6037            stored in different storage
6038          */
6039         return (-1);
6040 }
6041
6042 /***************************************************************************
6043  Map a parameter's string representation to the index of the canonical
6044  form of the parameter (it might be a synonym).
6045  Returns -1 if the parameter string is not recognised.
6046 ***************************************************************************/
6047
6048 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
6049 {
6050         int parm_num, canon_num;
6051         bool loc_inverse = false;
6052
6053         parm_num = map_parameter(pszParmName);
6054         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
6055                 /* invalid, parametric or no canidate for synonyms ... */
6056                 goto done;
6057         }
6058
6059         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
6060                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
6061                         parm_num = canon_num;
6062                         goto done;
6063                 }
6064         }
6065
6066 done:
6067         if (inverse != NULL) {
6068                 *inverse = loc_inverse;
6069         }
6070         return parm_num;
6071 }
6072
6073 /***************************************************************************
6074  return true if parameter number parm1 is a synonym of parameter
6075  number parm2 (parm2 being the principal name).
6076  set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
6077  false otherwise.
6078 ***************************************************************************/
6079
6080 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
6081 {
6082         if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
6083             (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
6084             (parm_table[parm1].flags & FLAG_HIDE) &&
6085             !(parm_table[parm2].flags & FLAG_HIDE))
6086         {
6087                 if (inverse != NULL) {
6088                         if ((parm_table[parm1].type == P_BOOLREV) &&
6089                             (parm_table[parm2].type == P_BOOL))
6090                         {
6091                                 *inverse = true;
6092                         } else {
6093                                 *inverse = false;
6094                         }
6095                 }
6096                 return true;
6097         }
6098         return false;
6099 }
6100
6101 /***************************************************************************
6102  Show one parameter's name, type, [values,] and flags.
6103  (helper functions for show_parameter_list)
6104 ***************************************************************************/
6105
6106 static void show_parameter(int parmIndex)
6107 {
6108         int enumIndex, flagIndex;
6109         int parmIndex2;
6110         bool hadFlag;
6111         bool hadSyn;
6112         bool inverse;
6113         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
6114                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
6115                 "P_ENUM", "P_SEP"};
6116         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
6117                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
6118                 FLAG_HIDE};
6119         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
6120                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
6121                 "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
6122
6123         printf("%s=%s", parm_table[parmIndex].label,
6124                type[parm_table[parmIndex].type]);
6125         if (parm_table[parmIndex].type == P_ENUM) {
6126                 printf(",");
6127                 for (enumIndex=0;
6128                      parm_table[parmIndex].enum_list[enumIndex].name;
6129                      enumIndex++)
6130                 {
6131                         printf("%s%s",
6132                                enumIndex ? "|" : "",
6133                                parm_table[parmIndex].enum_list[enumIndex].name);
6134                 }
6135         }
6136         printf(",");
6137         hadFlag = false;
6138         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
6139                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
6140                         printf("%s%s",
6141                                 hadFlag ? "|" : "",
6142                                 flag_names[flagIndex]);
6143                         hadFlag = true;
6144                 }
6145         }
6146
6147         /* output synonyms */
6148         hadSyn = false;
6149         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
6150                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
6151                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
6152                                parm_table[parmIndex2].label);
6153                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
6154                         if (!hadSyn) {
6155                                 printf(" (synonyms: ");
6156                                 hadSyn = true;
6157                         } else {
6158                                 printf(", ");
6159                         }
6160                         printf("%s%s", parm_table[parmIndex2].label,
6161                                inverse ? "[i]" : "");
6162                 }
6163         }
6164         if (hadSyn) {
6165                 printf(")");
6166         }
6167
6168         printf("\n");
6169 }
6170
6171 /***************************************************************************
6172  Show all parameter's name, type, [values,] and flags.
6173 ***************************************************************************/
6174
6175 void show_parameter_list(void)
6176 {
6177         int classIndex, parmIndex;
6178         const char *section_names[] = { "local", "global", NULL};
6179
6180         for (classIndex=0; section_names[classIndex]; classIndex++) {
6181                 printf("[%s]\n", section_names[classIndex]);
6182                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
6183                         if (parm_table[parmIndex].p_class == classIndex) {
6184                                 show_parameter(parmIndex);
6185                         }
6186                 }
6187         }
6188 }
6189
6190 /***************************************************************************
6191  Check if a given string correctly represents a boolean value.
6192 ***************************************************************************/
6193
6194 bool lp_string_is_valid_boolean(const char *parm_value)
6195 {
6196         return set_boolean(parm_value, NULL);
6197 }
6198
6199 /***************************************************************************
6200  Get the standard string representation of a boolean value ("yes" or "no")
6201 ***************************************************************************/
6202
6203 static const char *get_boolean(bool bool_value)
6204 {
6205         static const char *yes_str = "yes";
6206         static const char *no_str = "no";
6207
6208         return (bool_value ? yes_str : no_str);
6209 }
6210
6211 /***************************************************************************
6212  Provide the string of the negated boolean value associated to the boolean
6213  given as a string. Returns false if the passed string does not correctly
6214  represent a boolean.
6215 ***************************************************************************/
6216
6217 bool lp_invert_boolean(const char *str, const char **inverse_str)
6218 {
6219         bool val;
6220
6221         if (!set_boolean(str, &val)) {
6222                 return false;
6223         }
6224
6225         *inverse_str = get_boolean(!val);
6226         return true;
6227 }
6228
6229 /***************************************************************************
6230  Provide the canonical string representation of a boolean value given
6231  as a string. Return true on success, false if the string given does
6232  not correctly represent a boolean.
6233 ***************************************************************************/
6234
6235 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
6236 {
6237         bool val;
6238
6239         if (!set_boolean(str, &val)) {
6240                 return false;
6241         }
6242
6243         *canon_str = get_boolean(val);
6244         return true;
6245 }
6246
6247 /***************************************************************************
6248 Find a service by name. Otherwise works like get_service.
6249 ***************************************************************************/
6250
6251 static int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
6252 {
6253         int iService = -1;
6254         char *canon_name;
6255         TDB_DATA data;
6256         NTSTATUS status;
6257
6258         if (ServiceHash == NULL) {
6259                 return -1;
6260         }
6261
6262         canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
6263
6264         status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
6265                                        &data);
6266
6267         if (NT_STATUS_IS_OK(status) &&
6268             (data.dptr != NULL) &&
6269             (data.dsize == sizeof(iService)))
6270         {
6271                 iService = *(int *)data.dptr;
6272         }
6273
6274         TALLOC_FREE(canon_name);
6275
6276         if ((iService != -1) && (LP_SNUM_OK(iService))
6277             && (pserviceDest != NULL)) {
6278                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
6279         }
6280
6281         return (iService);
6282 }
6283
6284 /* Return a pointer to a service by name.  Unlike getservicebyname, it does not copy the service */
6285 struct loadparm_service *lp_service(const char *pszServiceName)
6286 {
6287         int iService = getservicebyname(pszServiceName, NULL);
6288         if (iService == -1 || !LP_SNUM_OK(iService)) {
6289                 return NULL;
6290         }
6291         return ServicePtrs[iService];
6292 }
6293
6294 struct loadparm_service *lp_servicebynum(int snum)
6295 {
6296         if ((snum == -1) || !LP_SNUM_OK(snum)) {
6297                 return NULL;
6298         }
6299         return ServicePtrs[snum];
6300 }
6301
6302 struct loadparm_service *lp_default_loadparm_service()
6303 {
6304         return &sDefault;
6305 }
6306
6307
6308 /***************************************************************************
6309  Copy a service structure to another.
6310  If pcopymapDest is NULL then copy all fields
6311 ***************************************************************************/
6312
6313 /**
6314  * Add a parametric option to a parmlist_entry,
6315  * replacing old value, if already present.
6316  */
6317 static void set_param_opt(struct parmlist_entry **opt_list,
6318                           const char *opt_name,
6319                           const char *opt_value,
6320                           unsigned priority)
6321 {
6322         struct parmlist_entry *new_opt, *opt;
6323         bool not_added;
6324
6325         if (opt_list == NULL) {
6326                 return;
6327         }
6328
6329         opt = *opt_list;
6330         not_added = true;
6331
6332         /* Traverse destination */
6333         while (opt) {
6334                 /* If we already have same option, override it */
6335                 if (strwicmp(opt->key, opt_name) == 0) {
6336                         if ((opt->priority & FLAG_CMDLINE) &&
6337                             !(priority & FLAG_CMDLINE)) {
6338                                 /* it's been marked as not to be
6339                                    overridden */
6340                                 return;
6341                         }
6342                         string_free(&opt->value);
6343                         TALLOC_FREE(opt->list);
6344                         opt->value = SMB_STRDUP(opt_value);
6345                         opt->priority = priority;
6346                         not_added = false;
6347                         break;
6348                 }
6349                 opt = opt->next;
6350         }
6351         if (not_added) {
6352             new_opt = SMB_XMALLOC_P(struct parmlist_entry);
6353             new_opt->key = SMB_STRDUP(opt_name);
6354             new_opt->value = SMB_STRDUP(opt_value);
6355             new_opt->list = NULL;
6356             new_opt->priority = priority;
6357             DLIST_ADD(*opt_list, new_opt);
6358         }
6359 }
6360
6361 static void copy_service(struct loadparm_service *pserviceDest, struct loadparm_service *pserviceSource,
6362                          struct bitmap *pcopymapDest)
6363 {
6364         int i;
6365         bool bcopyall = (pcopymapDest == NULL);
6366         struct parmlist_entry *data;
6367
6368         for (i = 0; parm_table[i].label; i++)
6369                 if (parm_table[i].p_class == P_LOCAL &&
6370                     (bcopyall || bitmap_query(pcopymapDest,i))) {
6371                         void *src_ptr = lp_parm_ptr(pserviceSource, &parm_table[i]);
6372                         void *dest_ptr = lp_parm_ptr(pserviceDest, &parm_table[i]);
6373
6374                         switch (parm_table[i].type) {
6375                                 case P_BOOL:
6376                                 case P_BOOLREV:
6377                                         *(bool *)dest_ptr = *(bool *)src_ptr;
6378                                         break;
6379
6380                                 case P_INTEGER:
6381                                 case P_ENUM:
6382                                 case P_OCTAL:
6383                                 case P_BYTES:
6384                                         *(int *)dest_ptr = *(int *)src_ptr;
6385                                         break;
6386
6387                                 case P_CHAR:
6388                                         *(char *)dest_ptr = *(char *)src_ptr;
6389                                         break;
6390
6391                                 case P_STRING:
6392                                         string_set((char **)dest_ptr,
6393                                                    *(char **)src_ptr);
6394                                         break;
6395
6396                                 case P_USTRING:
6397                                 {
6398                                         char *upper_string = strupper_talloc(talloc_tos(), 
6399                                                                              *(char **)src_ptr);
6400                                         string_set((char **)dest_ptr,
6401                                                    upper_string);
6402                                         TALLOC_FREE(upper_string);
6403                                         break;
6404                                 }
6405                                 case P_LIST:
6406                                         TALLOC_FREE(*((char ***)dest_ptr));
6407                                         *((char ***)dest_ptr) = str_list_copy(NULL, 
6408                                                       *(const char ***)src_ptr);
6409                                         break;
6410                                 default:
6411                                         break;
6412                         }
6413                 }
6414
6415         if (bcopyall) {
6416                 init_copymap(pserviceDest);
6417                 if (pserviceSource->copymap)
6418                         bitmap_copy(pserviceDest->copymap,
6419                                     pserviceSource->copymap);
6420         }
6421
6422         data = pserviceSource->param_opt;
6423         while (data) {
6424                 set_param_opt(&pserviceDest->param_opt, data->key, data->value, data->priority);
6425                 data = data->next;
6426         }
6427 }
6428
6429 /***************************************************************************
6430 Check a service for consistency. Return false if the service is in any way
6431 incomplete or faulty, else true.
6432 ***************************************************************************/
6433
6434 bool service_ok(int iService)
6435 {
6436         bool bRetval;
6437
6438         bRetval = true;
6439         if (ServicePtrs[iService]->szService[0] == '\0') {
6440                 DEBUG(0, ("The following message indicates an internal error:\n"));
6441                 DEBUG(0, ("No service name in service entry.\n"));
6442                 bRetval = false;
6443         }
6444
6445         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
6446         /* I can't see why you'd want a non-printable printer service...        */
6447         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
6448                 if (!ServicePtrs[iService]->bPrint_ok) {
6449                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
6450                                ServicePtrs[iService]->szService));
6451                         ServicePtrs[iService]->bPrint_ok = true;
6452                 }
6453                 /* [printers] service must also be non-browsable. */
6454                 if (ServicePtrs[iService]->bBrowseable)
6455                         ServicePtrs[iService]->bBrowseable = false;
6456         }
6457
6458         if (ServicePtrs[iService]->szPath[0] == '\0' &&
6459             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
6460             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
6461             ) {
6462                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
6463                         ServicePtrs[iService]->szService));
6464                 ServicePtrs[iService]->bAvailable = false;
6465         }
6466
6467         /* If a service is flagged unavailable, log the fact at level 1. */
6468         if (!ServicePtrs[iService]->bAvailable)
6469                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
6470                           ServicePtrs[iService]->szService));
6471
6472         return (bRetval);
6473 }
6474
6475 static struct smbconf_ctx *lp_smbconf_ctx(void)
6476 {
6477         sbcErr err;
6478         static struct smbconf_ctx *conf_ctx = NULL;
6479
6480         if (conf_ctx == NULL) {
6481                 err = smbconf_init(NULL, &conf_ctx, "registry:");
6482                 if (!SBC_ERROR_IS_OK(err)) {
6483                         DEBUG(1, ("error initializing registry configuration: "
6484                                   "%s\n", sbcErrorString(err)));
6485                         conf_ctx = NULL;
6486                 }
6487         }
6488
6489         return conf_ctx;
6490 }
6491
6492 static bool process_smbconf_service(struct smbconf_service *service)
6493 {
6494         uint32_t count;
6495         bool ret;
6496
6497         if (service == NULL) {
6498                 return false;
6499         }
6500
6501         ret = do_section(service->name, NULL);
6502         if (ret != true) {
6503                 return false;
6504         }
6505         for (count = 0; count < service->num_params; count++) {
6506                 ret = do_parameter(service->param_names[count],
6507                                    service->param_values[count],
6508                                    NULL);
6509                 if (ret != true) {
6510                         return false;
6511                 }
6512         }
6513         if (iServiceIndex >= 0) {
6514                 return service_ok(iServiceIndex);
6515         }
6516         return true;
6517 }
6518
6519 /**
6520  * load a service from registry and activate it
6521  */
6522 bool process_registry_service(const char *service_name)
6523 {
6524         sbcErr err;
6525         struct smbconf_service *service = NULL;
6526         TALLOC_CTX *mem_ctx = talloc_stackframe();
6527         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6528         bool ret = false;
6529
6530         if (conf_ctx == NULL) {
6531                 goto done;
6532         }
6533
6534         DEBUG(5, ("process_registry_service: service name %s\n", service_name));
6535
6536         if (!smbconf_share_exists(conf_ctx, service_name)) {
6537                 /*
6538                  * Registry does not contain data for this service (yet),
6539                  * but make sure lp_load doesn't return false.
6540                  */
6541                 ret = true;
6542                 goto done;
6543         }
6544
6545         err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
6546         if (!SBC_ERROR_IS_OK(err)) {
6547                 goto done;
6548         }
6549
6550         ret = process_smbconf_service(service);
6551         if (!ret) {
6552                 goto done;
6553         }
6554
6555         /* store the csn */
6556         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6557
6558 done:
6559         TALLOC_FREE(mem_ctx);
6560         return ret;
6561 }
6562
6563 /*
6564  * process_registry_globals
6565  */
6566 static bool process_registry_globals(void)
6567 {
6568         bool ret;
6569
6570         add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
6571
6572         ret = do_parameter("registry shares", "yes", NULL);
6573         if (!ret) {
6574                 return ret;
6575         }
6576
6577         return process_registry_service(GLOBAL_NAME);
6578 }
6579
6580 bool process_registry_shares(void)
6581 {
6582         sbcErr err;
6583         uint32_t count;
6584         struct smbconf_service **service = NULL;
6585         uint32_t num_shares = 0;
6586         TALLOC_CTX *mem_ctx = talloc_stackframe();
6587         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6588         bool ret = false;
6589
6590         if (conf_ctx == NULL) {
6591                 goto done;
6592         }
6593
6594         err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
6595         if (!SBC_ERROR_IS_OK(err)) {
6596                 goto done;
6597         }
6598
6599         ret = true;
6600
6601         for (count = 0; count < num_shares; count++) {
6602                 if (strequal(service[count]->name, GLOBAL_NAME)) {
6603                         continue;
6604                 }
6605                 ret = process_smbconf_service(service[count]);
6606                 if (!ret) {
6607                         goto done;
6608                 }
6609         }
6610
6611         /* store the csn */
6612         smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
6613
6614 done:
6615         TALLOC_FREE(mem_ctx);
6616         return ret;
6617 }
6618
6619 /**
6620  * reload those shares from registry that are already
6621  * activated in the services array.
6622  */
6623 static bool reload_registry_shares(void)
6624 {
6625         int i;
6626         bool ret = true;
6627
6628         for (i = 0; i < iNumServices; i++) {
6629                 if (!VALID(i)) {
6630                         continue;
6631                 }
6632
6633                 if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
6634                         continue;
6635                 }
6636
6637                 ret = process_registry_service(ServicePtrs[i]->szService);
6638                 if (!ret) {
6639                         goto done;
6640                 }
6641         }
6642
6643 done:
6644         return ret;
6645 }
6646
6647
6648 #define MAX_INCLUDE_DEPTH 100
6649
6650 static uint8_t include_depth;
6651
6652 static struct file_lists {
6653         struct file_lists *next;
6654         char *name;
6655         char *subfname;
6656         time_t modtime;
6657 } *file_lists = NULL;
6658
6659 /*******************************************************************
6660  Keep a linked list of all config files so we know when one has changed 
6661  it's date and needs to be reloaded.
6662 ********************************************************************/
6663
6664 static void add_to_file_list(const char *fname, const char *subfname)
6665 {
6666         struct file_lists *f = file_lists;
6667
6668         while (f) {
6669                 if (f->name && !strcmp(f->name, fname))
6670                         break;
6671                 f = f->next;
6672         }
6673
6674         if (!f) {
6675                 f = SMB_MALLOC_P(struct file_lists);
6676                 if (!f)
6677                         return;
6678                 f->next = file_lists;
6679                 f->name = SMB_STRDUP(fname);
6680                 if (!f->name) {
6681                         SAFE_FREE(f);
6682                         return;
6683                 }
6684                 f->subfname = SMB_STRDUP(subfname);
6685                 if (!f->subfname) {
6686                         SAFE_FREE(f->name);
6687                         SAFE_FREE(f);
6688                         return;
6689                 }
6690                 file_lists = f;
6691                 f->modtime = file_modtime(subfname);
6692         } else {
6693                 time_t t = file_modtime(subfname);
6694                 if (t)
6695                         f->modtime = t;
6696         }
6697         return;
6698 }
6699
6700 /**
6701  * Free the file lists
6702  */
6703 static void free_file_list(void)
6704 {
6705         struct file_lists *f;
6706         struct file_lists *next;
6707
6708         f = file_lists;
6709         while( f ) {
6710                 next = f->next;
6711                 SAFE_FREE( f->name );
6712                 SAFE_FREE( f->subfname );
6713                 SAFE_FREE( f );
6714                 f = next;
6715         }
6716         file_lists = NULL;
6717 }
6718
6719
6720 /**
6721  * Utility function for outsiders to check if we're running on registry.
6722  */
6723 bool lp_config_backend_is_registry(void)
6724 {
6725         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
6726 }
6727
6728 /**
6729  * Utility function to check if the config backend is FILE.
6730  */
6731 bool lp_config_backend_is_file(void)
6732 {
6733         return (lp_config_backend() == CONFIG_BACKEND_FILE);
6734 }
6735
6736 /*******************************************************************
6737  Check if a config file has changed date.
6738 ********************************************************************/
6739
6740 bool lp_file_list_changed(void)
6741 {
6742         struct file_lists *f = file_lists;
6743
6744         DEBUG(6, ("lp_file_list_changed()\n"));
6745
6746         while (f) {
6747                 time_t mod_time;
6748
6749                 if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
6750                         struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
6751
6752                         if (conf_ctx == NULL) {
6753                                 return false;
6754                         }
6755                         if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
6756                                             NULL))
6757                         {
6758                                 DEBUGADD(6, ("registry config changed\n"));
6759                                 return true;
6760                         }
6761                 } else {
6762                         char *n2 = NULL;
6763                         n2 = talloc_sub_basic(talloc_tos(),
6764                                               get_current_username(),
6765                                               current_user_info.domain,
6766                                               f->name);
6767                         if (!n2) {
6768                                 return false;
6769                         }
6770                         DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
6771                                      f->name, n2, ctime(&f->modtime)));
6772
6773                         mod_time = file_modtime(n2);
6774
6775                         if (mod_time &&
6776                             ((f->modtime != mod_time) ||
6777                              (f->subfname == NULL) ||
6778                              (strcmp(n2, f->subfname) != 0)))
6779                         {
6780                                 DEBUGADD(6,
6781                                          ("file %s modified: %s\n", n2,
6782                                           ctime(&mod_time)));
6783                                 f->modtime = mod_time;
6784                                 SAFE_FREE(f->subfname);
6785                                 f->subfname = SMB_STRDUP(n2);
6786                                 TALLOC_FREE(n2);
6787                                 return true;
6788                         }
6789                         TALLOC_FREE(n2);
6790                 }
6791                 f = f->next;
6792         }
6793         return false;
6794 }
6795
6796
6797 /**
6798  * Initialize iconv conversion descriptors.
6799  *
6800  * This is called the first time it is needed, and also called again
6801  * every time the configuration is reloaded, because the charset or
6802  * codepage might have changed.
6803  **/
6804 static void init_iconv(void)
6805 {
6806         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
6807                                                       lp_unix_charset(),
6808                                                       true, global_iconv_handle);
6809 }
6810
6811 static bool handle_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6812 {
6813         if (strcmp(*ptr, pszParmValue) != 0) {
6814                 string_set(ptr, pszParmValue);
6815                 init_iconv();
6816         }
6817         return true;
6818 }
6819
6820 static bool handle_dos_charset(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6821 {
6822         bool is_utf8 = false;
6823         size_t len = strlen(pszParmValue);
6824
6825         if (len == 4 || len == 5) {
6826                 /* Don't use StrCaseCmp here as we don't want to
6827                    initialize iconv. */
6828                 if ((toupper_m(pszParmValue[0]) == 'U') &&
6829                     (toupper_m(pszParmValue[1]) == 'T') &&
6830                     (toupper_m(pszParmValue[2]) == 'F')) {
6831                         if (len == 4) {
6832                                 if (pszParmValue[3] == '8') {
6833                                         is_utf8 = true;
6834                                 }
6835                         } else {
6836                                 if (pszParmValue[3] == '-' &&
6837                                     pszParmValue[4] == '8') {
6838                                         is_utf8 = true;
6839                                 }
6840                         }
6841                 }
6842         }
6843
6844         if (strcmp(*ptr, pszParmValue) != 0) {
6845                 if (is_utf8) {
6846                         DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
6847                                 "be UTF8, using (default value) %s instead.\n",
6848                                 DEFAULT_DOS_CHARSET));
6849                         pszParmValue = DEFAULT_DOS_CHARSET;
6850                 }
6851                 string_set(ptr, pszParmValue);
6852                 init_iconv();
6853         }
6854         return true;
6855 }
6856
6857 static bool handle_realm(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6858 {
6859         bool ret = true;
6860         char *realm = strupper_talloc(talloc_tos(), pszParmValue);
6861         char *dnsdomain = strlower_talloc(realm, pszParmValue);
6862
6863         ret &= string_set(&Globals.szRealm, pszParmValue);
6864         ret &= string_set(&Globals.szRealm_upper, realm);
6865         ret &= string_set(&Globals.szRealm_lower, dnsdomain);
6866         TALLOC_FREE(realm);
6867
6868         return ret;
6869 }
6870
6871 static bool handle_netbios_aliases(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6872 {
6873         TALLOC_FREE(Globals.szNetbiosAliases);
6874         Globals.szNetbiosAliases = (const char **)str_list_make_v3(NULL, pszParmValue, NULL);
6875         return set_netbios_aliases(Globals.szNetbiosAliases);
6876 }
6877
6878 /***************************************************************************
6879  Handle the include operation.
6880 ***************************************************************************/
6881 static bool bAllowIncludeRegistry = true;
6882
6883 static bool handle_include(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6884 {
6885         char *fname;
6886
6887         if (include_depth >= MAX_INCLUDE_DEPTH) {
6888                 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
6889                           include_depth));
6890                 return false;
6891         }
6892
6893         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
6894                 if (!bAllowIncludeRegistry) {
6895                         return true;
6896                 }
6897                 if (bInGlobalSection) {
6898                         bool ret;
6899                         include_depth++;
6900                         ret = process_registry_globals();
6901                         include_depth--;
6902                         return ret;
6903                 } else {
6904                         DEBUG(1, ("\"include = registry\" only effective "
6905                                   "in %s section\n", GLOBAL_NAME));
6906                         return false;
6907                 }
6908         }
6909
6910         fname = talloc_sub_basic(talloc_tos(), get_current_username(),
6911                                  current_user_info.domain,
6912                                  pszParmValue);
6913
6914         add_to_file_list(pszParmValue, fname);
6915
6916         string_set(ptr, fname);
6917
6918         if (file_exist(fname)) {
6919                 bool ret;
6920                 include_depth++;
6921                 ret = pm_process(fname, do_section, do_parameter, NULL);
6922                 include_depth--;
6923                 TALLOC_FREE(fname);
6924                 return ret;
6925         }
6926
6927         DEBUG(2, ("Can't find include file %s\n", fname));
6928         TALLOC_FREE(fname);
6929         return true;
6930 }
6931
6932 /***************************************************************************
6933  Handle the interpretation of the copy parameter.
6934 ***************************************************************************/
6935
6936 static bool handle_copy(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6937 {
6938         bool bRetval;
6939         int iTemp;
6940         struct loadparm_service serviceTemp;
6941
6942         string_set(ptr, pszParmValue);
6943
6944         init_service(&serviceTemp);
6945
6946         bRetval = false;
6947
6948         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
6949
6950         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
6951                 if (iTemp == iServiceIndex) {
6952                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
6953                 } else {
6954                         copy_service(ServicePtrs[iServiceIndex],
6955                                      &serviceTemp,
6956                                      ServicePtrs[iServiceIndex]->copymap);
6957                         bRetval = true;
6958                 }
6959         } else {
6960                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
6961                 bRetval = false;
6962         }
6963
6964         free_service(&serviceTemp);
6965         return (bRetval);
6966 }
6967
6968 static bool handle_ldap_debug_level(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
6969 {
6970         Globals.ldap_debug_level = lp_int(pszParmValue);
6971         init_ldap_debugging();
6972         return true;
6973 }
6974
6975 /***************************************************************************
6976  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
6977  parameters is:
6978
6979  [global]
6980
6981         idmap uid = 1000-1999
6982         idmap gid = 700-899
6983
6984  We only do simple parsing checks here.  The strings are parsed into useful
6985  structures in the idmap daemon code.
6986
6987 ***************************************************************************/
6988
6989 /* Some lp_ routines to return idmap [ug]id information */
6990
6991 static uid_t idmap_uid_low, idmap_uid_high;
6992 static gid_t idmap_gid_low, idmap_gid_high;
6993
6994 bool lp_idmap_uid(uid_t *low, uid_t *high)
6995 {
6996         if (idmap_uid_low == 0 || idmap_uid_high == 0)
6997                 return false;
6998
6999         if (low)
7000                 *low = idmap_uid_low;
7001
7002         if (high)
7003                 *high = idmap_uid_high;
7004
7005         return true;
7006 }
7007
7008 bool lp_idmap_gid(gid_t *low, gid_t *high)
7009 {
7010         if (idmap_gid_low == 0 || idmap_gid_high == 0)
7011                 return false;
7012
7013         if (low)
7014                 *low = idmap_gid_low;
7015
7016         if (high)
7017                 *high = idmap_gid_high;
7018
7019         return true;
7020 }
7021
7022 static bool handle_idmap_backend(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7023 {
7024         lp_do_parameter(snum, "idmap config * : backend", pszParmValue);
7025
7026         return true;
7027 }
7028
7029 /* Do some simple checks on "idmap [ug]id" parameter values */
7030
7031 static bool handle_idmap_uid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7032 {
7033         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7034
7035         return true;
7036 }
7037
7038 static bool handle_idmap_gid(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7039 {
7040         lp_do_parameter(snum, "idmap config * : range", pszParmValue);
7041
7042         return true;
7043 }
7044
7045 /***************************************************************************
7046  Handle the DEBUG level list.
7047 ***************************************************************************/
7048
7049 static bool handle_debug_list(struct loadparm_context *unused, int snum, const char *pszParmValueIn, char **ptr )
7050 {
7051         string_set(ptr, pszParmValueIn);
7052         return debug_parse_levels(pszParmValueIn);
7053 }
7054
7055 /***************************************************************************
7056  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
7057 ***************************************************************************/
7058
7059 static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
7060 {
7061         const char *suffix_string;
7062
7063         suffix_string = talloc_asprintf(ctx, "%s,%s", str,
7064                                         Globals.szLdapSuffix );
7065         if ( !suffix_string ) {
7066                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
7067                 return "";
7068         }
7069
7070         return suffix_string;
7071 }
7072
7073 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
7074 {
7075         if (Globals.szLdapMachineSuffix[0])
7076                 return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
7077
7078         return lp_string(ctx, Globals.szLdapSuffix);
7079 }
7080
7081 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
7082 {
7083         if (Globals.szLdapUserSuffix[0])
7084                 return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
7085
7086         return lp_string(ctx, Globals.szLdapSuffix);
7087 }
7088
7089 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
7090 {
7091         if (Globals.szLdapGroupSuffix[0])
7092                 return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
7093
7094         return lp_string(ctx, Globals.szLdapSuffix);
7095 }
7096
7097 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
7098 {
7099         if (Globals.szLdapIdmapSuffix[0])
7100                 return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
7101
7102         return lp_string(ctx, Globals.szLdapSuffix);
7103 }
7104
7105 /****************************************************************************
7106  set the value for a P_ENUM
7107  ***************************************************************************/
7108
7109 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
7110                               int *ptr )
7111 {
7112         int i;
7113
7114         for (i = 0; parm->enum_list[i].name; i++) {
7115                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
7116                         *ptr = parm->enum_list[i].value;
7117                         return;
7118                 }
7119         }
7120         DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
7121                   pszParmValue, parm->label));
7122 }
7123
7124 /***************************************************************************
7125 ***************************************************************************/
7126
7127 static bool handle_printing(struct loadparm_context *unused, int snum, const char *pszParmValue, char **ptr)
7128 {
7129         static int parm_num = -1;
7130         struct loadparm_service *s;
7131
7132         if ( parm_num == -1 )
7133                 parm_num = map_parameter( "printing" );
7134
7135         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
7136
7137         if ( snum < 0 )
7138                 s = &sDefault;
7139         else
7140                 s = ServicePtrs[snum];
7141
7142         init_printer_values( s );
7143
7144         return true;
7145 }
7146
7147
7148 /***************************************************************************
7149  Initialise a copymap.
7150 ***************************************************************************/
7151
7152 static void init_copymap(struct loadparm_service *pservice)
7153 {
7154         int i;
7155
7156         TALLOC_FREE(pservice->copymap);
7157
7158         pservice->copymap = bitmap_talloc(NULL, NUMPARAMETERS);
7159         if (!pservice->copymap)
7160                 DEBUG(0,
7161                       ("Couldn't allocate copymap!! (size %d)\n",
7162                        (int)NUMPARAMETERS));
7163         else
7164                 for (i = 0; i < NUMPARAMETERS; i++)
7165                         bitmap_set(pservice->copymap, i);
7166 }
7167
7168 /**
7169   return the parameter pointer for a parameter
7170 */
7171 void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
7172 {
7173         if (service == NULL) {
7174                 if (parm->p_class == P_LOCAL)
7175                         return (void *)(((char *)&sDefault)+parm->offset);
7176                 else if (parm->p_class == P_GLOBAL)
7177                         return (void *)(((char *)&Globals)+parm->offset);
7178                 else return NULL;
7179         } else {
7180                 return (void *)(((char *)service) + parm->offset);
7181         }
7182 }
7183
7184 /***************************************************************************
7185  Return the local pointer to a parameter given the service number and parameter
7186 ***************************************************************************/
7187
7188 void *lp_local_ptr_by_snum(int snum, struct parm_struct *parm)
7189 {
7190         return lp_parm_ptr(ServicePtrs[snum], parm);
7191 }
7192
7193 /***************************************************************************
7194  Process a parameter for a particular service number. If snum < 0
7195  then assume we are in the globals.
7196 ***************************************************************************/
7197
7198 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
7199 {
7200         int parmnum, i;
7201         void *parm_ptr = NULL;  /* where we are going to store the result */
7202         struct parmlist_entry **opt_list;
7203
7204         parmnum = map_parameter(pszParmName);
7205
7206         if (parmnum < 0) {
7207                 if (strchr(pszParmName, ':') == NULL) {
7208                         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
7209                                   pszParmName));
7210                         return true;
7211                 }
7212
7213                 /*
7214                  * We've got a parametric option
7215                  */
7216
7217                 opt_list = (snum < 0)
7218                         ? &Globals.param_opt : &ServicePtrs[snum]->param_opt;
7219                 set_param_opt(opt_list, pszParmName, pszParmValue, 0);
7220
7221                 return true;
7222         }
7223
7224         /* if it's already been set by the command line, then we don't
7225            override here */
7226         if (parm_table[parmnum].flags & FLAG_CMDLINE) {
7227                 return true;
7228         }
7229
7230         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
7231                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
7232                           pszParmName));
7233         }
7234
7235         /* we might point at a service, the default service or a global */
7236         if (snum < 0) {
7237                 parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
7238         } else {
7239                 if (parm_table[parmnum].p_class == P_GLOBAL) {
7240                         DEBUG(0,
7241                               ("Global parameter %s found in service section!\n",
7242                                pszParmName));
7243                         return true;
7244                 }
7245                 parm_ptr = lp_local_ptr_by_snum(snum, &parm_table[parmnum]);
7246         }
7247
7248         if (snum >= 0) {
7249                 if (!ServicePtrs[snum]->copymap)
7250                         init_copymap(ServicePtrs[snum]);
7251
7252                 /* this handles the aliases - set the copymap for other entries with
7253                    the same data pointer */
7254                 for (i = 0; parm_table[i].label; i++) {
7255                         if ((parm_table[i].offset == parm_table[parmnum].offset)
7256                             && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
7257                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
7258                         }
7259                 }
7260         }
7261
7262         /* if it is a special case then go ahead */
7263         if (parm_table[parmnum].special) {
7264                 return parm_table[parmnum].special(NULL, snum, pszParmValue,
7265                                                    (char **)parm_ptr);
7266         }
7267
7268         /* now switch on the type of variable it is */
7269         switch (parm_table[parmnum].type)
7270         {
7271                 case P_BOOL:
7272                         *(bool *)parm_ptr = lp_bool(pszParmValue);
7273                         break;
7274
7275                 case P_BOOLREV:
7276                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
7277                         break;
7278
7279                 case P_INTEGER:
7280                         *(int *)parm_ptr = lp_int(pszParmValue);
7281                         break;
7282
7283                 case P_CHAR:
7284                         *(char *)parm_ptr = *pszParmValue;
7285                         break;
7286
7287                 case P_OCTAL:
7288                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
7289                         if ( i != 1 ) {
7290                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
7291                         }
7292                         break;
7293
7294                 case P_BYTES:
7295                 {
7296                         uint64_t val;
7297                         if (conv_str_size_error(pszParmValue, &val)) {
7298                                 if (val <= INT_MAX) {
7299                                         *(int *)parm_ptr = (int)val;
7300                                         break;
7301                                 }
7302                         }
7303
7304                         DEBUG(0,("lp_do_parameter(%s): value is not "
7305                             "a valid size specifier!\n", pszParmValue));
7306                         return false;
7307                 }
7308
7309                 case P_LIST:
7310                 case P_CMDLIST:
7311                         TALLOC_FREE(*((char ***)parm_ptr));
7312                         *(char ***)parm_ptr = str_list_make_v3(
7313                                 NULL, pszParmValue, NULL);
7314                         break;
7315
7316                 case P_STRING:
7317                         string_set((char **)parm_ptr, pszParmValue);
7318                         break;
7319
7320                 case P_USTRING:
7321                 {
7322                         char *upper_string = strupper_talloc(talloc_tos(), 
7323                                                              pszParmValue);
7324                         string_set((char **)parm_ptr, upper_string);
7325                         TALLOC_FREE(upper_string);
7326                         break;
7327                 }
7328                 case P_ENUM:
7329                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
7330                         break;
7331                 case P_SEP:
7332                         break;
7333         }
7334
7335         return true;
7336 }
7337
7338 /***************************************************************************
7339 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
7340 FLAG_CMDLINE won't be overridden by loads from smb.conf.
7341 ***************************************************************************/
7342
7343 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue, bool store_values)
7344 {
7345         int parmnum, i;
7346         parmnum = map_parameter(pszParmName);
7347         if (parmnum >= 0) {
7348                 parm_table[parmnum].flags &= ~FLAG_CMDLINE;
7349                 if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
7350                         return false;
7351                 }
7352                 parm_table[parmnum].flags |= FLAG_CMDLINE;
7353
7354                 /* we have to also set FLAG_CMDLINE on aliases.  Aliases must
7355                  * be grouped in the table, so we don't have to search the
7356                  * whole table */
7357                 for (i=parmnum-1;
7358                      i>=0 && parm_table[i].offset == parm_table[parmnum].offset
7359                              && parm_table[i].p_class == parm_table[parmnum].p_class;
7360                      i--) {
7361                         parm_table[i].flags |= FLAG_CMDLINE;
7362                 }
7363                 for (i=parmnum+1;i<NUMPARAMETERS && parm_table[i].offset == parm_table[parmnum].offset
7364                              && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
7365                         parm_table[i].flags |= FLAG_CMDLINE;
7366                 }
7367
7368                 if (store_values) {
7369                         store_lp_set_cmdline(pszParmName, pszParmValue);
7370                 }
7371                 return true;
7372         }
7373
7374         /* it might be parametric */
7375         if (strchr(pszParmName, ':') != NULL) {
7376                 set_param_opt(&Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
7377                 if (store_values) {
7378                         store_lp_set_cmdline(pszParmName, pszParmValue);
7379                 }
7380                 return true;
7381         }
7382
7383         DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",  pszParmName));
7384         return true;
7385 }
7386
7387 bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
7388 {
7389         return lp_set_cmdline_helper(pszParmName, pszParmValue, true);
7390 }
7391
7392 /***************************************************************************
7393  Process a parameter.
7394 ***************************************************************************/
7395
7396 static bool do_parameter(const char *pszParmName, const char *pszParmValue,
7397                          void *userdata)
7398 {
7399         if (!bInGlobalSection && bGlobalOnly)
7400                 return true;
7401
7402         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
7403
7404         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
7405                                 pszParmName, pszParmValue));
7406 }
7407
7408 /*
7409   set a option from the commandline in 'a=b' format. Use to support --option
7410 */
7411 bool lp_set_option(const char *option)
7412 {
7413         char *p, *s;
7414         bool ret;
7415
7416         s = talloc_strdup(NULL, option);
7417         if (!s) {
7418                 return false;
7419         }
7420
7421         p = strchr(s, '=');
7422         if (!p) {
7423                 talloc_free(s);
7424                 return false;
7425         }
7426
7427         *p = 0;
7428
7429         /* skip white spaces after the = sign */
7430         do {
7431                 p++;
7432         } while (*p == ' ');
7433
7434         ret = lp_set_cmdline(s, p);
7435         talloc_free(s);
7436         return ret;
7437 }
7438
7439 /**************************************************************************
7440  Print a parameter of the specified type.
7441 ***************************************************************************/
7442
7443 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
7444 {
7445         /* For the seperation of lists values that we print below */
7446         const char *list_sep = ", ";
7447         int i;
7448         switch (p->type)
7449         {
7450                 case P_ENUM:
7451                         for (i = 0; p->enum_list[i].name; i++) {
7452                                 if (*(int *)ptr == p->enum_list[i].value) {
7453                                         fprintf(f, "%s",
7454                                                 p->enum_list[i].name);
7455                                         break;
7456                                 }
7457                         }
7458                         break;
7459
7460                 case P_BOOL:
7461                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
7462                         break;
7463
7464                 case P_BOOLREV:
7465                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
7466                         break;
7467
7468                 case P_INTEGER:
7469                 case P_BYTES:
7470                         fprintf(f, "%d", *(int *)ptr);
7471                         break;
7472
7473                 case P_CHAR:
7474                         fprintf(f, "%c", *(char *)ptr);
7475                         break;
7476
7477                 case P_OCTAL: {
7478                         int val = *(int *)ptr; 
7479                         if (val == -1) {
7480                                 fprintf(f, "-1");
7481                         } else {
7482                                 fprintf(f, "0%o", val);
7483                         }
7484                         break;
7485                 }
7486
7487                 case P_CMDLIST:
7488                         list_sep = " ";
7489                         /* fall through */
7490                 case P_LIST:
7491                         if ((char ***)ptr && *(char ***)ptr) {
7492                                 char **list = *(char ***)ptr;
7493                                 for (; *list; list++) {
7494                                         /* surround strings with whitespace in double quotes */
7495                                         if (*(list+1) == NULL) {
7496                                                 /* last item, no extra separator */
7497                                                 list_sep = "";
7498                                         }
7499                                         if ( strchr_m( *list, ' ' ) ) {
7500                                                 fprintf(f, "\"%s\"%s", *list, list_sep);
7501                                         } else {
7502                                                 fprintf(f, "%s%s", *list, list_sep);
7503                                         }
7504                                 }
7505                         }
7506                         break;
7507
7508                 case P_STRING:
7509                 case P_USTRING:
7510                         if (*(char **)ptr) {
7511                                 fprintf(f, "%s", *(char **)ptr);
7512                         }
7513                         break;
7514                 case P_SEP:
7515                         break;
7516         }
7517 }
7518
7519 /***************************************************************************
7520  Check if two parameters are equal.
7521 ***************************************************************************/
7522
7523 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
7524 {
7525         switch (type) {
7526                 case P_BOOL:
7527                 case P_BOOLREV:
7528                         return (*((bool *)ptr1) == *((bool *)ptr2));
7529
7530                 case P_INTEGER:
7531                 case P_ENUM:
7532                 case P_OCTAL:
7533                 case P_BYTES:
7534                         return (*((int *)ptr1) == *((int *)ptr2));
7535
7536                 case P_CHAR:
7537                         return (*((char *)ptr1) == *((char *)ptr2));
7538
7539                 case P_LIST:
7540                 case P_CMDLIST:
7541                         return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
7542
7543                 case P_STRING:
7544                 case P_USTRING:
7545                 {
7546                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
7547                         if (p1 && !*p1)
7548                                 p1 = NULL;
7549                         if (p2 && !*p2)
7550                                 p2 = NULL;
7551                         return (p1 == p2 || strequal(p1, p2));
7552                 }
7553                 case P_SEP:
7554                         break;
7555         }
7556         return false;
7557 }
7558
7559 /***************************************************************************
7560  Initialize any local varients in the sDefault table.
7561 ***************************************************************************/
7562
7563 void init_locals(void)
7564 {
7565         /* None as yet. */
7566 }
7567
7568 /***************************************************************************
7569  Process a new section (service). At this stage all sections are services.
7570  Later we'll have special sections that permit server parameters to be set.
7571  Returns true on success, false on failure.
7572 ***************************************************************************/
7573
7574 static bool do_section(const char *pszSectionName, void *userdata)
7575 {
7576         bool bRetval;
7577         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
7578                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
7579         bRetval = false;
7580
7581         /* if we were in a global section then do the local inits */
7582         if (bInGlobalSection && !isglobal)
7583                 init_locals();
7584
7585         /* if we've just struck a global section, note the fact. */
7586         bInGlobalSection = isglobal;
7587
7588         /* check for multiple global sections */
7589         if (bInGlobalSection) {
7590                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
7591                 return true;
7592         }
7593
7594         if (!bInGlobalSection && bGlobalOnly)
7595                 return true;
7596
7597         /* if we have a current service, tidy it up before moving on */
7598         bRetval = true;
7599
7600         if (iServiceIndex >= 0)
7601                 bRetval = service_ok(iServiceIndex);
7602
7603         /* if all is still well, move to the next record in the services array */
7604         if (bRetval) {
7605                 /* We put this here to avoid an odd message order if messages are */
7606                 /* issued by the post-processing of a previous section. */
7607                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
7608
7609                 iServiceIndex = add_a_service(&sDefault, pszSectionName);
7610                 if (iServiceIndex < 0) {
7611                         DEBUG(0, ("Failed to add a new service\n"));
7612                         return false;
7613                 }
7614                 /* Clean all parametric options for service */
7615                 /* They will be added during parsing again */
7616                 free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
7617         }
7618
7619         return bRetval;
7620 }
7621
7622
7623 /***************************************************************************
7624  Determine if a partcular base parameter is currentl set to the default value.
7625 ***************************************************************************/
7626
7627 static bool is_default(int i)
7628 {
7629         if (!defaults_saved)
7630                 return false;
7631         switch (parm_table[i].type) {
7632                 case P_LIST:
7633                 case P_CMDLIST:
7634                         return str_list_equal((const char **)parm_table[i].def.lvalue, 
7635                                               *(const char ***)lp_parm_ptr(NULL, 
7636                                                                            &parm_table[i]));
7637                 case P_STRING:
7638                 case P_USTRING:
7639                         return strequal(parm_table[i].def.svalue,
7640                                         *(char **)lp_parm_ptr(NULL, 
7641                                                               &parm_table[i]));
7642                 case P_BOOL:
7643                 case P_BOOLREV:
7644                         return parm_table[i].def.bvalue ==
7645                                 *(bool *)lp_parm_ptr(NULL, 
7646                                                      &parm_table[i]);
7647                 case P_CHAR:
7648                         return parm_table[i].def.cvalue ==
7649                                 *(char *)lp_parm_ptr(NULL, 
7650                                                      &parm_table[i]);
7651                 case P_INTEGER:
7652                 case P_OCTAL:
7653                 case P_ENUM:
7654                 case P_BYTES:
7655                         return parm_table[i].def.ivalue ==
7656                                 *(int *)lp_parm_ptr(NULL, 
7657                                                     &parm_table[i]);
7658                 case P_SEP:
7659                         break;
7660         }
7661         return false;
7662 }
7663
7664 /***************************************************************************
7665 Display the contents of the global structure.
7666 ***************************************************************************/
7667
7668 static void dump_globals(FILE *f)
7669 {
7670         int i;
7671         struct parmlist_entry *data;
7672
7673         fprintf(f, "[global]\n");
7674
7675         for (i = 0; parm_table[i].label; i++)
7676                 if (parm_table[i].p_class == P_GLOBAL &&
7677                     !(parm_table[i].flags & FLAG_META) &&
7678                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
7679                         if (defaults_saved && is_default(i))
7680                                 continue;
7681                         fprintf(f, "\t%s = ", parm_table[i].label);
7682                         print_parameter(&parm_table[i], lp_parm_ptr(NULL, 
7683                                                                     &parm_table[i]),
7684                                         f);
7685                         fprintf(f, "\n");
7686         }
7687         if (Globals.param_opt != NULL) {
7688                 data = Globals.param_opt;
7689                 while(data) {
7690                         fprintf(f, "\t%s = %s\n", data->key, data->value);
7691                         data = data->next;
7692                 }
7693         }
7694
7695 }
7696
7697 /***************************************************************************
7698  Return true if a local parameter is currently set to the global default.
7699 ***************************************************************************/
7700
7701 bool lp_is_default(int snum, struct parm_struct *parm)
7702 {
7703         return equal_parameter(parm->type,
7704                                lp_parm_ptr(ServicePtrs[snum], parm),
7705                                lp_parm_ptr(NULL, parm));
7706 }
7707
7708 /***************************************************************************
7709  Display the contents of a single services record.
7710 ***************************************************************************/
7711
7712 static void dump_a_service(struct loadparm_service *pService, FILE * f)
7713 {
7714         int i;
7715         struct parmlist_entry *data;
7716
7717         if (pService != &sDefault)
7718                 fprintf(f, "[%s]\n", pService->szService);
7719
7720         for (i = 0; parm_table[i].label; i++) {
7721
7722                 if (parm_table[i].p_class == P_LOCAL &&
7723                     !(parm_table[i].flags & FLAG_META) &&
7724                     (*parm_table[i].label != '-') &&
7725                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7726                 {
7727                         if (pService == &sDefault) {
7728                                 if (defaults_saved && is_default(i))
7729                                         continue;
7730                         } else {
7731                                 if (equal_parameter(parm_table[i].type,
7732                                                     lp_parm_ptr(pService, &parm_table[i]),
7733                                                     lp_parm_ptr(NULL, &parm_table[i])))
7734                                         continue;
7735                         }
7736
7737                         fprintf(f, "\t%s = ", parm_table[i].label);
7738                         print_parameter(&parm_table[i],
7739                                         lp_parm_ptr(pService, &parm_table[i]),
7740                                         f);
7741                         fprintf(f, "\n");
7742                 }
7743         }
7744
7745                 if (pService->param_opt != NULL) {
7746                         data = pService->param_opt;
7747                         while(data) {
7748                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
7749                                 data = data->next;
7750                         }
7751                 }
7752 }
7753
7754 /***************************************************************************
7755  Display the contents of a parameter of a single services record.
7756 ***************************************************************************/
7757
7758 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
7759 {
7760         int i;
7761         bool result = false;
7762         parm_class p_class;
7763         unsigned flag = 0;
7764         fstring local_parm_name;
7765         char *parm_opt;
7766         const char *parm_opt_value;
7767
7768         /* check for parametrical option */
7769         fstrcpy( local_parm_name, parm_name);
7770         parm_opt = strchr( local_parm_name, ':');
7771
7772         if (parm_opt) {
7773                 *parm_opt = '\0';
7774                 parm_opt++;
7775                 if (strlen(parm_opt)) {
7776                         parm_opt_value = lp_parm_const_string( snum,
7777                                 local_parm_name, parm_opt, NULL);
7778                         if (parm_opt_value) {
7779                                 printf( "%s\n", parm_opt_value);
7780                                 result = true;
7781                         }
7782                 }
7783                 return result;
7784         }
7785
7786         /* check for a key and print the value */
7787         if (isGlobal) {
7788                 p_class = P_GLOBAL;
7789                 flag = FLAG_GLOBAL;
7790         } else
7791                 p_class = P_LOCAL;
7792
7793         for (i = 0; parm_table[i].label; i++) {
7794                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
7795                     !(parm_table[i].flags & FLAG_META) &&
7796                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
7797                     (*parm_table[i].label != '-') &&
7798                     (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) 
7799                 {
7800                         void *ptr;
7801
7802                         if (isGlobal) {
7803                                 ptr = lp_parm_ptr(NULL, 
7804                                                   &parm_table[i]);
7805                         } else {
7806                                 ptr = lp_parm_ptr(ServicePtrs[snum], 
7807                                                   &parm_table[i]);
7808                         }
7809
7810                         print_parameter(&parm_table[i],
7811                                         ptr, f);
7812                         fprintf(f, "\n");
7813                         result = true;
7814                         break;
7815                 }
7816         }
7817
7818         return result;
7819 }
7820
7821 /***************************************************************************
7822  Return info about the requested parameter (given as a string).
7823  Return NULL when the string is not a valid parameter name.
7824 ***************************************************************************/
7825
7826 struct parm_struct *lp_get_parameter(const char *param_name)
7827 {
7828         int num = map_parameter(param_name);
7829
7830         if (num < 0) {
7831                 return NULL;
7832         }
7833
7834         return &parm_table[num];
7835 }
7836
7837 /***************************************************************************
7838  Return info about the next parameter in a service.
7839  snum==GLOBAL_SECTION_SNUM gives the globals.
7840  Return NULL when out of parameters.
7841 ***************************************************************************/
7842
7843 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
7844 {
7845         if (snum < 0) {
7846                 /* do the globals */
7847                 for (; parm_table[*i].label; (*i)++) {
7848                         if (parm_table[*i].p_class == P_SEPARATOR)
7849                                 return &parm_table[(*i)++];
7850
7851                         if ((*parm_table[*i].label == '-'))
7852                                 continue;
7853
7854                         if ((*i) > 0
7855                             && (parm_table[*i].offset ==
7856                                 parm_table[(*i) - 1].offset)
7857                             && (parm_table[*i].p_class ==
7858                                 parm_table[(*i) - 1].p_class))
7859                                 continue;
7860
7861                         if (is_default(*i) && !allparameters)
7862                                 continue;
7863
7864                         return &parm_table[(*i)++];
7865                 }
7866         } else {
7867                 struct loadparm_service *pService = ServicePtrs[snum];
7868
7869                 for (; parm_table[*i].label; (*i)++) {
7870                         if (parm_table[*i].p_class == P_SEPARATOR)
7871                                 return &parm_table[(*i)++];
7872
7873                         if (parm_table[*i].p_class == P_LOCAL &&
7874                             (*parm_table[*i].label != '-') &&
7875                             ((*i) == 0 ||
7876                              (parm_table[*i].offset !=
7877                               parm_table[(*i) - 1].offset)))
7878                         {
7879                                 if (allparameters ||
7880                                     !equal_parameter(parm_table[*i].type,
7881                                                      lp_parm_ptr(pService, 
7882                                                                  &parm_table[*i]),
7883                                                      lp_parm_ptr(NULL, 
7884                                                                  &parm_table[*i])))
7885                                 {
7886                                         return &parm_table[(*i)++];
7887                                 }
7888                         }
7889                 }
7890         }
7891
7892         return NULL;
7893 }
7894
7895
7896 #if 0
7897 /***************************************************************************
7898  Display the contents of a single copy structure.
7899 ***************************************************************************/
7900 static void dump_copy_map(bool *pcopymap)
7901 {
7902         int i;
7903         if (!pcopymap)
7904                 return;
7905
7906         printf("\n\tNon-Copied parameters:\n");
7907
7908         for (i = 0; parm_table[i].label; i++)
7909                 if (parm_table[i].p_class == P_LOCAL &&
7910                     parm_table[i].ptr && !pcopymap[i] &&
7911                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
7912                 {
7913                         printf("\t\t%s\n", parm_table[i].label);
7914                 }
7915 }
7916 #endif
7917
7918 /***************************************************************************
7919  Return TRUE if the passed service number is within range.
7920 ***************************************************************************/
7921
7922 bool lp_snum_ok(int iService)
7923 {
7924         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
7925 }
7926
7927 /***************************************************************************
7928  Auto-load some home services.
7929 ***************************************************************************/
7930
7931 static void lp_add_auto_services(char *str)
7932 {
7933         char *s;
7934         char *p;
7935         int homes;
7936         char *saveptr;
7937
7938         if (!str)
7939                 return;
7940
7941         s = SMB_STRDUP(str);
7942         if (!s)
7943                 return;
7944
7945         homes = lp_servicenumber(HOMES_NAME);
7946
7947         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
7948              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
7949                 char *home;
7950
7951                 if (lp_servicenumber(p) >= 0)
7952                         continue;
7953
7954                 home = get_user_home_dir(talloc_tos(), p);
7955
7956                 if (home && home[0] && homes >= 0)
7957                         lp_add_home(p, homes, p, home);
7958
7959                 TALLOC_FREE(home);
7960         }
7961         SAFE_FREE(s);
7962 }
7963
7964 /***************************************************************************
7965  Auto-load one printer.
7966 ***************************************************************************/
7967
7968 void lp_add_one_printer(const char *name, const char *comment,
7969                         const char *location, void *pdata)
7970 {
7971         int printers = lp_servicenumber(PRINTERS_NAME);
7972         int i;
7973
7974         if (lp_servicenumber(name) < 0) {
7975                 lp_add_printer(name, printers);
7976                 if ((i = lp_servicenumber(name)) >= 0) {
7977                         string_set(&ServicePtrs[i]->comment, comment);
7978                         ServicePtrs[i]->autoloaded = true;
7979                 }
7980         }
7981 }
7982
7983 /***************************************************************************
7984  Have we loaded a services file yet?
7985 ***************************************************************************/
7986
7987 bool lp_loaded(void)
7988 {
7989         return (bLoaded);
7990 }
7991
7992 /***************************************************************************
7993  Unload unused services.
7994 ***************************************************************************/
7995
7996 void lp_killunused(struct smbd_server_connection *sconn,
7997                    bool (*snumused) (struct smbd_server_connection *, int))
7998 {
7999         int i;
8000         for (i = 0; i < iNumServices; i++) {
8001                 if (!VALID(i))
8002                         continue;
8003
8004                 /* don't kill autoloaded or usershare services */
8005                 if ( ServicePtrs[i]->autoloaded ||
8006                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
8007                         continue;
8008                 }
8009
8010                 if (!snumused || !snumused(sconn, i)) {
8011                         free_service_byindex(i);
8012                 }
8013         }
8014 }
8015
8016 /**
8017  * Kill all except autoloaded and usershare services - convenience wrapper
8018  */
8019 void lp_kill_all_services(void)
8020 {
8021         lp_killunused(NULL, NULL);
8022 }
8023
8024 /***************************************************************************
8025  Unload a service.
8026 ***************************************************************************/
8027
8028 void lp_killservice(int iServiceIn)
8029 {
8030         if (VALID(iServiceIn)) {
8031                 free_service_byindex(iServiceIn);
8032         }
8033 }
8034
8035 /***************************************************************************
8036  Save the curent values of all global and sDefault parameters into the 
8037  defaults union. This allows swat and testparm to show only the
8038  changed (ie. non-default) parameters.
8039 ***************************************************************************/
8040
8041 static void lp_save_defaults(void)
8042 {
8043         int i;
8044         for (i = 0; parm_table[i].label; i++) {
8045                 if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
8046                     && parm_table[i].p_class == parm_table[i - 1].p_class)
8047                         continue;
8048                 switch (parm_table[i].type) {
8049                         case P_LIST:
8050                         case P_CMDLIST:
8051                                 parm_table[i].def.lvalue = str_list_copy(
8052                                         NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
8053                                 break;
8054                         case P_STRING:
8055                         case P_USTRING:
8056                                 parm_table[i].def.svalue = SMB_STRDUP(*(char **)lp_parm_ptr(NULL, &parm_table[i]));
8057                                 break;
8058                         case P_BOOL:
8059                         case P_BOOLREV:
8060                                 parm_table[i].def.bvalue =
8061                                         *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
8062                                 break;
8063                         case P_CHAR:
8064                                 parm_table[i].def.cvalue =
8065                                         *(char *)lp_parm_ptr(NULL, &parm_table[i]);
8066                                 break;
8067                         case P_INTEGER:
8068                         case P_OCTAL:
8069                         case P_ENUM:
8070                         case P_BYTES:
8071                                 parm_table[i].def.ivalue =
8072                                         *(int *)lp_parm_ptr(NULL, &parm_table[i]);
8073                                 break;
8074                         case P_SEP:
8075                                 break;
8076                 }
8077         }
8078         defaults_saved = true;
8079 }
8080
8081 /***********************************************************
8082  If we should send plaintext/LANMAN passwords in the clinet
8083 ************************************************************/
8084
8085 static void set_allowed_client_auth(void)
8086 {
8087         if (Globals.bClientNTLMv2Auth) {
8088                 Globals.bClientLanManAuth = false;
8089         }
8090         if (!Globals.bClientLanManAuth) {
8091                 Globals.bClientPlaintextAuth = false;
8092         }
8093 }
8094
8095 /***************************************************************************
8096  JRA.
8097  The following code allows smbd to read a user defined share file.
8098  Yes, this is my intent. Yes, I'm comfortable with that...
8099
8100  THE FOLLOWING IS SECURITY CRITICAL CODE.
8101
8102  It washes your clothes, it cleans your house, it guards you while you sleep...
8103  Do not f%^k with it....
8104 ***************************************************************************/
8105
8106 #define MAX_USERSHARE_FILE_SIZE (10*1024)
8107
8108 /***************************************************************************
8109  Check allowed stat state of a usershare file.
8110  Ensure we print out who is dicking with us so the admin can
8111  get their sorry ass fired.
8112 ***************************************************************************/
8113
8114 static bool check_usershare_stat(const char *fname,
8115                                  const SMB_STRUCT_STAT *psbuf)
8116 {
8117         if (!S_ISREG(psbuf->st_ex_mode)) {
8118                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8119                         "not a regular file\n",
8120                         fname, (unsigned int)psbuf->st_ex_uid ));
8121                 return false;
8122         }
8123
8124         /* Ensure this doesn't have the other write bit set. */
8125         if (psbuf->st_ex_mode & S_IWOTH) {
8126                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
8127                         "public write. Refusing to allow as a usershare file.\n",
8128                         fname, (unsigned int)psbuf->st_ex_uid ));
8129                 return false;
8130         }
8131
8132         /* Should be 10k or less. */
8133         if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
8134                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
8135                         "too large (%u) to be a user share file.\n",
8136                         fname, (unsigned int)psbuf->st_ex_uid,
8137                         (unsigned int)psbuf->st_ex_size ));
8138                 return false;
8139         }
8140
8141         return true;
8142 }
8143
8144 /***************************************************************************
8145  Parse the contents of a usershare file.
8146 ***************************************************************************/
8147
8148 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
8149                         SMB_STRUCT_STAT *psbuf,
8150                         const char *servicename,
8151                         int snum,
8152                         char **lines,
8153                         int numlines,
8154                         char **pp_sharepath,
8155                         char **pp_comment,
8156                         char **pp_cp_servicename,
8157                         struct security_descriptor **ppsd,
8158                         bool *pallow_guest)
8159 {
8160         const char **prefixallowlist = lp_usershare_prefix_allow_list();
8161         const char **prefixdenylist = lp_usershare_prefix_deny_list();
8162         int us_vers;
8163         DIR *dp;
8164         SMB_STRUCT_STAT sbuf;
8165         char *sharepath = NULL;
8166         char *comment = NULL;
8167
8168         *pp_sharepath = NULL;
8169         *pp_comment = NULL;
8170
8171         *pallow_guest = false;
8172
8173         if (numlines < 4) {
8174                 return USERSHARE_MALFORMED_FILE;
8175         }
8176
8177         if (strcmp(lines[0], "#VERSION 1") == 0) {
8178                 us_vers = 1;
8179         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
8180                 us_vers = 2;
8181                 if (numlines < 5) {
8182                         return USERSHARE_MALFORMED_FILE;
8183                 }
8184         } else {
8185                 return USERSHARE_BAD_VERSION;
8186         }
8187
8188         if (strncmp(lines[1], "path=", 5) != 0) {
8189                 return USERSHARE_MALFORMED_PATH;
8190         }
8191
8192         sharepath = talloc_strdup(ctx, &lines[1][5]);
8193         if (!sharepath) {
8194                 return USERSHARE_POSIX_ERR;
8195         }
8196         trim_string(sharepath, " ", " ");
8197
8198         if (strncmp(lines[2], "comment=", 8) != 0) {
8199                 return USERSHARE_MALFORMED_COMMENT_DEF;
8200         }
8201
8202         comment = talloc_strdup(ctx, &lines[2][8]);
8203         if (!comment) {
8204                 return USERSHARE_POSIX_ERR;
8205         }
8206         trim_string(comment, " ", " ");
8207         trim_char(comment, '"', '"');
8208
8209         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
8210                 return USERSHARE_MALFORMED_ACL_DEF;
8211         }
8212
8213         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
8214                 return USERSHARE_ACL_ERR;
8215         }
8216
8217         if (us_vers == 2) {
8218                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
8219                         return USERSHARE_MALFORMED_ACL_DEF;
8220                 }
8221                 if (lines[4][9] == 'y') {
8222                         *pallow_guest = true;
8223                 }
8224
8225                 /* Backwards compatible extension to file version #2. */
8226                 if (numlines > 5) {
8227                         if (strncmp(lines[5], "sharename=", 10) != 0) {
8228                                 return USERSHARE_MALFORMED_SHARENAME_DEF;
8229                         }
8230                         if (!strequal(&lines[5][10], servicename)) {
8231                                 return USERSHARE_BAD_SHARENAME;
8232                         }
8233                         *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
8234                         if (!*pp_cp_servicename) {
8235                                 return USERSHARE_POSIX_ERR;
8236                         }
8237                 }
8238         }
8239
8240         if (*pp_cp_servicename == NULL) {
8241                 *pp_cp_servicename = talloc_strdup(ctx, servicename);
8242                 if (!*pp_cp_servicename) {
8243                         return USERSHARE_POSIX_ERR;
8244                 }
8245         }
8246
8247         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
8248                 /* Path didn't change, no checks needed. */
8249                 *pp_sharepath = sharepath;
8250                 *pp_comment = comment;
8251                 return USERSHARE_OK;
8252         }
8253
8254         /* The path *must* be absolute. */
8255         if (sharepath[0] != '/') {
8256                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
8257                         servicename, sharepath));
8258                 return USERSHARE_PATH_NOT_ABSOLUTE;
8259         }
8260
8261         /* If there is a usershare prefix deny list ensure one of these paths
8262            doesn't match the start of the user given path. */
8263         if (prefixdenylist) {
8264                 int i;
8265                 for ( i=0; prefixdenylist[i]; i++ ) {
8266                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
8267                                 servicename, i, prefixdenylist[i], sharepath ));
8268                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
8269                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
8270                                         "usershare prefix deny list entries.\n",
8271                                         servicename, sharepath));
8272                                 return USERSHARE_PATH_IS_DENIED;
8273                         }
8274                 }
8275         }
8276
8277         /* If there is a usershare prefix allow list ensure one of these paths
8278            does match the start of the user given path. */
8279
8280         if (prefixallowlist) {
8281                 int i;
8282                 for ( i=0; prefixallowlist[i]; i++ ) {
8283                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
8284                                 servicename, i, prefixallowlist[i], sharepath ));
8285                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
8286                                 break;
8287                         }
8288                 }
8289                 if (prefixallowlist[i] == NULL) {
8290                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
8291                                 "usershare prefix allow list entries.\n",
8292                                 servicename, sharepath));
8293                         return USERSHARE_PATH_NOT_ALLOWED;
8294                 }
8295         }
8296
8297         /* Ensure this is pointing to a directory. */
8298         dp = opendir(sharepath);
8299
8300         if (!dp) {
8301                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8302                         servicename, sharepath));
8303                 return USERSHARE_PATH_NOT_DIRECTORY;
8304         }
8305
8306         /* Ensure the owner of the usershare file has permission to share
8307            this directory. */
8308
8309         if (sys_stat(sharepath, &sbuf, false) == -1) {
8310                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
8311                         servicename, sharepath, strerror(errno) ));
8312                 closedir(dp);
8313                 return USERSHARE_POSIX_ERR;
8314         }
8315
8316         closedir(dp);
8317
8318         if (!S_ISDIR(sbuf.st_ex_mode)) {
8319                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
8320                         servicename, sharepath ));
8321                 return USERSHARE_PATH_NOT_DIRECTORY;
8322         }
8323
8324         /* Check if sharing is restricted to owner-only. */
8325         /* psbuf is the stat of the usershare definition file,
8326            sbuf is the stat of the target directory to be shared. */
8327
8328         if (lp_usershare_owner_only()) {
8329                 /* root can share anything. */
8330                 if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
8331                         return USERSHARE_PATH_NOT_ALLOWED;
8332                 }
8333         }
8334
8335         *pp_sharepath = sharepath;
8336         *pp_comment = comment;
8337         return USERSHARE_OK;
8338 }
8339
8340 /***************************************************************************
8341  Deal with a usershare file.
8342  Returns:
8343         >= 0 - snum
8344         -1 - Bad name, invalid contents.
8345            - service name already existed and not a usershare, problem
8346             with permissions to share directory etc.
8347 ***************************************************************************/
8348
8349 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
8350 {
8351         SMB_STRUCT_STAT sbuf;
8352         SMB_STRUCT_STAT lsbuf;
8353         char *fname = NULL;
8354         char *sharepath = NULL;
8355         char *comment = NULL;
8356         char *cp_service_name = NULL;
8357         char **lines = NULL;
8358         int numlines = 0;
8359         int fd = -1;
8360         int iService = -1;
8361         TALLOC_CTX *ctx = talloc_stackframe();
8362         struct security_descriptor *psd = NULL;
8363         bool guest_ok = false;
8364         char *canon_name = NULL;
8365         bool added_service = false;
8366         int ret = -1;
8367
8368         /* Ensure share name doesn't contain invalid characters. */
8369         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
8370                 DEBUG(0,("process_usershare_file: share name %s contains "
8371                         "invalid characters (any of %s)\n",
8372                         file_name, INVALID_SHARENAME_CHARS ));
8373                 goto out;
8374         }
8375
8376         canon_name = canonicalize_servicename(ctx, file_name);
8377         if (!canon_name) {
8378                 goto out;
8379         }
8380
8381         fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
8382         if (!fname) {
8383                 goto out;
8384         }
8385
8386         /* Minimize the race condition by doing an lstat before we
8387            open and fstat. Ensure this isn't a symlink link. */
8388
8389         if (sys_lstat(fname, &lsbuf, false) != 0) {
8390                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
8391                         fname, strerror(errno) ));
8392                 goto out;
8393         }
8394
8395         /* This must be a regular file, not a symlink, directory or
8396            other strange filetype. */
8397         if (!check_usershare_stat(fname, &lsbuf)) {
8398                 goto out;
8399         }
8400
8401         {
8402                 TDB_DATA data;
8403                 NTSTATUS status;
8404
8405                 status = dbwrap_fetch_bystring(ServiceHash, canon_name,
8406                                                canon_name, &data);
8407
8408                 iService = -1;
8409
8410                 if (NT_STATUS_IS_OK(status) &&
8411                     (data.dptr != NULL) &&
8412                     (data.dsize == sizeof(iService))) {
8413                         memcpy(&iService, data.dptr, sizeof(iService));
8414                 }
8415         }
8416
8417         if (iService != -1 &&
8418             timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
8419                              &lsbuf.st_ex_mtime) == 0) {
8420                 /* Nothing changed - Mark valid and return. */
8421                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
8422                         canon_name ));
8423                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
8424                 ret = iService;
8425                 goto out;
8426         }
8427
8428         /* Try and open the file read only - no symlinks allowed. */
8429 #ifdef O_NOFOLLOW
8430         fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
8431 #else
8432         fd = open(fname, O_RDONLY, 0);
8433 #endif
8434
8435         if (fd == -1) {
8436                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
8437                         fname, strerror(errno) ));
8438                 goto out;
8439         }
8440
8441         /* Now fstat to be *SURE* it's a regular file. */
8442         if (sys_fstat(fd, &sbuf, false) != 0) {
8443                 close(fd);
8444                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
8445                         fname, strerror(errno) ));
8446                 goto out;
8447         }
8448
8449         /* Is it the same dev/inode as was lstated ? */
8450         if (!check_same_stat(&lsbuf, &sbuf)) {
8451                 close(fd);
8452                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
8453                         "Symlink spoofing going on ?\n", fname ));
8454                 goto out;
8455         }
8456
8457         /* This must be a regular file, not a symlink, directory or
8458            other strange filetype. */
8459         if (!check_usershare_stat(fname, &sbuf)) {
8460                 goto out;
8461         }
8462
8463         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
8464
8465         close(fd);
8466         if (lines == NULL) {
8467                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
8468                         fname, (unsigned int)sbuf.st_ex_uid ));
8469                 goto out;
8470         }
8471
8472         if (parse_usershare_file(ctx, &sbuf, file_name,
8473                         iService, lines, numlines, &sharepath,
8474                         &comment, &cp_service_name,
8475                         &psd, &guest_ok) != USERSHARE_OK) {
8476                 goto out;
8477         }
8478
8479         /* Everything ok - add the service possibly using a template. */
8480         if (iService < 0) {
8481                 const struct loadparm_service *sp = &sDefault;
8482                 if (snum_template != -1) {
8483                         sp = ServicePtrs[snum_template];
8484                 }
8485
8486                 if ((iService = add_a_service(sp, cp_service_name)) < 0) {
8487                         DEBUG(0, ("process_usershare_file: Failed to add "
8488                                 "new service %s\n", cp_service_name));
8489                         goto out;
8490                 }
8491
8492                 added_service = true;
8493
8494                 /* Read only is controlled by usershare ACL below. */
8495                 ServicePtrs[iService]->bRead_only = false;
8496         }
8497
8498         /* Write the ACL of the new/modified share. */
8499         if (!set_share_security(canon_name, psd)) {
8500                  DEBUG(0, ("process_usershare_file: Failed to set share "
8501                         "security for user share %s\n",
8502                         canon_name ));
8503                 goto out;
8504         }
8505
8506         /* If from a template it may be marked invalid. */
8507         ServicePtrs[iService]->valid = true;
8508
8509         /* Set the service as a valid usershare. */
8510         ServicePtrs[iService]->usershare = USERSHARE_VALID;
8511
8512         /* Set guest access. */
8513         if (lp_usershare_allow_guests()) {
8514                 ServicePtrs[iService]->bGuest_ok = guest_ok;
8515         }
8516
8517         /* And note when it was loaded. */
8518         ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
8519         string_set(&ServicePtrs[iService]->szPath, sharepath);
8520         string_set(&ServicePtrs[iService]->comment, comment);
8521
8522         ret = iService;
8523
8524   out:
8525
8526         if (ret == -1 && iService != -1 && added_service) {
8527                 lp_remove_service(iService);
8528         }
8529
8530         TALLOC_FREE(lines);
8531         TALLOC_FREE(ctx);
8532         return ret;
8533 }
8534
8535 /***************************************************************************
8536  Checks if a usershare entry has been modified since last load.
8537 ***************************************************************************/
8538
8539 static bool usershare_exists(int iService, struct timespec *last_mod)
8540 {
8541         SMB_STRUCT_STAT lsbuf;
8542         const char *usersharepath = Globals.szUsersharePath;
8543         char *fname;
8544
8545         if (asprintf(&fname, "%s/%s",
8546                                 usersharepath,
8547                                 ServicePtrs[iService]->szService) < 0) {
8548                 return false;
8549         }
8550
8551         if (sys_lstat(fname, &lsbuf, false) != 0) {
8552                 SAFE_FREE(fname);
8553                 return false;
8554         }
8555
8556         if (!S_ISREG(lsbuf.st_ex_mode)) {
8557                 SAFE_FREE(fname);
8558                 return false;
8559         }
8560
8561         SAFE_FREE(fname);
8562         *last_mod = lsbuf.st_ex_mtime;
8563         return true;
8564 }
8565
8566 /***************************************************************************
8567  Load a usershare service by name. Returns a valid servicenumber or -1.
8568 ***************************************************************************/
8569
8570 int load_usershare_service(const char *servicename)
8571 {
8572         SMB_STRUCT_STAT sbuf;
8573         const char *usersharepath = Globals.szUsersharePath;
8574         int max_user_shares = Globals.iUsershareMaxShares;
8575         int snum_template = -1;
8576
8577         if (*usersharepath == 0 ||  max_user_shares == 0) {
8578                 return -1;
8579         }
8580
8581         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8582                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
8583                         usersharepath, strerror(errno) ));
8584                 return -1;
8585         }
8586
8587         if (!S_ISDIR(sbuf.st_ex_mode)) {
8588                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
8589                         usersharepath ));
8590                 return -1;
8591         }
8592
8593         /*
8594          * This directory must be owned by root, and have the 't' bit set.
8595          * It also must not be writable by "other".
8596          */
8597
8598 #ifdef S_ISVTX
8599         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8600 #else
8601         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8602 #endif
8603                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
8604                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8605                         usersharepath ));
8606                 return -1;
8607         }
8608
8609         /* Ensure the template share exists if it's set. */
8610         if (Globals.szUsershareTemplateShare[0]) {
8611                 /* We can't use lp_servicenumber here as we are recommending that
8612                    template shares have -valid=false set. */
8613                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8614                         if (ServicePtrs[snum_template]->szService &&
8615                                         strequal(ServicePtrs[snum_template]->szService,
8616                                                 Globals.szUsershareTemplateShare)) {
8617                                 break;
8618                         }
8619                 }
8620
8621                 if (snum_template == -1) {
8622                         DEBUG(0,("load_usershare_service: usershare template share %s "
8623                                 "does not exist.\n",
8624                                 Globals.szUsershareTemplateShare ));
8625                         return -1;
8626                 }
8627         }
8628
8629         return process_usershare_file(usersharepath, servicename, snum_template);
8630 }
8631
8632 /***************************************************************************
8633  Load all user defined shares from the user share directory.
8634  We only do this if we're enumerating the share list.
8635  This is the function that can delete usershares that have
8636  been removed.
8637 ***************************************************************************/
8638
8639 int load_usershare_shares(struct smbd_server_connection *sconn,
8640                           bool (*snumused) (struct smbd_server_connection *, int))
8641 {
8642         DIR *dp;
8643         SMB_STRUCT_STAT sbuf;
8644         struct dirent *de;
8645         int num_usershares = 0;
8646         int max_user_shares = Globals.iUsershareMaxShares;
8647         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
8648         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
8649         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
8650         int iService;
8651         int snum_template = -1;
8652         const char *usersharepath = Globals.szUsersharePath;
8653         int ret = lp_numservices();
8654         TALLOC_CTX *tmp_ctx;
8655
8656         if (max_user_shares == 0 || *usersharepath == '\0') {
8657                 return lp_numservices();
8658         }
8659
8660         if (sys_stat(usersharepath, &sbuf, false) != 0) {
8661                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
8662                         usersharepath, strerror(errno) ));
8663                 return ret;
8664         }
8665
8666         /*
8667          * This directory must be owned by root, and have the 't' bit set.
8668          * It also must not be writable by "other".
8669          */
8670
8671 #ifdef S_ISVTX
8672         if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
8673 #else
8674         if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
8675 #endif
8676                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
8677                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
8678                         usersharepath ));
8679                 return ret;
8680         }
8681
8682         /* Ensure the template share exists if it's set. */
8683         if (Globals.szUsershareTemplateShare[0]) {
8684                 /* We can't use lp_servicenumber here as we are recommending that
8685                    template shares have -valid=false set. */
8686                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
8687                         if (ServicePtrs[snum_template]->szService &&
8688                                         strequal(ServicePtrs[snum_template]->szService,
8689                                                 Globals.szUsershareTemplateShare)) {
8690                                 break;
8691                         }
8692                 }
8693
8694                 if (snum_template == -1) {
8695                         DEBUG(0,("load_usershare_shares: usershare template share %s "
8696                                 "does not exist.\n",
8697                                 Globals.szUsershareTemplateShare ));
8698                         return ret;
8699                 }
8700         }
8701
8702         /* Mark all existing usershares as pending delete. */
8703         for (iService = iNumServices - 1; iService >= 0; iService--) {
8704                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
8705                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
8706                 }
8707         }
8708
8709         dp = opendir(usersharepath);
8710         if (!dp) {
8711                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
8712                         usersharepath, strerror(errno) ));
8713                 return ret;
8714         }
8715
8716         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
8717                         (de = readdir(dp));
8718                         num_dir_entries++ ) {
8719                 int r;
8720                 const char *n = de->d_name;
8721
8722                 /* Ignore . and .. */
8723                 if (*n == '.') {
8724                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
8725                                 continue;
8726                         }
8727                 }
8728
8729                 if (n[0] == ':') {
8730                         /* Temporary file used when creating a share. */
8731                         num_tmp_dir_entries++;
8732                 }
8733
8734                 /* Allow 20% tmp entries. */
8735                 if (num_tmp_dir_entries > allowed_tmp_entries) {
8736                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
8737                                 "in directory %s\n",
8738                                 num_tmp_dir_entries, usersharepath));
8739                         break;
8740                 }
8741
8742                 r = process_usershare_file(usersharepath, n, snum_template);
8743                 if (r == 0) {
8744                         /* Update the services count. */
8745                         num_usershares++;
8746                         if (num_usershares >= max_user_shares) {
8747                                 DEBUG(0,("load_usershare_shares: max user shares reached "
8748                                         "on file %s in directory %s\n",
8749                                         n, usersharepath ));
8750                                 break;
8751                         }
8752                 } else if (r == -1) {
8753                         num_bad_dir_entries++;
8754                 }
8755
8756                 /* Allow 20% bad entries. */
8757                 if (num_bad_dir_entries > allowed_bad_entries) {
8758                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
8759                                 "in directory %s\n",
8760                                 num_bad_dir_entries, usersharepath));
8761                         break;
8762                 }
8763
8764                 /* Allow 20% bad entries. */
8765                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
8766                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
8767                         "in directory %s\n",
8768                         num_dir_entries, usersharepath));
8769                         break;
8770                 }
8771         }
8772
8773         closedir(dp);
8774
8775         /* Sweep through and delete any non-refreshed usershares that are
8776            not currently in use. */
8777         tmp_ctx = talloc_stackframe();
8778         for (iService = iNumServices - 1; iService >= 0; iService--) {
8779                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
8780                         char *servname;
8781
8782                         if (snumused && snumused(sconn, iService)) {
8783                                 continue;
8784                         }
8785
8786                         servname = lp_servicename(tmp_ctx, iService);
8787
8788                         /* Remove from the share ACL db. */
8789                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
8790                                   servname ));
8791                         delete_share_security(servname);
8792                         free_service_byindex(iService);
8793                 }
8794         }
8795         talloc_free(tmp_ctx);
8796
8797         return lp_numservices();
8798 }
8799
8800 /********************************************************
8801  Destroy global resources allocated in this file
8802 ********************************************************/
8803
8804 void gfree_loadparm(void)
8805 {
8806         int i;
8807
8808         free_file_list();
8809
8810         /* Free resources allocated to services */
8811
8812         for ( i = 0; i < iNumServices; i++ ) {
8813                 if ( VALID(i) ) {
8814                         free_service_byindex(i);
8815                 }
8816         }
8817
8818         SAFE_FREE( ServicePtrs );
8819         iNumServices = 0;
8820
8821         /* Now release all resources allocated to global
8822            parameters and the default service */
8823
8824         free_global_parameters();
8825 }
8826
8827
8828 /***************************************************************************
8829  Allow client apps to specify that they are a client
8830 ***************************************************************************/
8831 static void lp_set_in_client(bool b)
8832 {
8833     in_client = b;
8834 }
8835
8836
8837 /***************************************************************************
8838  Determine if we're running in a client app
8839 ***************************************************************************/
8840 static bool lp_is_in_client(void)
8841 {
8842     return in_client;
8843 }
8844
8845 /***************************************************************************
8846  Load the services array from the services file. Return true on success,
8847  false on failure.
8848 ***************************************************************************/
8849
8850 static bool lp_load_ex(const char *pszFname,
8851                        bool global_only,
8852                        bool save_defaults,
8853                        bool add_ipc,
8854                        bool initialize_globals,
8855                        bool allow_include_registry,
8856                        bool load_all_shares)
8857 {
8858         char *n2 = NULL;
8859         bool bRetval;
8860
8861         bRetval = false;
8862
8863         DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
8864
8865         bInGlobalSection = true;
8866         bGlobalOnly = global_only;
8867         bAllowIncludeRegistry = allow_include_registry;
8868
8869         init_globals(initialize_globals);
8870
8871         free_file_list();
8872
8873         if (save_defaults) {
8874                 init_locals();
8875                 lp_save_defaults();
8876         }
8877
8878         if (!initialize_globals) {
8879                 free_param_opts(&Globals.param_opt);
8880                 apply_lp_set_cmdline();
8881         }
8882
8883         lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
8884
8885         /* We get sections first, so have to start 'behind' to make up */
8886         iServiceIndex = -1;
8887
8888         if (lp_config_backend_is_file()) {
8889                 n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
8890                                         current_user_info.domain,
8891                                         pszFname);
8892                 if (!n2) {
8893                         smb_panic("lp_load_ex: out of memory");
8894                 }
8895
8896                 add_to_file_list(pszFname, n2);
8897
8898                 bRetval = pm_process(n2, do_section, do_parameter, NULL);
8899                 TALLOC_FREE(n2);
8900
8901                 /* finish up the last section */
8902                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
8903                 if (bRetval) {
8904                         if (iServiceIndex >= 0) {
8905                                 bRetval = service_ok(iServiceIndex);
8906                         }
8907                 }
8908
8909                 if (lp_config_backend_is_registry()) {
8910                         /* config backend changed to registry in config file */
8911                         /*
8912                          * We need to use this extra global variable here to
8913                          * survive restart: init_globals uses this as a default
8914                          * for ConfigBackend. Otherwise, init_globals would
8915                          *  send us into an endless loop here.
8916                          */
8917                         config_backend = CONFIG_BACKEND_REGISTRY;
8918                         /* start over */
8919                         DEBUG(1, ("lp_load_ex: changing to config backend "
8920                                   "registry\n"));
8921                         init_globals(true);
8922                         lp_kill_all_services();
8923                         return lp_load_ex(pszFname, global_only, save_defaults,
8924                                           add_ipc, initialize_globals,
8925                                           allow_include_registry,
8926                                           load_all_shares);
8927                 }
8928         } else if (lp_config_backend_is_registry()) {
8929                 bRetval = process_registry_globals();
8930         } else {
8931                 DEBUG(0, ("Illegal config  backend given: %d\n",
8932                           lp_config_backend()));
8933                 bRetval = false;
8934         }
8935
8936         if (bRetval && lp_registry_shares()) {
8937                 if (load_all_shares) {
8938                         bRetval = process_registry_shares();
8939                 } else {
8940                         bRetval = reload_registry_shares();
8941                 }
8942         }
8943
8944         {
8945                 char *serv = lp_auto_services(talloc_tos());
8946                 lp_add_auto_services(serv);
8947                 TALLOC_FREE(serv);
8948         }
8949
8950         if (add_ipc) {
8951                 /* When 'restrict anonymous = 2' guest connections to ipc$
8952                    are denied */
8953                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
8954                 if ( lp_enable_asu_support() ) {
8955                         lp_add_ipc("ADMIN$", false);
8956                 }
8957         }
8958
8959         set_allowed_client_auth();
8960
8961         if (lp_security() == SEC_ADS && strchr(lp_passwordserver(), ':')) {
8962                 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
8963                           lp_passwordserver()));
8964         }
8965
8966         bLoaded = true;
8967
8968         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
8969         /* if bWINSsupport is true and we are in the client            */
8970         if (lp_is_in_client() && Globals.bWINSsupport) {
8971                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
8972         }
8973
8974         init_iconv();
8975
8976         fault_configure(smb_panic_s3);
8977
8978         bAllowIncludeRegistry = true;
8979
8980         return (bRetval);
8981 }
8982
8983 bool lp_load(const char *pszFname,
8984              bool global_only,
8985              bool save_defaults,
8986              bool add_ipc,
8987              bool initialize_globals)
8988 {
8989         return lp_load_ex(pszFname,
8990                           global_only,
8991                           save_defaults,
8992                           add_ipc,
8993                           initialize_globals,
8994                           true,   /* allow_include_registry */
8995                           false); /* load_all_shares*/
8996 }
8997
8998 bool lp_load_initial_only(const char *pszFname)
8999 {
9000         return lp_load_ex(pszFname,
9001                           true,   /* global only */
9002                           false,  /* save_defaults */
9003                           false,  /* add_ipc */
9004                           true,   /* initialize_globals */
9005                           false,  /* allow_include_registry */
9006                           false); /* load_all_shares*/
9007 }
9008
9009 /**
9010  * most common lp_load wrapper, loading only the globals
9011  */
9012 bool lp_load_global(const char *file_name)
9013 {
9014         return lp_load_ex(file_name,
9015                           true,   /* global_only */
9016                           false,  /* save_defaults */
9017                           false,  /* add_ipc */
9018                           true,   /* initialize_globals */
9019                           true,   /* allow_include_registry */
9020                           false); /* load_all_shares*/
9021 }
9022
9023 /**
9024  * lp_load wrapper, especially for clients
9025  */
9026 bool lp_load_client(const char *file_name)
9027 {
9028         lp_set_in_client(true);
9029
9030         return lp_load_global(file_name);
9031 }
9032
9033 /**
9034  * lp_load wrapper, loading only globals, but intended
9035  * for subsequent calls, not reinitializing the globals
9036  * to default values
9037  */
9038 bool lp_load_global_no_reinit(const char *file_name)
9039 {
9040         return lp_load_ex(file_name,
9041                           true,   /* global_only */
9042                           false,  /* save_defaults */
9043                           false,  /* add_ipc */
9044                           false,  /* initialize_globals */
9045                           true,   /* allow_include_registry */
9046                           false); /* load_all_shares*/
9047 }
9048
9049 /**
9050  * lp_load wrapper, especially for clients, no reinitialization
9051  */
9052 bool lp_load_client_no_reinit(const char *file_name)
9053 {
9054         lp_set_in_client(true);
9055
9056         return lp_load_global_no_reinit(file_name);
9057 }
9058
9059 bool lp_load_with_registry_shares(const char *pszFname,
9060                                   bool global_only,
9061                                   bool save_defaults,
9062                                   bool add_ipc,
9063                                   bool initialize_globals)
9064 {
9065         return lp_load_ex(pszFname,
9066                           global_only,
9067                           save_defaults,
9068                           add_ipc,
9069                           initialize_globals,
9070                           true,  /* allow_include_registry */
9071                           true); /* load_all_shares*/
9072 }
9073
9074 /***************************************************************************
9075  Return the max number of services.
9076 ***************************************************************************/
9077
9078 int lp_numservices(void)
9079 {
9080         return (iNumServices);
9081 }
9082
9083 /***************************************************************************
9084 Display the contents of the services array in human-readable form.
9085 ***************************************************************************/
9086
9087 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
9088 {
9089         int iService;
9090
9091         if (show_defaults)
9092                 defaults_saved = false;
9093
9094         dump_globals(f);
9095
9096         dump_a_service(&sDefault, f);
9097
9098         for (iService = 0; iService < maxtoprint; iService++) {
9099                 fprintf(f,"\n");
9100                 lp_dump_one(f, show_defaults, iService);
9101         }
9102 }
9103
9104 /***************************************************************************
9105 Display the contents of one service in human-readable form.
9106 ***************************************************************************/
9107
9108 void lp_dump_one(FILE * f, bool show_defaults, int snum)
9109 {
9110         if (VALID(snum)) {
9111                 if (ServicePtrs[snum]->szService[0] == '\0')
9112                         return;
9113                 dump_a_service(ServicePtrs[snum], f);
9114         }
9115 }
9116
9117 /***************************************************************************
9118 Return the number of the service with the given name, or -1 if it doesn't
9119 exist. Note that this is a DIFFERENT ANIMAL from the internal function
9120 getservicebyname()! This works ONLY if all services have been loaded, and
9121 does not copy the found service.
9122 ***************************************************************************/
9123
9124 int lp_servicenumber(const char *pszServiceName)
9125 {
9126         int iService;
9127         fstring serviceName;
9128
9129         if (!pszServiceName) {
9130                 return GLOBAL_SECTION_SNUM;
9131         }
9132
9133         for (iService = iNumServices - 1; iService >= 0; iService--) {
9134                 if (VALID(iService) && ServicePtrs[iService]->szService) {
9135                         /*
9136                          * The substitution here is used to support %U is
9137                          * service names
9138                          */
9139                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
9140                         standard_sub_basic(get_current_username(),
9141                                            current_user_info.domain,
9142                                            serviceName,sizeof(serviceName));
9143                         if (strequal(serviceName, pszServiceName)) {
9144                                 break;
9145                         }
9146                 }
9147         }
9148
9149         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
9150                 struct timespec last_mod;
9151
9152                 if (!usershare_exists(iService, &last_mod)) {
9153                         /* Remove the share security tdb entry for it. */
9154                         delete_share_security(lp_servicename(talloc_tos(), iService));
9155                         /* Remove it from the array. */
9156                         free_service_byindex(iService);
9157                         /* Doesn't exist anymore. */
9158                         return GLOBAL_SECTION_SNUM;
9159                 }
9160
9161                 /* Has it been modified ? If so delete and reload. */
9162                 if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
9163                                      &last_mod) < 0) {
9164                         /* Remove it from the array. */
9165                         free_service_byindex(iService);
9166                         /* and now reload it. */
9167                         iService = load_usershare_service(pszServiceName);
9168                 }
9169         }
9170
9171         if (iService < 0) {
9172                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
9173                 return GLOBAL_SECTION_SNUM;
9174         }
9175
9176         return (iService);
9177 }
9178
9179 /*******************************************************************
9180  A useful volume label function. 
9181 ********************************************************************/
9182
9183 const char *volume_label(TALLOC_CTX *ctx, int snum)
9184 {
9185         char *ret;
9186         const char *label = lp_volume(ctx, snum);
9187         if (!*label) {
9188                 label = lp_servicename(ctx, snum);
9189         }
9190
9191         /* This returns a 33 byte guarenteed null terminated string. */
9192         ret = talloc_strndup(ctx, label, 32);
9193         if (!ret) {
9194                 return "";
9195         }               
9196         return ret;
9197 }
9198
9199 /*******************************************************************
9200  Get the default server type we will announce as via nmbd.
9201 ********************************************************************/
9202
9203 int lp_default_server_announce(void)
9204 {
9205         int default_server_announce = 0;
9206         default_server_announce |= SV_TYPE_WORKSTATION;
9207         default_server_announce |= SV_TYPE_SERVER;
9208         default_server_announce |= SV_TYPE_SERVER_UNIX;
9209
9210         /* note that the flag should be set only if we have a 
9211            printer service but nmbd doesn't actually load the 
9212            services so we can't tell   --jerry */
9213
9214         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
9215
9216         default_server_announce |= SV_TYPE_SERVER_NT;
9217         default_server_announce |= SV_TYPE_NT;
9218
9219         switch (lp_server_role()) {
9220                 case ROLE_DOMAIN_MEMBER:
9221                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
9222                         break;
9223                 case ROLE_DOMAIN_PDC:
9224                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
9225                         break;
9226                 case ROLE_DOMAIN_BDC:
9227                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
9228                         break;
9229                 case ROLE_STANDALONE:
9230                 default:
9231                         break;
9232         }
9233         if (lp_time_server())
9234                 default_server_announce |= SV_TYPE_TIME_SOURCE;
9235
9236         if (lp_host_msdfs())
9237                 default_server_announce |= SV_TYPE_DFS_SERVER;
9238
9239         return default_server_announce;
9240 }
9241
9242 /***********************************************************
9243  If we are PDC then prefer us as DMB
9244 ************************************************************/
9245
9246 bool lp_domain_master(void)
9247 {
9248         if (Globals.domain_master == Auto)
9249                 return (lp_server_role() == ROLE_DOMAIN_PDC);
9250
9251         return (bool)Globals.domain_master;
9252 }
9253
9254 /***********************************************************
9255  If we are PDC then prefer us as DMB
9256 ************************************************************/
9257
9258 static bool lp_domain_master_true_or_auto(void)
9259 {
9260         if (Globals.domain_master) /* auto or yes */
9261                 return true;
9262
9263         return false;
9264 }
9265
9266 /***********************************************************
9267  If we are DMB then prefer us as LMB
9268 ************************************************************/
9269
9270 bool lp_preferred_master(void)
9271 {
9272         if (Globals.iPreferredMaster == Auto)
9273                 return (lp_local_master() && lp_domain_master());
9274
9275         return (bool)Globals.iPreferredMaster;
9276 }
9277
9278 /*******************************************************************
9279  Remove a service.
9280 ********************************************************************/
9281
9282 void lp_remove_service(int snum)
9283 {
9284         ServicePtrs[snum]->valid = false;
9285         invalid_services[num_invalid_services++] = snum;
9286 }
9287
9288 /*******************************************************************
9289  Copy a service.
9290 ********************************************************************/
9291
9292 void lp_copy_service(int snum, const char *new_name)
9293 {
9294         do_section(new_name, NULL);
9295         if (snum >= 0) {
9296                 snum = lp_servicenumber(new_name);
9297                 if (snum >= 0) {
9298                         char *name = lp_servicename(talloc_tos(), snum);
9299                         lp_do_parameter(snum, "copy", name);
9300                 }
9301         }
9302 }
9303
9304 const char *lp_printername(TALLOC_CTX *ctx, int snum)
9305 {
9306         const char *ret = lp__printername(talloc_tos(), snum);
9307         if (ret == NULL || *ret == '\0') {
9308                 ret = lp_const_servicename(snum);
9309         }
9310
9311         return ret;
9312 }
9313
9314
9315 /***********************************************************
9316  Allow daemons such as winbindd to fix their logfile name.
9317 ************************************************************/
9318
9319 void lp_set_logfile(const char *name)
9320 {
9321         string_set(&Globals.logfile, name);
9322         debug_set_logfile(name);
9323 }
9324
9325 /*******************************************************************
9326  Return the max print jobs per queue.
9327 ********************************************************************/
9328
9329 int lp_maxprintjobs(int snum)
9330 {
9331         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
9332         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
9333                 maxjobs = PRINT_MAX_JOBID - 1;
9334
9335         return maxjobs;
9336 }
9337
9338 const char *lp_printcapname(void)
9339 {
9340         if ((Globals.szPrintcapname != NULL) &&
9341             (Globals.szPrintcapname[0] != '\0'))
9342                 return Globals.szPrintcapname;
9343
9344         if (sDefault.iPrinting == PRINT_CUPS) {
9345 #ifdef HAVE_CUPS
9346                 return "cups";
9347 #else
9348                 return "lpstat";
9349 #endif
9350         }
9351
9352         if (sDefault.iPrinting == PRINT_BSD)
9353                 return "/etc/printcap";
9354
9355         return PRINTCAP_NAME;
9356 }
9357
9358 static uint32 spoolss_state;
9359
9360 bool lp_disable_spoolss( void )
9361 {
9362         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
9363                 spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9364
9365         return spoolss_state == SVCCTL_STOPPED ? true : false;
9366 }
9367
9368 void lp_set_spoolss_state( uint32 state )
9369 {
9370         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
9371
9372         spoolss_state = state;
9373 }
9374
9375 uint32 lp_get_spoolss_state( void )
9376 {
9377         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
9378 }
9379
9380 /*******************************************************************
9381  Ensure we don't use sendfile if server smb signing is active.
9382 ********************************************************************/
9383
9384 bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
9385 {
9386         bool sign_active = false;
9387
9388         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
9389         if (get_Protocol() < PROTOCOL_NT1) {
9390                 return false;
9391         }
9392         if (signing_state) {
9393                 sign_active = smb_signing_is_active(signing_state);
9394         }
9395         return (lp__use_sendfile(snum) &&
9396                         (get_remote_arch() != RA_WIN95) &&
9397                         !sign_active);
9398 }
9399
9400 /*******************************************************************
9401  Turn off sendfile if we find the underlying OS doesn't support it.
9402 ********************************************************************/
9403
9404 void set_use_sendfile(int snum, bool val)
9405 {
9406         if (LP_SNUM_OK(snum))
9407                 ServicePtrs[snum]->bUseSendfile = val;
9408         else
9409                 sDefault.bUseSendfile = val;
9410 }
9411
9412 /*******************************************************************
9413  Turn off storing DOS attributes if this share doesn't support it.
9414 ********************************************************************/
9415
9416 void set_store_dos_attributes(int snum, bool val)
9417 {
9418         if (!LP_SNUM_OK(snum))
9419                 return;
9420         ServicePtrs[(snum)]->bStoreDosAttributes = val;
9421 }
9422
9423 void lp_set_mangling_method(const char *new_method)
9424 {
9425         string_set(&Globals.szManglingMethod, new_method);
9426 }
9427
9428 /*******************************************************************
9429  Global state for POSIX pathname processing.
9430 ********************************************************************/
9431
9432 static bool posix_pathnames;
9433
9434 bool lp_posix_pathnames(void)
9435 {
9436         return posix_pathnames;
9437 }
9438
9439 /*******************************************************************
9440  Change everything needed to ensure POSIX pathname processing (currently
9441  not much).
9442 ********************************************************************/
9443
9444 void lp_set_posix_pathnames(void)
9445 {
9446         posix_pathnames = true;
9447 }
9448
9449 /*******************************************************************
9450  Global state for POSIX lock processing - CIFS unix extensions.
9451 ********************************************************************/
9452
9453 bool posix_default_lock_was_set;
9454 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
9455
9456 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
9457 {
9458         if (posix_default_lock_was_set) {
9459                 return posix_cifsx_locktype;
9460         } else {
9461                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
9462         }
9463 }
9464
9465 /*******************************************************************
9466 ********************************************************************/
9467
9468 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
9469 {
9470         posix_default_lock_was_set = true;
9471         posix_cifsx_locktype = val;
9472 }
9473
9474 int lp_min_receive_file_size(void)
9475 {
9476         if (Globals.iminreceivefile < 0) {
9477                 return 0;
9478         }
9479         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
9480 }
9481
9482 /*******************************************************************
9483  If socket address is an empty character string, it is necessary to 
9484  define it as "0.0.0.0". 
9485 ********************************************************************/
9486
9487 const char *lp_socket_address(void)
9488 {
9489         char *sock_addr = Globals.szSocketAddress;
9490
9491         if (sock_addr[0] == '\0'){
9492                 string_set(&Globals.szSocketAddress, "0.0.0.0");
9493         }
9494         return  Globals.szSocketAddress;
9495 }
9496
9497 /*******************************************************************
9498  Safe wide links checks.
9499  This helper function always verify the validity of wide links,
9500  even after a configuration file reload.
9501 ********************************************************************/
9502
9503 static bool lp_widelinks_internal(int snum)
9504 {
9505         return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks :
9506                         sDefault.bWidelinks);
9507 }
9508
9509 void widelinks_warning(int snum)
9510 {
9511         if (lp_allow_insecure_widelinks()) {
9512                 return;
9513         }
9514
9515         if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
9516                 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
9517                         "These parameters are incompatible. "
9518                         "Wide links will be disabled for this share.\n",
9519                          lp_servicename(talloc_tos(), snum) ));
9520         }
9521 }
9522
9523 bool lp_widelinks(int snum)
9524 {
9525         /* wide links is always incompatible with unix extensions */
9526         if (lp_unix_extensions()) {
9527                 /*
9528                  * Unless we have "allow insecure widelinks"
9529                  * turned on.
9530                  */
9531                 if (!lp_allow_insecure_widelinks()) {
9532                         return false;
9533                 }
9534         }
9535
9536         return lp_widelinks_internal(snum);
9537 }
9538
9539 bool lp_writeraw(void)
9540 {
9541         if (lp_async_smb_echo_handler()) {
9542                 return false;
9543         }
9544         return lp__writeraw();
9545 }
9546
9547 bool lp_readraw(void)
9548 {
9549         if (lp_async_smb_echo_handler()) {
9550                 return false;
9551         }
9552         return lp__readraw();
9553 }
9554
9555 int lp_server_role(void)
9556 {
9557         return lp_find_server_role(lp__server_role(),
9558                                    lp_security(),
9559                                    lp_domain_logons(),
9560                                    lp_domain_master_true_or_auto());
9561 }