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