Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test
[ira/wip.git] / source / 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    
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 3 of the License, or
17    (at your option) any later version.
18    
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23    
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
26 */
27
28 /*
29  *  Load parameters.
30  *
31  *  This module provides suitable callback functions for the params
32  *  module. It builds the internal table of service details which is
33  *  then used by the rest of the server.
34  *
35  * To add a parameter:
36  *
37  * 1) add it to the global or service structure definition
38  * 2) add it to the parm_table
39  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40  * 4) If it's a global then initialise it in init_globals. If a local
41  *    (ie. service) parameter then initialise it in the sDefault structure
42  *  
43  *
44  * Notes:
45  *   The configuration file is processed sequentially for speed. It is NOT
46  *   accessed randomly as happens in 'real' Windows. For this reason, there
47  *   is a fair bit of sequence-dependent code here - ie., code which assumes
48  *   that certain things happen before others. In particular, the code which
49  *   happens at the boundary between sections is delicately poised, so be
50  *   careful!
51  *
52  */
53
54 #include "includes.h"
55 #include "libnet/libnet.h"
56
57 bool in_client = False;         /* Not in the client by default */
58 bool bLoaded = False;
59
60 extern enum protocol_types Protocol;
61 extern userdom_struct current_user_info;
62
63 #ifndef GLOBAL_NAME
64 #define GLOBAL_NAME "global"
65 #endif
66
67 #ifndef PRINTERS_NAME
68 #define PRINTERS_NAME "printers"
69 #endif
70
71 #ifndef HOMES_NAME
72 #define HOMES_NAME "homes"
73 #endif
74
75 static uint64_t conf_last_seqnum = 0;
76 static struct libnet_conf_ctx *conf_ctx = NULL;
77
78 #define CONFIG_BACKEND_FILE 0
79 #define CONFIG_BACKEND_REGISTRY 1
80
81 static int config_backend = CONFIG_BACKEND_FILE;
82
83 /* some helpful bits */
84 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
85 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
86
87 #define USERSHARE_VALID 1
88 #define USERSHARE_PENDING_DELETE 2
89
90 extern int extra_time_offset;
91
92 static bool defaults_saved = False;
93
94 typedef struct _param_opt_struct param_opt_struct;
95 struct _param_opt_struct {
96         param_opt_struct *prev, *next;
97         char *key;
98         char *value;
99         char **list;
100 };
101
102 /* 
103  * This structure describes global (ie., server-wide) parameters.
104  */
105 typedef struct {
106         int ConfigBackend;
107         char *smb_ports;
108         char *dos_charset;
109         char *unix_charset;
110         char *display_charset;
111         char *szPrintcapname;
112         char *szAddPortCommand;
113         char *szEnumPortsCommand;
114         char *szAddPrinterCommand;
115         char *szDeletePrinterCommand;
116         char *szOs2DriverMap;
117         char *szLockDir;
118         char *szPidDir;
119         char *szRootdir;
120         char *szDefaultService;
121         char *szGetQuota;
122         char *szSetQuota;
123         char *szMsgCommand;
124         char *szServerString;
125         char *szAutoServices;
126         char *szPasswdProgram;
127         char *szPasswdChat;
128         char *szLogFile;
129         char *szConfigFile;
130         char *szSMBPasswdFile;
131         char *szPrivateDir;
132         char *szPassdbBackend;
133         char **szPreloadModules;
134         char *szPasswordServer;
135         char *szSocketOptions;
136         char *szRealm;
137         char *szAfsUsernameMap;
138         int iAfsTokenLifetime;
139         char *szLogNtTokenCommand;
140         char *szUsernameMap;
141         char *szLogonScript;
142         char *szLogonPath;
143         char *szLogonDrive;
144         char *szLogonHome;
145         char **szWINSservers;
146         char **szInterfaces;
147         char *szRemoteAnnounce;
148         char *szRemoteBrowseSync;
149         char *szSocketAddress;
150         char *szNISHomeMapName;
151         char *szAnnounceVersion;        /* This is initialised in init_globals */
152         char *szWorkgroup;
153         char *szNetbiosName;
154         char **szNetbiosAliases;
155         char *szNetbiosScope;
156         char *szNameResolveOrder;
157         char *szPanicAction;
158         char *szAddUserScript;
159         char *szRenameUserScript;
160         char *szDelUserScript;
161         char *szAddGroupScript;
162         char *szDelGroupScript;
163         char *szAddUserToGroupScript;
164         char *szDelUserFromGroupScript;
165         char *szSetPrimaryGroupScript;
166         char *szAddMachineScript;
167         char *szShutdownScript;
168         char *szAbortShutdownScript;
169         char *szUsernameMapScript;
170         char *szCheckPasswordScript;
171         char *szWINSHook;
172         char *szUtmpDir;
173         char *szWtmpDir;
174         bool bUtmp;
175         char *szIdmapUID;
176         char *szIdmapGID;
177         bool bPassdbExpandExplicit;
178         int AlgorithmicRidBase;
179         char *szTemplateHomedir;
180         char *szTemplateShell;
181         char *szWinbindSeparator;
182         bool bWinbindEnumUsers;
183         bool bWinbindEnumGroups;
184         bool bWinbindUseDefaultDomain;
185         bool bWinbindTrustedDomainsOnly;
186         bool bWinbindNestedGroups;
187         int  winbind_expand_groups;
188         bool bWinbindRefreshTickets;
189         bool bWinbindOfflineLogon;
190         bool bWinbindNormalizeNames;
191         bool bWinbindRpcOnly;
192         char **szIdmapDomains;
193         char **szIdmapBackend; /* deprecated */
194         char *szIdmapAllocBackend;
195         char *szAddShareCommand;
196         char *szChangeShareCommand;
197         char *szDeleteShareCommand;
198         char **szEventLogs;
199         char *szGuestaccount;
200         char *szManglingMethod;
201         char **szServicesList;
202         char *szUsersharePath;
203         char *szUsershareTemplateShare;
204         char **szUsersharePrefixAllowList;
205         char **szUsersharePrefixDenyList;
206         int mangle_prefix;
207         int max_log_size;
208         char *szLogLevel;
209         int max_xmit;
210         int max_mux;
211         int max_open_files;
212         int open_files_db_hash_size;
213         int pwordlevel;
214         int unamelevel;
215         int deadtime;
216         bool getwd_cache;
217         int maxprotocol;
218         int minprotocol;
219         int security;
220         char **AuthMethods;
221         bool paranoid_server_security;
222         int maxdisksize;
223         int lpqcachetime;
224         int iMaxSmbdProcesses;
225         bool bDisableSpoolss;
226         int syslog;
227         int os_level;
228         bool enhanced_browsing;
229         int max_ttl;
230         int max_wins_ttl;
231         int min_wins_ttl;
232         int lm_announce;
233         int lm_interval;
234         int announce_as;        /* This is initialised in init_globals */
235         int machine_password_timeout;
236         int map_to_guest;
237         int oplock_break_wait_time;
238         int winbind_cache_time;
239         int winbind_max_idle_children;
240         char **szWinbindNssInfo;
241         int iLockSpinTime;
242         char *szLdapMachineSuffix;
243         char *szLdapUserSuffix;
244         char *szLdapIdmapSuffix;
245         char *szLdapGroupSuffix;
246         int ldap_ssl;
247         char *szLdapSuffix;
248         char *szLdapAdminDn;
249         int ldap_debug_level;
250         int ldap_debug_threshold;
251         int iAclCompat;
252         char *szCupsServer;
253         char *szIPrintServer;
254         char *ctdbdSocket;
255         char **szClusterAddresses;
256         bool clustering;
257         int ldap_passwd_sync;
258         int ldap_replication_sleep;
259         int ldap_timeout; /* This is initialised in init_globals */
260         int ldap_page_size;
261         bool ldap_delete_dn;
262         bool bMsAddPrinterWizard;
263         bool bDNSproxy;
264         bool bWINSsupport;
265         bool bWINSproxy;
266         bool bLocalMaster;
267         int  iPreferredMaster;
268         int iDomainMaster;
269         bool bDomainLogons;
270         bool bEncryptPasswords;
271         bool bUpdateEncrypt;
272         int  clientSchannel;
273         int  serverSchannel;
274         bool bNullPasswords;
275         bool bObeyPamRestrictions;
276         bool bLoadPrinters;
277         int PrintcapCacheTime;
278         bool bLargeReadwrite;
279         bool bReadRaw;
280         bool bWriteRaw;
281         bool bSyslogOnly;
282         bool bBrowseList;
283         bool bNISHomeMap;
284         bool bTimeServer;
285         bool bBindInterfacesOnly;
286         bool bPamPasswordChange;
287         bool bUnixPasswdSync;
288         bool bPasswdChatDebug;
289         int iPasswdChatTimeout;
290         bool bTimestampLogs;
291         bool bNTSmbSupport;
292         bool bNTPipeSupport;
293         bool bNTStatusSupport;
294         bool bStatCache;
295         int iMaxStatCacheSize;
296         bool bKernelOplocks;
297         bool bAllowTrustedDomains;
298         bool bLanmanAuth;
299         bool bNTLMAuth;
300         bool bUseSpnego;
301         bool bClientLanManAuth;
302         bool bClientNTLMv2Auth;
303         bool bClientPlaintextAuth;
304         bool bClientUseSpnego;
305         bool bDebugPrefixTimestamp;
306         bool bDebugHiresTimestamp;
307         bool bDebugPid;
308         bool bDebugUid;
309         bool bDebugClass;
310         bool bEnableCoreFiles;
311         bool bHostMSDfs;
312         bool bUseMmap;
313         bool bHostnameLookups;
314         bool bUnixExtensions;
315         bool bDisableNetbios;
316         bool bUseKerberosKeytab;
317         bool bDeferSharingViolations;
318         bool bEnablePrivileges;
319         bool bASUSupport;
320         bool bUsershareOwnerOnly;
321         bool bUsershareAllowGuests;
322         bool bRegistryShares;
323         int restrict_anonymous;
324         int name_cache_timeout;
325         int client_signing;
326         int server_signing;
327         int client_ldap_sasl_wrapping;
328         int iUsershareMaxShares;
329         int iIdmapCacheTime;
330         int iIdmapNegativeCacheTime;
331
332         bool bResetOnZeroVC;
333         int iKeepalive;
334         int iminreceivefile;
335         param_opt_struct *param_opt;
336 } global;
337
338 static global Globals;
339
340 /* 
341  * This structure describes a single service. 
342  */
343 typedef struct {
344         bool valid;
345         bool autoloaded;
346         int usershare;
347         time_t usershare_last_mod;
348         char *szService;
349         char *szPath;
350         char *szUsername;
351         char **szInvalidUsers;
352         char **szValidUsers;
353         char **szAdminUsers;
354         char *szCopy;
355         char *szInclude;
356         char *szPreExec;
357         char *szPostExec;
358         char *szRootPreExec;
359         char *szRootPostExec;
360         char *szCupsOptions;
361         char *szPrintcommand;
362         char *szLpqcommand;
363         char *szLprmcommand;
364         char *szLppausecommand;
365         char *szLpresumecommand;
366         char *szQueuepausecommand;
367         char *szQueueresumecommand;
368         char *szPrintername;
369         char *szPrintjobUsername;
370         char *szDontdescend;
371         char **szHostsallow;
372         char **szHostsdeny;
373         char *szMagicScript;
374         char *szMagicOutput;
375         char *szVetoFiles;
376         char *szHideFiles;
377         char *szVetoOplockFiles;
378         char *comment;
379         char *force_user;
380         char *force_group;
381         char **readlist;
382         char **writelist;
383         char **printer_admin;
384         char *volume;
385         char *fstype;
386         char **szVfsObjects;
387         char *szMSDfsProxy;
388         char *szAioWriteBehind;
389         char *szDfree;
390         int iMinPrintSpace;
391         int iMaxPrintJobs;
392         int iMaxReportedPrintJobs;
393         int iWriteCacheSize;
394         int iCreate_mask;
395         int iCreate_force_mode;
396         int iSecurity_mask;
397         int iSecurity_force_mode;
398         int iDir_mask;
399         int iDir_force_mode;
400         int iDir_Security_mask;
401         int iDir_Security_force_mode;
402         int iMaxConnections;
403         int iDefaultCase;
404         int iPrinting;
405         int iOplockContentionLimit;
406         int iCSCPolicy;
407         int iBlock_size;
408         int iDfreeCacheTime;
409         bool bPreexecClose;
410         bool bRootpreexecClose;
411         int  iCaseSensitive;
412         bool bCasePreserve;
413         bool bShortCasePreserve;
414         bool bHideDotFiles;
415         bool bHideSpecialFiles;
416         bool bHideUnReadable;
417         bool bHideUnWriteableFiles;
418         bool bBrowseable;
419         bool bAvailable;
420         bool bRead_only;
421         bool bNo_set_dir;
422         bool bGuest_only;
423         bool bGuest_ok;
424         bool bPrint_ok;
425         bool bMap_system;
426         bool bMap_hidden;
427         bool bMap_archive;
428         bool bStoreDosAttributes;
429         bool bDmapiSupport;
430         bool bLocking;
431         int iStrictLocking;
432         bool bPosixLocking;
433         bool bShareModes;
434         bool bOpLocks;
435         bool bLevel2OpLocks;
436         bool bOnlyUser;
437         bool bMangledNames;
438         bool bWidelinks;
439         bool bSymlinks;
440         bool bSyncAlways;
441         bool bStrictAllocate;
442         bool bStrictSync;
443         char magic_char;
444         struct bitmap *copymap;
445         bool bDeleteReadonly;
446         bool bFakeOplocks;
447         bool bDeleteVetoFiles;
448         bool bDosFilemode;
449         bool bDosFiletimes;
450         bool bDosFiletimeResolution;
451         bool bFakeDirCreateTimes;
452         bool bBlockingLocks;
453         bool bInheritPerms;
454         bool bInheritACLS;
455         bool bInheritOwner;
456         bool bMSDfsRoot;
457         bool bUseClientDriver;
458         bool bDefaultDevmode;
459         bool bForcePrintername;
460         bool bNTAclSupport;
461         bool bForceUnknownAclUser;
462         bool bUseSendfile;
463         bool bProfileAcls;
464         bool bMap_acl_inherit;
465         bool bAfs_Share;
466         bool bEASupport;
467         bool bAclCheckPermissions;
468         bool bAclMapFullControl;
469         bool bAclGroupControl;
470         bool bChangeNotify;
471         bool bKernelChangeNotify;
472         int iallocation_roundup_size;
473         int iAioReadSize;
474         int iAioWriteSize;
475         int iMap_readonly;
476         int iDirectoryNameCacheSize;
477         int ismb_encrypt;
478         param_opt_struct *param_opt;
479
480         char dummy[3];          /* for alignment */
481 } service;
482
483
484 /* This is a default service used to prime a services structure */
485 static service sDefault = {
486         True,                   /* valid */
487         False,                  /* not autoloaded */
488         0,                      /* not a usershare */
489         (time_t)0,              /* No last mod time */
490         NULL,                   /* szService */
491         NULL,                   /* szPath */
492         NULL,                   /* szUsername */
493         NULL,                   /* szInvalidUsers */
494         NULL,                   /* szValidUsers */
495         NULL,                   /* szAdminUsers */
496         NULL,                   /* szCopy */
497         NULL,                   /* szInclude */
498         NULL,                   /* szPreExec */
499         NULL,                   /* szPostExec */
500         NULL,                   /* szRootPreExec */
501         NULL,                   /* szRootPostExec */
502         NULL,                   /* szCupsOptions */
503         NULL,                   /* szPrintcommand */
504         NULL,                   /* szLpqcommand */
505         NULL,                   /* szLprmcommand */
506         NULL,                   /* szLppausecommand */
507         NULL,                   /* szLpresumecommand */
508         NULL,                   /* szQueuepausecommand */
509         NULL,                   /* szQueueresumecommand */
510         NULL,                   /* szPrintername */
511         NULL,                   /* szPrintjobUsername */
512         NULL,                   /* szDontdescend */
513         NULL,                   /* szHostsallow */
514         NULL,                   /* szHostsdeny */
515         NULL,                   /* szMagicScript */
516         NULL,                   /* szMagicOutput */
517         NULL,                   /* szVetoFiles */
518         NULL,                   /* szHideFiles */
519         NULL,                   /* szVetoOplockFiles */
520         NULL,                   /* comment */
521         NULL,                   /* force user */
522         NULL,                   /* force group */
523         NULL,                   /* readlist */
524         NULL,                   /* writelist */
525         NULL,                   /* printer admin */
526         NULL,                   /* volume */
527         NULL,                   /* fstype */
528         NULL,                   /* vfs objects */
529         NULL,                   /* szMSDfsProxy */
530         NULL,                   /* szAioWriteBehind */
531         NULL,                   /* szDfree */
532         0,                      /* iMinPrintSpace */
533         1000,                   /* iMaxPrintJobs */
534         0,                      /* iMaxReportedPrintJobs */
535         0,                      /* iWriteCacheSize */
536         0744,                   /* iCreate_mask */
537         0000,                   /* iCreate_force_mode */
538         0777,                   /* iSecurity_mask */
539         0,                      /* iSecurity_force_mode */
540         0755,                   /* iDir_mask */
541         0000,                   /* iDir_force_mode */
542         0777,                   /* iDir_Security_mask */
543         0,                      /* iDir_Security_force_mode */
544         0,                      /* iMaxConnections */
545         CASE_LOWER,             /* iDefaultCase */
546         DEFAULT_PRINTING,       /* iPrinting */
547         2,                      /* iOplockContentionLimit */
548         0,                      /* iCSCPolicy */
549         1024,                   /* iBlock_size */
550         0,                      /* iDfreeCacheTime */
551         False,                  /* bPreexecClose */
552         False,                  /* bRootpreexecClose */
553         Auto,                   /* case sensitive */
554         True,                   /* case preserve */
555         True,                   /* short case preserve */
556         True,                   /* bHideDotFiles */
557         False,                  /* bHideSpecialFiles */
558         False,                  /* bHideUnReadable */
559         False,                  /* bHideUnWriteableFiles */
560         True,                   /* bBrowseable */
561         True,                   /* bAvailable */
562         True,                   /* bRead_only */
563         True,                   /* bNo_set_dir */
564         False,                  /* bGuest_only */
565         False,                  /* bGuest_ok */
566         False,                  /* bPrint_ok */
567         False,                  /* bMap_system */
568         False,                  /* bMap_hidden */
569         True,                   /* bMap_archive */
570         False,                  /* bStoreDosAttributes */
571         False,                  /* bDmapiSupport */
572         True,                   /* bLocking */
573         Auto,                   /* iStrictLocking */
574         True,                   /* bPosixLocking */
575         True,                   /* bShareModes */
576         True,                   /* bOpLocks */
577         True,                   /* bLevel2OpLocks */
578         False,                  /* bOnlyUser */
579         True,                   /* bMangledNames */
580         True,                   /* bWidelinks */
581         True,                   /* bSymlinks */
582         False,                  /* bSyncAlways */
583         False,                  /* bStrictAllocate */
584         False,                  /* bStrictSync */
585         '~',                    /* magic char */
586         NULL,                   /* copymap */
587         False,                  /* bDeleteReadonly */
588         False,                  /* bFakeOplocks */
589         False,                  /* bDeleteVetoFiles */
590         False,                  /* bDosFilemode */
591         True,                   /* bDosFiletimes */
592         False,                  /* bDosFiletimeResolution */
593         False,                  /* bFakeDirCreateTimes */
594         True,                   /* bBlockingLocks */
595         False,                  /* bInheritPerms */
596         False,                  /* bInheritACLS */
597         False,                  /* bInheritOwner */
598         False,                  /* bMSDfsRoot */
599         False,                  /* bUseClientDriver */
600         True,                   /* bDefaultDevmode */
601         False,                  /* bForcePrintername */
602         True,                   /* bNTAclSupport */
603         False,                  /* bForceUnknownAclUser */
604         False,                  /* bUseSendfile */
605         False,                  /* bProfileAcls */
606         False,                  /* bMap_acl_inherit */
607         False,                  /* bAfs_Share */
608         False,                  /* bEASupport */
609         True,                   /* bAclCheckPermissions */
610         True,                   /* bAclMapFullControl */
611         False,                  /* bAclGroupControl */
612         True,                   /* bChangeNotify */
613         True,                   /* bKernelChangeNotify */
614         SMB_ROUNDUP_ALLOCATION_SIZE,            /* iallocation_roundup_size */
615         0,                      /* iAioReadSize */
616         0,                      /* iAioWriteSize */
617         MAP_READONLY_YES,       /* iMap_readonly */
618 #ifdef BROKEN_DIRECTORY_HANDLING
619         0,                      /* iDirectoryNameCacheSize */
620 #else
621         100,                    /* iDirectoryNameCacheSize */
622 #endif
623         Auto,                   /* ismb_encrypt */
624         NULL,                   /* Parametric options */
625
626         ""                      /* dummy */
627 };
628
629 /* local variables */
630 static service **ServicePtrs = NULL;
631 static int iNumServices = 0;
632 static int iServiceIndex = 0;
633 static struct db_context *ServiceHash;
634 static int *invalid_services = NULL;
635 static int num_invalid_services = 0;
636 static bool bInGlobalSection = True;
637 static bool bGlobalOnly = False;
638 static int server_role;
639 static int default_server_announce;
640
641 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
642
643 /* prototypes for the special type handlers */
644 static bool handle_include( int snum, const char *pszParmValue, char **ptr);
645 static bool handle_copy( int snum, const char *pszParmValue, char **ptr);
646 static bool handle_netbios_name( int snum, const char *pszParmValue, char **ptr);
647 static bool handle_idmap_uid( int snum, const char *pszParmValue, char **ptr);
648 static bool handle_idmap_gid( int snum, const char *pszParmValue, char **ptr);
649 static bool handle_debug_list( int snum, const char *pszParmValue, char **ptr );
650 static bool handle_workgroup( int snum, const char *pszParmValue, char **ptr );
651 static bool handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
652 static bool handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
653 static bool handle_charset( int snum, const char *pszParmValue, char **ptr );
654 static bool handle_printing( int snum, const char *pszParmValue, char **ptr);
655 static bool handle_ldap_debug_level( int snum, const char *pszParmValue, char **ptr);
656
657 static void set_server_role(void);
658 static void set_default_server_announce_type(void);
659 static void set_allowed_client_auth(void);
660
661 static const struct enum_list enum_protocol[] = {
662         {PROTOCOL_NT1, "NT1"},
663         {PROTOCOL_LANMAN2, "LANMAN2"},
664         {PROTOCOL_LANMAN1, "LANMAN1"},
665         {PROTOCOL_CORE, "CORE"},
666         {PROTOCOL_COREPLUS, "COREPLUS"},
667         {PROTOCOL_COREPLUS, "CORE+"},
668         {-1, NULL}
669 };
670
671 static const struct enum_list enum_security[] = {
672         {SEC_SHARE, "SHARE"},
673         {SEC_USER, "USER"},
674         {SEC_SERVER, "SERVER"},
675         {SEC_DOMAIN, "DOMAIN"},
676 #ifdef HAVE_ADS
677         {SEC_ADS, "ADS"},
678 #endif
679         {-1, NULL}
680 };
681
682 static const struct enum_list enum_printing[] = {
683         {PRINT_SYSV, "sysv"},
684         {PRINT_AIX, "aix"},
685         {PRINT_HPUX, "hpux"},
686         {PRINT_BSD, "bsd"},
687         {PRINT_QNX, "qnx"},
688         {PRINT_PLP, "plp"},
689         {PRINT_LPRNG, "lprng"},
690         {PRINT_CUPS, "cups"},
691         {PRINT_IPRINT, "iprint"},
692         {PRINT_LPRNT, "nt"},
693         {PRINT_LPROS2, "os2"},
694 #ifdef DEVELOPER
695         {PRINT_TEST, "test"},
696         {PRINT_VLP, "vlp"},
697 #endif /* DEVELOPER */
698         {-1, NULL}
699 };
700
701 static const struct enum_list enum_ldap_sasl_wrapping[] = {
702         {0, "plain"},
703         {ADS_AUTH_SASL_SIGN, "sign"},
704         {ADS_AUTH_SASL_SEAL, "seal"},
705         {-1, NULL}
706 };
707
708 static const struct enum_list enum_ldap_ssl[] = {
709         {LDAP_SSL_OFF, "no"},
710         {LDAP_SSL_OFF, "No"},
711         {LDAP_SSL_OFF, "off"},
712         {LDAP_SSL_OFF, "Off"},
713         {LDAP_SSL_START_TLS, "start tls"},
714         {LDAP_SSL_START_TLS, "Start_tls"},
715         {-1, NULL}
716 };
717
718 static const struct enum_list enum_ldap_passwd_sync[] = {
719         {LDAP_PASSWD_SYNC_OFF, "no"},
720         {LDAP_PASSWD_SYNC_OFF, "No"},
721         {LDAP_PASSWD_SYNC_OFF, "off"},
722         {LDAP_PASSWD_SYNC_OFF, "Off"},
723         {LDAP_PASSWD_SYNC_ON, "Yes"},
724         {LDAP_PASSWD_SYNC_ON, "yes"},
725         {LDAP_PASSWD_SYNC_ON, "on"},
726         {LDAP_PASSWD_SYNC_ON, "On"},
727         {LDAP_PASSWD_SYNC_ONLY, "Only"},
728         {LDAP_PASSWD_SYNC_ONLY, "only"},
729         {-1, NULL}
730 };
731
732 /* Types of machine we can announce as. */
733 #define ANNOUNCE_AS_NT_SERVER 1
734 #define ANNOUNCE_AS_WIN95 2
735 #define ANNOUNCE_AS_WFW 3
736 #define ANNOUNCE_AS_NT_WORKSTATION 4
737
738 static const struct enum_list enum_announce_as[] = {
739         {ANNOUNCE_AS_NT_SERVER, "NT"},
740         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
741         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
742         {ANNOUNCE_AS_WIN95, "win95"},
743         {ANNOUNCE_AS_WFW, "WfW"},
744         {-1, NULL}
745 };
746
747 static const struct enum_list enum_map_readonly[] = {
748         {MAP_READONLY_NO, "no"},
749         {MAP_READONLY_NO, "false"},
750         {MAP_READONLY_NO, "0"},
751         {MAP_READONLY_YES, "yes"},
752         {MAP_READONLY_YES, "true"},
753         {MAP_READONLY_YES, "1"},
754         {MAP_READONLY_PERMISSIONS, "permissions"},
755         {MAP_READONLY_PERMISSIONS, "perms"},
756         {-1, NULL}
757 };
758
759 static const struct enum_list enum_case[] = {
760         {CASE_LOWER, "lower"},
761         {CASE_UPPER, "upper"},
762         {-1, NULL}
763 };
764
765 static const struct enum_list enum_bool_auto[] = {
766         {False, "No"},
767         {False, "False"},
768         {False, "0"},
769         {True, "Yes"},
770         {True, "True"},
771         {True, "1"},
772         {Auto, "Auto"},
773         {-1, NULL}
774 };
775
776 /* Client-side offline caching policy types */
777 #define CSC_POLICY_MANUAL 0
778 #define CSC_POLICY_DOCUMENTS 1
779 #define CSC_POLICY_PROGRAMS 2
780 #define CSC_POLICY_DISABLE 3
781
782 static const struct enum_list enum_csc_policy[] = {
783         {CSC_POLICY_MANUAL, "manual"},
784         {CSC_POLICY_DOCUMENTS, "documents"},
785         {CSC_POLICY_PROGRAMS, "programs"},
786         {CSC_POLICY_DISABLE, "disable"},
787         {-1, NULL}
788 };
789
790 /* SMB signing types. */
791 static const struct enum_list enum_smb_signing_vals[] = {
792         {False, "No"},
793         {False, "False"},
794         {False, "0"},
795         {False, "Off"},
796         {False, "disabled"},
797         {True, "Yes"},
798         {True, "True"},
799         {True, "1"},
800         {True, "On"},
801         {True, "enabled"},
802         {Auto, "auto"},
803         {Required, "required"},
804         {Required, "mandatory"},
805         {Required, "force"},
806         {Required, "forced"},
807         {Required, "enforced"},
808         {-1, NULL}
809 };
810
811 /* ACL compatibility options. */
812 static const struct enum_list enum_acl_compat_vals[] = {
813     { ACL_COMPAT_AUTO, "auto" },
814     { ACL_COMPAT_WINNT, "winnt" },
815     { ACL_COMPAT_WIN2K, "win2k" },
816     { -1, NULL}
817 };
818
819 /* 
820    Do you want session setups at user level security with a invalid
821    password to be rejected or allowed in as guest? WinNT rejects them
822    but it can be a pain as it means "net view" needs to use a password
823
824    You have 3 choices in the setting of map_to_guest:
825
826    "Never" means session setups with an invalid password
827    are rejected. This is the default.
828
829    "Bad User" means session setups with an invalid password
830    are rejected, unless the username does not exist, in which case it
831    is treated as a guest login
832
833    "Bad Password" means session setups with an invalid password
834    are treated as a guest login
835
836    Note that map_to_guest only has an effect in user or server
837    level security.
838 */
839
840 static const struct enum_list enum_map_to_guest[] = {
841         {NEVER_MAP_TO_GUEST, "Never"},
842         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
843         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
844         {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
845         {-1, NULL}
846 };
847
848 /* Config backend options */
849
850 static const struct enum_list enum_config_backend[] = {
851         {CONFIG_BACKEND_FILE, "file"},
852         {CONFIG_BACKEND_REGISTRY, "registry"},
853         {-1, NULL}
854 };
855
856 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
857  *
858  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
859  * screen in SWAT. This is used to exclude parameters as well as to squash all
860  * parameters that have been duplicated by pseudonyms.
861  *
862  * NOTE: To display a parameter in BASIC view set FLAG_BASIC
863  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
864  *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
865  *        respective views.
866  *
867  * NOTE2: Handling of duplicated (synonym) paramters:
868  *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
869  *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
870  *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
871  *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
872  */
873
874 static struct parm_struct parm_table[] = {
875         {N_("Base Options"), P_SEP, P_SEPARATOR}, 
876
877         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, 
878         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, 
879         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, 
880         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
881         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
882         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, 
883         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
884 #ifdef WITH_ADS
885         {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
886 #endif
887         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
888         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases,  NULL, FLAG_ADVANCED}, 
889         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope,  NULL, FLAG_ADVANCED}, 
890         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED }, 
891         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
892         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
893
894         {"config backend", P_ENUM, P_GLOBAL, &Globals.ConfigBackend, NULL, enum_config_backend, FLAG_ADVANCED},
895
896         {N_("Security Options"), P_SEP, P_SEPARATOR}, 
897
898         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
899         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_ADVANCED}, 
900         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
901         {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_ADVANCED}, 
902         {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
903         {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
904         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, 
905         {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
906         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
907         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
908         {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
909         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
910         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
911         {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
912         {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
913         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
914         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
915         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
916         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
917         {"enable privileges", P_BOOL, P_GLOBAL, &Globals.bEnablePrivileges, NULL, NULL, FLAG_ADVANCED}, 
918
919         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED}, 
920         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED}, 
921         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED}, 
922         {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED}, 
923         {"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED}, 
924         {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED}, 
925         {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
926         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED}, 
927         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED}, 
928         {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED}, 
929         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED}, 
930         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED}, 
931         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED}, 
932         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED}, 
933         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED}, 
934         {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED}, 
935
936         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
937         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
938         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
939
940         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
941         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
942         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
943         {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
944         {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
945         {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED }, 
946         {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
947         {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
948         {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, 
949
950         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE}, 
951         {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
952         {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
953         {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
954
955         {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
956         {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED },
957         {"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
958         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
959         {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, 
960         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
961         {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
962         {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
963         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
964         {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
965         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
966         {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
967         {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
968         {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
969         {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
970         {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
971         {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
972         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
973         {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, 
974
975         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
976         {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, 
977
978         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
979         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
980         {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE}, 
981         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
982         {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, 
983         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
984         {"use kerberos keytab", P_BOOL, P_GLOBAL, &Globals.bUseKerberosKeytab, NULL, NULL, FLAG_ADVANCED}, 
985
986         {N_("Logging Options"), P_SEP, P_SEPARATOR}, 
987
988         {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED}, 
989         {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE}, 
990         {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED}, 
991         {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED}, 
992         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED}, 
993
994         {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, 
995         {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
996         {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
997         {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED}, 
998         {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, 
999         {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, 
1000         {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, 
1001         {"debug class", P_BOOL, P_GLOBAL, &Globals.bDebugClass, NULL, NULL, FLAG_ADVANCED},
1002         {"enable core files", P_BOOL, P_GLOBAL, &Globals.bEnableCoreFiles, NULL, NULL, FLAG_ADVANCED},
1003
1004         {N_("Protocol Options"), P_SEP, P_SEPARATOR}, 
1005
1006         {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED}, 
1007         {"aio read size", P_INTEGER, P_LOCAL, &sDefault.iAioReadSize, NULL, NULL, FLAG_ADVANCED}, 
1008         {"aio write size", P_INTEGER, P_LOCAL, &sDefault.iAioWriteSize, NULL, NULL, FLAG_ADVANCED}, 
1009         {"aio write behind", P_STRING, P_LOCAL, &sDefault.szAioWriteBehind, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1010         {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, 
1011         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, 
1012         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1013         {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1014         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1015         {"min receivefile size", P_INTEGER, P_GLOBAL, &Globals.iminreceivefile, NULL, NULL, FLAG_ADVANCED}, 
1016         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, 
1017         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, 
1018         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, 
1019         {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED}, 
1020
1021         {"acl compatibility", P_ENUM, P_GLOBAL, &Globals.iAclCompat, NULL,  enum_acl_compat_vals, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1022         {"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
1023         {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1024         {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1025         {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, 
1026         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED}, 
1027         {"profile acls", P_BOOL, P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
1028
1029         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_ADVANCED}, 
1030         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as,  FLAG_ADVANCED}, 
1031         {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1032         {"afs share", P_BOOL, P_LOCAL, &sDefault.bAfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
1033         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, 
1034         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, 
1035
1036         {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
1037         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED}, 
1038         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
1039         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED}, 
1040         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED}, 
1041         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED}, 
1042         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1043         {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1044         {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, 
1045         {"smb encrypt", P_ENUM, P_LOCAL, &sDefault.ismb_encrypt, NULL, enum_smb_signing_vals, FLAG_ADVANCED},
1046         {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
1047         {"client ldap sasl wrapping", P_ENUM, P_GLOBAL, &Globals.client_ldap_sasl_wrapping, NULL, enum_ldap_sasl_wrapping, FLAG_ADVANCED},
1048         {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, 
1049         {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
1050
1051         {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
1052
1053         {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1054         {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED}, 
1055         {"getwd cache", P_BOOL, P_GLOBAL, &Globals.getwd_cache, NULL, NULL, FLAG_ADVANCED},
1056         {"keepalive", P_INTEGER, P_GLOBAL, &Globals.iKeepalive, NULL, NULL, FLAG_ADVANCED},
1057         {"change notify", P_BOOL, P_LOCAL, &sDefault.bChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1058         {"directory name cache size", P_INTEGER, P_LOCAL, &sDefault.iDirectoryNameCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1059         {"kernel change notify", P_BOOL, P_LOCAL, &sDefault.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
1060
1061         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, 
1062         {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, 
1063         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1064         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_ADVANCED}, 
1065         {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_ADVANCED}, 
1066         {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED}, 
1067         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1068
1069         {"socket options", P_STRING, P_GLOBAL, &Globals.szSocketOptions, NULL, NULL, FLAG_ADVANCED},
1070         {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1071         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1072         {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1073         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_ADVANCED}, 
1074         {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1075         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED}, 
1076         {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
1077
1078         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED}, 
1079         {"ctdbd socket", P_STRING, P_GLOBAL, &Globals.ctdbdSocket, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1080         {"cluster addresses", P_LIST, P_GLOBAL, &Globals.szClusterAddresses, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1081         {"clustering", P_BOOL, P_GLOBAL, &Globals.clustering, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1082
1083         {N_("Printing Options"), P_SEP, P_SEPARATOR}, 
1084
1085         {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1086         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1087         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1088         {"printcap cache time", P_INTEGER, P_GLOBAL, &Globals.PrintcapCacheTime, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1089         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1090         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE}, 
1091         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1092         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE}, 
1093         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, handle_printing, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1094         {"cups options", P_STRING, P_LOCAL, &sDefault.szCupsOptions, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1095         {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1096         {"iprint server", P_STRING, P_GLOBAL, &Globals.szIPrintServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1097         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1098         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1099         {"enable spoolss", P_BOOLREV, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_HIDE}, 
1100         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1101         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1102         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1103         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1104         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1105         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, 
1106
1107         {"addport command", P_STRING, P_GLOBAL, &Globals.szAddPortCommand, NULL, NULL, FLAG_ADVANCED}, 
1108         {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED}, 
1109         {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1110         {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED}, 
1111         {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED}, 
1112         {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED}, 
1113
1114         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1115         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE}, 
1116         {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1117         {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1118         {"force printername", P_BOOL, P_LOCAL, &sDefault.bForcePrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, 
1119         {"printjob username", P_STRING, P_LOCAL, &sDefault.szPrintjobUsername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT},
1120
1121         {N_("Filename Handling"), P_SEP, P_SEPARATOR}, 
1122         {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, 
1123         {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, 
1124
1125         {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, 
1126         {"case sensitive", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1127         {"casesignames", P_ENUM, P_LOCAL, &sDefault.iCaseSensitive, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_HIDE}, 
1128         {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1129         {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1130         {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1131         {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1132         {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1133         {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1134         {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1135         {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1136         {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1137         {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1138         {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
1139         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1140         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1141         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1142         {"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1143         {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1144         {"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, 
1145         {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, 
1146         {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1147         {"dmapi support", P_BOOL, P_LOCAL, &sDefault.bDmapiSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
1148
1149
1150         {N_("Domain Options"), P_SEP, P_SEPARATOR}, 
1151
1152         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
1153
1154         {N_("Logon Options"), P_SEP, P_SEPARATOR}, 
1155
1156         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED}, 
1157         {"rename user script", P_STRING, P_GLOBAL, &Globals.szRenameUserScript, NULL, NULL, FLAG_ADVANCED},
1158         {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED}, 
1159         {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1160         {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1161         {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1162         {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1163         {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED}, 
1164         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED}, 
1165         {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1166         {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED}, 
1167         {"username map script", P_STRING, P_GLOBAL, &Globals.szUsernameMapScript, NULL, NULL, FLAG_ADVANCED}, 
1168
1169         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED}, 
1170         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED}, 
1171         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED}, 
1172         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED}, 
1173         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED}, 
1174
1175         {N_("Browse Options"), P_SEP, P_SEPARATOR}, 
1176
1177         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1178         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED}, 
1179         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED}, 
1180         {"preferred master", P_ENUM, P_GLOBAL, &Globals.iPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1181         {"prefered master", P_ENUM, P_GLOBAL, &Globals.iPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE}, 
1182         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
1183         {"domain master", P_ENUM, P_GLOBAL, &Globals.iDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
1184         {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED}, 
1185         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1186         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE}, 
1187         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_ADVANCED}, 
1188
1189         {N_("WINS Options"), P_SEP, P_SEPARATOR}, 
1190
1191         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED}, 
1192         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED}, 
1193
1194         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1195         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
1196         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, 
1197
1198         {N_("Locking Options"), P_SEP, P_SEPARATOR}, 
1199
1200         {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1201         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1202         {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1203         {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1204         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1205         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1206
1207         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1208         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1209         {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
1210         {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1211         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1212         {"strict locking", P_ENUM, P_LOCAL, &sDefault.iStrictLocking, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1213         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1214
1215         {N_("Ldap Options"), P_SEP, P_SEPARATOR}, 
1216
1217         {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, 
1218         {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, 
1219         {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, NULL, NULL, FLAG_ADVANCED}, 
1220         {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1221         {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, NULL, NULL, FLAG_ADVANCED}, 
1222         {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, 
1223         {"ldap password sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_HIDE}, 
1224         {"ldap replication sleep", P_INTEGER, P_GLOBAL, &Globals.ldap_replication_sleep, NULL, NULL, FLAG_ADVANCED},
1225         {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, NULL, NULL, FLAG_ADVANCED}, 
1226         {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, 
1227         {"ldap timeout", P_INTEGER, P_GLOBAL, &Globals.ldap_timeout, NULL, NULL, FLAG_ADVANCED},
1228         {"ldap page size", P_INTEGER, P_GLOBAL, &Globals.ldap_page_size, NULL, NULL, FLAG_ADVANCED},
1229         {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, NULL, NULL, FLAG_ADVANCED}, 
1230
1231         {"ldap debug level", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_level, handle_ldap_debug_level, NULL, FLAG_ADVANCED},
1232         {"ldap debug threshold", P_INTEGER, P_GLOBAL, &Globals.ldap_debug_threshold, NULL, NULL, FLAG_ADVANCED},
1233
1234
1235         {N_("EventLog Options"), P_SEP, P_SEPARATOR}, 
1236         {"eventlog list",  P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
1237
1238         {N_("Miscellaneous Options"), P_SEP, P_SEPARATOR}, 
1239         {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1240         {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1241         {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, 
1242
1243         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, 
1244         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1245         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, 
1246         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED}, 
1247         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
1248         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED}, 
1249 #ifdef WITH_UTMP
1250         {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1251         {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED}, 
1252         {"utmp", P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED}, 
1253 #endif
1254
1255         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1256         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, 
1257         {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED}, 
1258         {"dfree cache time", P_INTEGER, P_LOCAL, &sDefault.iDfreeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1259         {"dfree command", P_STRING, P_LOCAL, &sDefault.szDfree, NULL, NULL, FLAG_ADVANCED}, 
1260         {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED}, 
1261         {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED}, 
1262         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED}, 
1263         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED}, 
1264         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_ADVANCED}, 
1265         {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED}, 
1266         {"afs username map", P_STRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
1267         {"afs token lifetime", P_INTEGER, P_GLOBAL, &Globals.iAfsTokenLifetime, NULL, NULL, FLAG_ADVANCED},
1268         {"log nt token command", P_STRING, P_GLOBAL, &Globals.szLogNtTokenCommand, NULL, NULL, FLAG_ADVANCED},
1269         {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED}, 
1270         {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED}, 
1271         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE}, 
1272
1273         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE}, 
1274         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE}, 
1275         {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1276         {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED}, 
1277
1278         {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1279         {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1280         {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1281         {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1282         {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1283         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
1284         {"registry shares", P_BOOL, P_GLOBAL, &Globals.bRegistryShares, NULL, NULL, FLAG_ADVANCED},
1285         {"usershare allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
1286         {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
1287         {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
1288         {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
1289         {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
1290         {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
1291         {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
1292         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
1293         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1294         {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1295         {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1296         {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1297         {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1298         {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1299         {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1300         {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1301         {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1302         {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1303         {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1304
1305         {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1306         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED}, 
1307
1308         {N_("VFS module options"), P_SEP, P_SEPARATOR}, 
1309
1310         {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1311         {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE}, 
1312
1313
1314         {N_("MSDFS options"), P_SEP, P_SEPARATOR},
1315
1316         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1317         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1318         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED}, 
1319
1320         {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
1321
1322         {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
1323         {"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED}, 
1324         {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED }, 
1325         {"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED}, 
1326         {"idmap cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1327         {"idmap negative cache time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeCacheTime, NULL, NULL, FLAG_ADVANCED}, 
1328         {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED }, 
1329         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE }, 
1330         {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED }, 
1331         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE }, 
1332         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
1333         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
1334         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
1335         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, 
1336         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, 
1337         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, 
1338         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, 
1339         {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, 
1340         {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
1341         {"winbind expand groups", P_INTEGER, P_GLOBAL, &Globals.winbind_expand_groups, NULL, NULL, FLAG_ADVANCED}, 
1342         {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
1343         {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
1344         {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
1345         {"winbind normalize names", P_BOOL, P_GLOBAL, &Globals.bWinbindNormalizeNames, NULL, NULL, FLAG_ADVANCED},
1346         {"winbind rpc only", P_BOOL, P_GLOBAL, &Globals.bWinbindRpcOnly, NULL, NULL, FLAG_ADVANCED},
1347
1348         {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
1349 };
1350
1351 /***************************************************************************
1352  Initialise the sDefault parameter structure for the printer values.
1353 ***************************************************************************/
1354
1355 static void init_printer_values(service *pService)
1356 {
1357         /* choose defaults depending on the type of printing */
1358         switch (pService->iPrinting) {
1359                 case PRINT_BSD:
1360                 case PRINT_AIX:
1361                 case PRINT_LPRNT:
1362                 case PRINT_LPROS2:
1363                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1364                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1365                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1366                         break;
1367
1368                 case PRINT_LPRNG:
1369                 case PRINT_PLP:
1370                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1371                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1372                         string_set(&pService->szPrintcommand, "lpr -r -P'%p' %s");
1373                         string_set(&pService->szQueuepausecommand, "lpc stop '%p'");
1374                         string_set(&pService->szQueueresumecommand, "lpc start '%p'");
1375                         string_set(&pService->szLppausecommand, "lpc hold '%p' %j");
1376                         string_set(&pService->szLpresumecommand, "lpc release '%p' %j");
1377                         break;
1378
1379                 case PRINT_CUPS:
1380                 case PRINT_IPRINT:
1381 #ifdef HAVE_CUPS
1382                         /* set the lpq command to contain the destination printer
1383                            name only.  This is used by cups_queue_get() */
1384                         string_set(&pService->szLpqcommand, "%p");
1385                         string_set(&pService->szLprmcommand, "");
1386                         string_set(&pService->szPrintcommand, "");
1387                         string_set(&pService->szLppausecommand, "");
1388                         string_set(&pService->szLpresumecommand, "");
1389                         string_set(&pService->szQueuepausecommand, "");
1390                         string_set(&pService->szQueueresumecommand, "");
1391 #else
1392                         string_set(&pService->szLpqcommand, "lpq -P'%p'");
1393                         string_set(&pService->szLprmcommand, "lprm -P'%p' %j");
1394                         string_set(&pService->szPrintcommand, "lpr -P'%p' %s; rm %s");
1395                         string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
1396                         string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
1397                         string_set(&pService->szQueuepausecommand, "disable '%p'");
1398                         string_set(&pService->szQueueresumecommand, "enable '%p'");
1399 #endif /* HAVE_CUPS */
1400                         break;
1401
1402                 case PRINT_SYSV:
1403                 case PRINT_HPUX:
1404                         string_set(&pService->szLpqcommand, "lpstat -o%p");
1405                         string_set(&pService->szLprmcommand, "cancel %p-%j");
1406                         string_set(&pService->szPrintcommand, "lp -c -d%p %s; rm %s");
1407                         string_set(&pService->szQueuepausecommand, "disable %p");
1408                         string_set(&pService->szQueueresumecommand, "enable %p");
1409 #ifndef HPUX
1410                         string_set(&pService->szLppausecommand, "lp -i %p-%j -H hold");
1411                         string_set(&pService->szLpresumecommand, "lp -i %p-%j -H resume");
1412 #endif /* HPUX */
1413                         break;
1414
1415                 case PRINT_QNX:
1416                         string_set(&pService->szLpqcommand, "lpq -P%p");
1417                         string_set(&pService->szLprmcommand, "lprm -P%p %j");
1418                         string_set(&pService->szPrintcommand, "lp -r -P%p %s");
1419                         break;
1420
1421 #ifdef DEVELOPER
1422         case PRINT_TEST:
1423         case PRINT_VLP:
1424                 string_set(&pService->szPrintcommand, "vlp print %p %s");
1425                 string_set(&pService->szLpqcommand, "vlp lpq %p");
1426                 string_set(&pService->szLprmcommand, "vlp lprm %p %j");
1427                 string_set(&pService->szLppausecommand, "vlp lppause %p %j");
1428                 string_set(&pService->szLpresumecommand, "vlp lpresum %p %j");
1429                 string_set(&pService->szQueuepausecommand, "vlp queuepause %p");
1430                 string_set(&pService->szQueueresumecommand, "vlp queueresume %p");
1431                 break;
1432 #endif /* DEVELOPER */
1433
1434         }
1435 }
1436
1437 /***************************************************************************
1438  Initialise the global parameter structure.
1439 ***************************************************************************/
1440
1441 static void init_globals(bool first_time_only)
1442 {
1443         static bool done_init = False;
1444         char *s = NULL;
1445
1446         /* If requested to initialize only once and we've already done it... */
1447         if (first_time_only && done_init) {
1448                 /* ... then we have nothing more to do */
1449                 return;
1450         }
1451
1452         if (!done_init) {
1453                 int i;
1454
1455                 /* The logfile can be set before this is invoked. Free it if so. */
1456                 if (Globals.szLogFile != NULL) {
1457                         string_free(&Globals.szLogFile);
1458                         Globals.szLogFile = NULL;
1459                 }
1460
1461                 memset((void *)&Globals, '\0', sizeof(Globals));
1462
1463                 for (i = 0; parm_table[i].label; i++)
1464                         if ((parm_table[i].type == P_STRING ||
1465                              parm_table[i].type == P_USTRING) &&
1466                             parm_table[i].ptr)
1467                                 string_set((char **)parm_table[i].ptr, "");
1468
1469                 string_set(&sDefault.fstype, FSTYPE_STRING);
1470                 string_set(&sDefault.szPrintjobUsername, "%U");
1471
1472                 init_printer_values(&sDefault);
1473
1474                 done_init = True;
1475         }
1476
1477
1478         DEBUG(3, ("Initialising global parameters\n"));
1479
1480         string_set(&Globals.szSMBPasswdFile, get_dyn_SMB_PASSWD_FILE());
1481         string_set(&Globals.szPrivateDir, get_dyn_PRIVATE_DIR());
1482
1483         /* use the new 'hash2' method by default, with a prefix of 1 */
1484         string_set(&Globals.szManglingMethod, "hash2");
1485         Globals.mangle_prefix = 1;
1486
1487         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
1488
1489         /* using UTF8 by default allows us to support all chars */
1490         string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET);
1491
1492 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
1493         /* If the system supports nl_langinfo(), try to grab the value
1494            from the user's locale */
1495         string_set(&Globals.display_charset, "LOCALE");
1496 #else
1497         string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET);
1498 #endif
1499
1500         /* Use codepage 850 as a default for the dos character set */
1501         string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET);
1502
1503         /*
1504          * Allow the default PASSWD_CHAT to be overridden in local.h.
1505          */
1506         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
1507
1508         set_global_myname(myhostname());
1509         string_set(&Globals.szNetbiosName,global_myname());
1510
1511         set_global_myworkgroup(WORKGROUP);
1512         string_set(&Globals.szWorkgroup, lp_workgroup());
1513
1514         string_set(&Globals.szPasswdProgram, "");
1515         string_set(&Globals.szPidDir, get_dyn_PIDDIR());
1516         string_set(&Globals.szLockDir, get_dyn_LOCKDIR());
1517         string_set(&Globals.szSocketAddress, "0.0.0.0");
1518
1519         if (asprintf(&s, "Samba %s", SAMBA_VERSION_STRING) < 0) {
1520                 smb_panic("init_globals: ENOMEM");
1521         }
1522         string_set(&Globals.szServerString, s);
1523         SAFE_FREE(s);
1524         if (asprintf(&s, "%d.%d", DEFAULT_MAJOR_VERSION,
1525                         DEFAULT_MINOR_VERSION) < 0) {
1526                 smb_panic("init_globals: ENOMEM");
1527         }
1528         string_set(&Globals.szAnnounceVersion, s);
1529         SAFE_FREE(s);
1530 #ifdef DEVELOPER
1531         string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
1532 #endif
1533
1534         string_set(&Globals.szSocketOptions, DEFAULT_SOCKET_OPTIONS);
1535
1536         string_set(&Globals.szLogonDrive, "");
1537         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
1538         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
1539         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
1540
1541         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
1542         string_set(&Globals.szPasswordServer, "*");
1543
1544         Globals.AlgorithmicRidBase = BASE_RID;
1545
1546         Globals.bLoadPrinters = True;
1547         Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
1548
1549         Globals.ConfigBackend = config_backend;
1550
1551         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
1552         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
1553         Globals.max_xmit = 0x4104;
1554         Globals.max_mux = 50;   /* This is *needed* for profile support. */
1555         Globals.lpqcachetime = 30;      /* changed to handle large print servers better -- jerry */
1556         Globals.bDisableSpoolss = False;
1557         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
1558         Globals.pwordlevel = 0;
1559         Globals.unamelevel = 0;
1560         Globals.deadtime = 0;
1561         Globals.getwd_cache = true;
1562         Globals.bLargeReadwrite = True;
1563         Globals.max_log_size = 5000;
1564         Globals.max_open_files = MAX_OPEN_FILES;
1565         Globals.open_files_db_hash_size = SMB_OPEN_DATABASE_TDB_HASH_SIZE;
1566         Globals.maxprotocol = PROTOCOL_NT1;
1567         Globals.minprotocol = PROTOCOL_CORE;
1568         Globals.security = SEC_USER;
1569         Globals.paranoid_server_security = True;
1570         Globals.bEncryptPasswords = True;
1571         Globals.bUpdateEncrypt = False;
1572         Globals.clientSchannel = Auto;
1573         Globals.serverSchannel = Auto;
1574         Globals.bReadRaw = True;
1575         Globals.bWriteRaw = True;
1576         Globals.bNullPasswords = False;
1577         Globals.bObeyPamRestrictions = False;
1578         Globals.syslog = 1;
1579         Globals.bSyslogOnly = False;
1580         Globals.bTimestampLogs = True;
1581         string_set(&Globals.szLogLevel, "0");
1582         Globals.bDebugPrefixTimestamp = False;
1583         Globals.bDebugHiresTimestamp = False;
1584         Globals.bDebugPid = False;
1585         Globals.bDebugUid = False;
1586         Globals.bDebugClass = False;
1587         Globals.bEnableCoreFiles = True;
1588         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1589         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1590         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1591         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1592         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1593         Globals.lm_interval = 60;
1594         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1595 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1596         Globals.bNISHomeMap = False;
1597 #ifdef WITH_NISPLUS_HOME
1598         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
1599 #else
1600         string_set(&Globals.szNISHomeMapName, "auto.home");
1601 #endif
1602 #endif
1603         Globals.bTimeServer = False;
1604         Globals.bBindInterfacesOnly = False;
1605         Globals.bUnixPasswdSync = False;
1606         Globals.bPamPasswordChange = False;
1607         Globals.bPasswdChatDebug = False;
1608         Globals.iPasswdChatTimeout = 2; /* 2 second default. */
1609         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
1610         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1611         Globals.bStatCache = True;      /* use stat cache by default */
1612         Globals.iMaxStatCacheSize = 256; /* 256k by default */
1613         Globals.restrict_anonymous = 0;
1614         Globals.bClientLanManAuth = False;      /* Do NOT use the LanMan hash if it is available */
1615         Globals.bClientPlaintextAuth = False;   /* Do NOT use a plaintext password even if is requested by the server */
1616         Globals.bLanmanAuth = False;    /* Do NOT use the LanMan hash, even if it is supplied */
1617         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
1618         Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */
1619         /* Note, that we will use NTLM2 session security (which is different), if it is available */
1620
1621         Globals.map_to_guest = 0;       /* By Default, "Never" */
1622         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
1623         Globals.enhanced_browsing = true;
1624         Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
1625 #ifdef MMAP_BLACKLIST
1626         Globals.bUseMmap = False;
1627 #else
1628         Globals.bUseMmap = True;
1629 #endif
1630         Globals.bUnixExtensions = True;
1631         Globals.bResetOnZeroVC = False;
1632
1633         /* hostname lookups can be very expensive and are broken on
1634            a large number of sites (tridge) */
1635         Globals.bHostnameLookups = False;
1636
1637         string_set(&Globals.szPassdbBackend, "smbpasswd");
1638         string_set(&Globals.szLdapSuffix, "");
1639         string_set(&Globals.szLdapMachineSuffix, "");
1640         string_set(&Globals.szLdapUserSuffix, "");
1641         string_set(&Globals.szLdapGroupSuffix, "");
1642         string_set(&Globals.szLdapIdmapSuffix, "");
1643
1644         string_set(&Globals.szLdapAdminDn, "");
1645         Globals.ldap_ssl = LDAP_SSL_ON;
1646         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1647         Globals.ldap_delete_dn = False;
1648         Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
1649         Globals.ldap_timeout = LDAP_CONNECT_DEFAULT_TIMEOUT;
1650         Globals.ldap_page_size = LDAP_PAGE_SIZE;
1651
1652         Globals.ldap_debug_level = 0;
1653         Globals.ldap_debug_threshold = 10;
1654
1655         /* This is what we tell the afs client. in reality we set the token 
1656          * to never expire, though, when this runs out the afs client will 
1657          * forget the token. Set to 0 to get NEVERDATE.*/
1658         Globals.iAfsTokenLifetime = 604800;
1659
1660 /* these parameters are set to defaults that are more appropriate
1661    for the increasing samba install base:
1662
1663    as a member of the workgroup, that will possibly become a
1664    _local_ master browser (lm = True).  this is opposed to a forced
1665    local master browser startup (pm = True).
1666
1667    doesn't provide WINS server service by default (wsupp = False),
1668    and doesn't provide domain master browser services by default, either.
1669
1670 */
1671
1672         Globals.bMsAddPrinterWizard = True;
1673         Globals.os_level = 20;
1674         Globals.bLocalMaster = True;
1675         Globals.iDomainMaster = Auto;   /* depending on bDomainLogons */
1676         Globals.bDomainLogons = False;
1677         Globals.bBrowseList = True;
1678         Globals.bWINSsupport = False;
1679         Globals.bWINSproxy = False;
1680
1681         Globals.bDNSproxy = True;
1682
1683         /* this just means to use them if they exist */
1684         Globals.bKernelOplocks = True;
1685
1686         Globals.bAllowTrustedDomains = True;
1687
1688         string_set(&Globals.szTemplateShell, "/bin/false");
1689         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1690         string_set(&Globals.szWinbindSeparator, "\\");
1691
1692         string_set(&Globals.szCupsServer, "");
1693         string_set(&Globals.szIPrintServer, "");
1694
1695         string_set(&Globals.ctdbdSocket, "");
1696         Globals.szClusterAddresses = NULL;
1697         Globals.clustering = False;
1698
1699         Globals.winbind_cache_time = 300;       /* 5 minutes */
1700         Globals.bWinbindEnumUsers = False;
1701         Globals.bWinbindEnumGroups = False;
1702         Globals.bWinbindUseDefaultDomain = False;
1703         Globals.bWinbindTrustedDomainsOnly = False;
1704         Globals.bWinbindNestedGroups = True;
1705         Globals.winbind_expand_groups = 1;
1706         Globals.szWinbindNssInfo = str_list_make(NULL, "template", NULL);
1707         Globals.bWinbindRefreshTickets = False;
1708         Globals.bWinbindOfflineLogon = False;
1709
1710         Globals.iIdmapCacheTime = 900; /* 15 minutes by default */
1711         Globals.iIdmapNegativeCacheTime = 120; /* 2 minutes by default */
1712
1713         Globals.bPassdbExpandExplicit = False;
1714
1715         Globals.name_cache_timeout = 660; /* In seconds */
1716
1717         Globals.bUseSpnego = True;
1718         Globals.bClientUseSpnego = True;
1719
1720         Globals.client_signing = Auto;
1721         Globals.server_signing = False;
1722
1723         Globals.bDeferSharingViolations = True;
1724         string_set(&Globals.smb_ports, SMB_PORTS);
1725
1726         Globals.bEnablePrivileges = True;
1727         Globals.bHostMSDfs        = True;
1728         Globals.bASUSupport       = False;
1729
1730         /* User defined shares. */
1731         if (asprintf(&s, "%s/usershares", get_dyn_STATEDIR()) < 0) {
1732                 smb_panic("init_globals: ENOMEM");
1733         }
1734         string_set(&Globals.szUsersharePath, s);
1735         SAFE_FREE(s);
1736         string_set(&Globals.szUsershareTemplateShare, "");
1737         Globals.iUsershareMaxShares = 0;
1738         /* By default disallow sharing of directories not owned by the sharer. */
1739         Globals.bUsershareOwnerOnly = True;
1740         /* By default disallow guest access to usershares. */
1741         Globals.bUsershareAllowGuests = False;
1742
1743         Globals.iKeepalive = DEFAULT_KEEPALIVE;
1744
1745         /* By default no shares out of the registry */
1746         Globals.bRegistryShares = False;
1747
1748         Globals.iminreceivefile = 0;
1749 }
1750
1751 /*******************************************************************
1752  Convenience routine to grab string parameters into temporary memory
1753  and run standard_sub_basic on them. The buffers can be written to by
1754  callers without affecting the source string.
1755 ********************************************************************/
1756
1757 static char *lp_string(const char *s)
1758 {
1759         char *ret;
1760         TALLOC_CTX *ctx = talloc_tos();
1761
1762         /* The follow debug is useful for tracking down memory problems
1763            especially if you have an inner loop that is calling a lp_*()
1764            function that returns a string.  Perhaps this debug should be
1765            present all the time? */
1766
1767 #if 0
1768         DEBUG(10, ("lp_string(%s)\n", s));
1769 #endif
1770
1771         ret = talloc_sub_basic(ctx,
1772                         get_current_username(),
1773                         current_user_info.domain,
1774                         s);
1775         if (trim_char(ret, '\"', '\"')) {
1776                 if (strchr(ret,'\"') != NULL) {
1777                         TALLOC_FREE(ret);
1778                         ret = talloc_sub_basic(ctx,
1779                                         get_current_username(),
1780                                         current_user_info.domain,
1781                                         s);
1782                 }
1783         }
1784         return ret;
1785 }
1786
1787 /*
1788    In this section all the functions that are used to access the 
1789    parameters from the rest of the program are defined 
1790 */
1791
1792 #define FN_GLOBAL_STRING(fn_name,ptr) \
1793  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1794 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1795  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1796 #define FN_GLOBAL_LIST(fn_name,ptr) \
1797  const char **fn_name(void) {return(*(const char ***)(ptr));}
1798 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1799  bool fn_name(void) {return(*(bool *)(ptr));}
1800 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1801  char fn_name(void) {return(*(char *)(ptr));}
1802 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1803  int fn_name(void) {return(*(int *)(ptr));}
1804
1805 #define FN_LOCAL_STRING(fn_name,val) \
1806  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1807 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1808  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1809 #define FN_LOCAL_LIST(fn_name,val) \
1810  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1811 #define FN_LOCAL_BOOL(fn_name,val) \
1812  bool fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1813 #define FN_LOCAL_INTEGER(fn_name,val) \
1814  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1815
1816 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1817  bool fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1818 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1819  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1820 #define FN_LOCAL_PARM_STRING(fn_name,val) \
1821  char *fn_name(const struct share_params *p) {return(lp_string((LP_SNUM_OK(p->service) && ServicePtrs[(p->service)]->val) ? ServicePtrs[(p->service)]->val : sDefault.val));}
1822 #define FN_LOCAL_CHAR(fn_name,val) \
1823  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1824
1825 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1826 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1827 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1828 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1829 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1830 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1831 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1832 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1833 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1834 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
1835 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
1836 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1837 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1838 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1839 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1840 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1841 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1842 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1843 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1844 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1845 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1846 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1847 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1848 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1849 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1850 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
1851 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
1852 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1853 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1854 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1855 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1856 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1857 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1858 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
1859 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
1860 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
1861 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1862 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1863 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1864 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1865 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1866 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1867 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1868 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1869 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1870 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1871 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1872 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1873 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1874 /* FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
1875  * lp_passdb_backend() should be replace by the this macro again after
1876  * some releases.
1877  * */
1878 const char *lp_passdb_backend(void)
1879 {
1880         char *delim, *quote;
1881
1882         delim = strchr( Globals.szPassdbBackend, ' ');
1883         /* no space at all */
1884         if (delim == NULL) {
1885                 goto out;
1886         }
1887
1888         quote = strchr(Globals.szPassdbBackend, '"');
1889         /* no quote char or non in the first part */
1890         if (quote == NULL || quote > delim) {
1891                 *delim = '\0';
1892                 goto warn;
1893         }
1894
1895         quote = strchr(quote+1, '"');
1896         if (quote == NULL) {
1897                 DEBUG(0, ("WARNING: Your 'passdb backend' configuration is invalid due to a missing second \" char.\n"));
1898                 goto out;
1899         } else if (*(quote+1) == '\0') {
1900                 /* space, fitting quote char, and one backend only */
1901                 goto out;
1902         } else {
1903                 /* terminate string after the fitting quote char */
1904                 *(quote+1) = '\0';
1905         }
1906
1907 warn:
1908         DEBUG(0, ("WARNING: Your 'passdb backend' configuration includes multiple backends.  This\n"
1909                 "is deprecated since Samba 3.0.23.  Please check WHATSNEW.txt or the section 'Passdb\n"
1910                 "Changes' from the ChangeNotes as part of the Samba HOWTO collection.  Only the first\n"
1911                 "backend (%s) is used.  The rest is ignored.\n", Globals.szPassdbBackend));
1912
1913 out:
1914         return Globals.szPassdbBackend;
1915 }
1916 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1917 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1918 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1919 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
1920 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1921
1922 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1923 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1924 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1925 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1926 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1927 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1928
1929 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1930
1931 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1932 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1933 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
1934
1935 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
1936
1937 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1938 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1939 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
1940 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1941 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
1942 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1943 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1944 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1945 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
1946 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
1947 FN_GLOBAL_INTEGER(lp_winbind_expand_groups, &Globals.winbind_expand_groups)
1948 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
1949 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
1950 FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
1951 FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
1952
1953 FN_GLOBAL_LIST(lp_idmap_domains, &Globals.szIdmapDomains)
1954 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) /* deprecated */
1955 FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend)
1956 FN_GLOBAL_INTEGER(lp_idmap_cache_time, &Globals.iIdmapCacheTime)
1957 FN_GLOBAL_INTEGER(lp_idmap_negative_cache_time, &Globals.iIdmapNegativeCacheTime)
1958 FN_GLOBAL_INTEGER(lp_keepalive, &Globals.iKeepalive)
1959 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
1960
1961 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1962 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1963 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1964 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1965 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1966 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
1967 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
1968 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
1969 FN_GLOBAL_INTEGER(lp_ldap_debug_level, &Globals.ldap_debug_level)
1970 FN_GLOBAL_INTEGER(lp_ldap_debug_threshold, &Globals.ldap_debug_threshold)
1971 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1972 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1973 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1974 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
1975 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
1976 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
1977
1978 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
1979
1980 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
1981 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
1982 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
1983 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1984 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
1985 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1986 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1987 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1988 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1989 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1990 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1991 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1992 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1993 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1994 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1995 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1996 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1997 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1998 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1999 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
2000 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
2001 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
2002 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
2003 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
2004 FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
2005 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
2006 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
2007 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
2008 FN_GLOBAL_BOOL(lp_debug_class, &Globals.bDebugClass)
2009 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
2010 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
2011 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
2012 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
2013 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
2014 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
2015 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
2016 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
2017 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
2018 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
2019 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
2020 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
2021 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
2022 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
2023 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
2024 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
2025 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
2026 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
2027 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
2028 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
2029 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
2030 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
2031 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
2032 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
2033 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
2034 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
2035 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
2036 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
2037 FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify)
2038 FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify)
2039 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
2040 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
2041 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
2042 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
2043 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
2044 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
2045 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
2046 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
2047 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
2048 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
2049 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
2050 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
2051 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
2052 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
2053 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
2054 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
2055 FN_GLOBAL_BOOL(lp_getwd_cache, &Globals.getwd_cache)
2056 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
2057 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
2058 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
2059 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
2060 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
2061 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
2062 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
2063 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
2064 FN_GLOBAL_BOOL(_lp_disable_spoolss, &Globals.bDisableSpoolss)
2065 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
2066 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
2067 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
2068 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
2069 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
2070 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
2071 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
2072 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
2073 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
2074 FN_GLOBAL_CONST_STRING(lp_socket_options, &Globals.szSocketOptions)
2075 FN_GLOBAL_INTEGER(lp_config_backend, &Globals.ConfigBackend);
2076
2077 FN_LOCAL_STRING(lp_preexec, szPreExec)
2078 FN_LOCAL_STRING(lp_postexec, szPostExec)
2079 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
2080 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
2081 FN_LOCAL_STRING(lp_servicename, szService)
2082 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
2083 FN_LOCAL_STRING(lp_pathname, szPath)
2084 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
2085 FN_LOCAL_STRING(lp_username, szUsername)
2086 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
2087 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
2088 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
2089 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
2090 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
2091 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
2092 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
2093 FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket)
2094 FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses)
2095 FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering);
2096 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
2097 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
2098 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
2099 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
2100 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
2101 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
2102 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
2103 static FN_LOCAL_STRING(_lp_printername, szPrintername)
2104 FN_LOCAL_CONST_STRING(lp_printjob_username, szPrintjobUsername)
2105 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
2106 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
2107 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
2108 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
2109 FN_LOCAL_STRING(lp_comment, comment)
2110 FN_LOCAL_STRING(lp_force_user, force_user)
2111 FN_LOCAL_STRING(lp_force_group, force_group)
2112 FN_LOCAL_LIST(lp_readlist, readlist)
2113 FN_LOCAL_LIST(lp_writelist, writelist)
2114 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
2115 FN_LOCAL_STRING(lp_fstype, fstype)
2116 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
2117 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
2118 static FN_LOCAL_STRING(lp_volume, volume)
2119 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
2120 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
2121 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
2122 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
2123 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
2124 FN_LOCAL_STRING(lp_dfree_command, szDfree)
2125 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
2126 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
2127 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
2128 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
2129 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
2130 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
2131 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
2132 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
2133 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
2134 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
2135 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
2136 FN_LOCAL_BOOL(lp_readonly, bRead_only)
2137 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
2138 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
2139 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
2140 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
2141 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
2142 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
2143 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
2144 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
2145 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
2146 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
2147 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
2148 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
2149 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
2150 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
2151 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
2152 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
2153 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
2154 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
2155 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
2156 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
2157 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
2158 FN_LOCAL_BOOL(lp_map_system, bMap_system)
2159 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
2160 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
2161 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
2162 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
2163 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
2164 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
2165 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
2166 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
2167 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
2168 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
2169 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
2170 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
2171 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
2172 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
2173 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
2174 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
2175 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
2176 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
2177 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
2178 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
2179 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
2180 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
2181 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
2182 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
2183 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
2184 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
2185 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
2186 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
2187 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
2188 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
2189 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
2190 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
2191 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
2192 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
2193 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
2194 FN_LOCAL_INTEGER(lp_printing, iPrinting)
2195 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
2196 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
2197 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
2198 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
2199 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
2200 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
2201 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
2202 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
2203 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
2204 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
2205 FN_LOCAL_INTEGER(lp_directory_name_cache_size, iDirectoryNameCacheSize)
2206 FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt)
2207 FN_LOCAL_CHAR(lp_magicchar, magic_char)
2208 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
2209 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
2210 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
2211 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
2212 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
2213 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
2214 FN_GLOBAL_INTEGER(lp_client_ldap_sasl_wrapping, &Globals.client_ldap_sasl_wrapping)
2215
2216 /* local prototypes */
2217
2218 static int map_parameter(const char *pszParmName);
2219 static int map_parameter_canonical(const char *pszParmName, bool *inverse);
2220 static bool set_boolean(bool *pb, const char *pszParmValue);
2221 static const char *get_boolean(bool bool_value);
2222 static int getservicebyname(const char *pszServiceName,
2223                             service * pserviceDest);
2224 static void copy_service(service * pserviceDest,
2225                          service * pserviceSource,
2226                          struct bitmap *pcopymapDest);
2227 static bool do_parameter(const char *pszParmName, const char *pszParmValue);
2228 static bool do_section(const char *pszSectionName);
2229 static void init_copymap(service * pservice);
2230 static bool hash_a_service(const char *name, int number);
2231 static void free_service_byindex(int iService);
2232 static char * canonicalize_servicename(const char *name);
2233 static void show_parameter(int parmIndex);
2234 static bool is_synonym_of(int parm1, int parm2, bool *inverse);
2235
2236 /* This is a helper function for parametrical options support. */
2237 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2238 /* Actual parametrical functions are quite simple */
2239 static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
2240 {
2241         bool global_section = False;
2242         char* param_key;
2243         param_opt_struct *data;
2244         
2245         if (snum >= iNumServices) return NULL;
2246         
2247         if (snum < 0) { 
2248                 data = Globals.param_opt;
2249                 global_section = True;
2250         } else {
2251                 data = ServicePtrs[snum]->param_opt;
2252         }
2253     
2254         asprintf(&param_key, "%s:%s", type, option);
2255         if (!param_key) {
2256                 DEBUG(0,("asprintf failed!\n"));
2257                 return NULL;
2258         }
2259
2260         while (data) {
2261                 if (strcmp(data->key, param_key) == 0) {
2262                         string_free(&param_key);
2263                         return data;
2264                 }
2265                 data = data->next;
2266         }
2267
2268         if (!global_section) {
2269                 /* Try to fetch the same option but from globals */
2270                 /* but only if we are not already working with Globals */
2271                 data = Globals.param_opt;
2272                 while (data) {
2273                         if (strcmp(data->key, param_key) == 0) {
2274                                 string_free(&param_key);
2275                                 return data;
2276                         }
2277                         data = data->next;
2278                 }
2279         }
2280
2281         string_free(&param_key);
2282         
2283         return NULL;
2284 }
2285
2286
2287 #define MISSING_PARAMETER(name) \
2288     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
2289
2290 /*******************************************************************
2291 convenience routine to return int parameters.
2292 ********************************************************************/
2293 static int lp_int(const char *s)
2294 {
2295
2296         if (!s || !*s) {
2297                 MISSING_PARAMETER(lp_int);
2298                 return (-1);
2299         }
2300
2301         return (int)strtol(s, NULL, 0);
2302 }
2303
2304 /*******************************************************************
2305 convenience routine to return unsigned long parameters.
2306 ********************************************************************/
2307 static unsigned long lp_ulong(const char *s)
2308 {
2309
2310         if (!s || !*s) {
2311                 MISSING_PARAMETER(lp_ulong);
2312                 return (0);
2313         }
2314
2315         return strtoul(s, NULL, 0);
2316 }
2317
2318 /*******************************************************************
2319 convenience routine to return boolean parameters.
2320 ********************************************************************/
2321 static bool lp_bool(const char *s)
2322 {
2323         bool ret = False;
2324
2325         if (!s || !*s) {
2326                 MISSING_PARAMETER(lp_bool);
2327                 return False;
2328         }
2329         
2330         if (!set_boolean(&ret,s)) {
2331                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2332                 return False;
2333         }
2334
2335         return ret;
2336 }
2337
2338 /*******************************************************************
2339 convenience routine to return enum parameters.
2340 ********************************************************************/
2341 static int lp_enum(const char *s,const struct enum_list *_enum)
2342 {
2343         int i;
2344
2345         if (!s || !*s || !_enum) {
2346                 MISSING_PARAMETER(lp_enum);
2347                 return (-1);
2348         }
2349         
2350         for (i=0; _enum[i].name; i++) {
2351                 if (strequal(_enum[i].name,s))
2352                         return _enum[i].value;
2353         }
2354
2355         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
2356         return (-1);
2357 }
2358
2359 #undef MISSING_PARAMETER
2360
2361 /* DO NOT USE lp_parm_string ANYMORE!!!!
2362  * use lp_parm_const_string or lp_parm_talloc_string
2363  *
2364  * lp_parm_string is only used to let old modules find this symbol
2365  */
2366 #undef lp_parm_string
2367  char *lp_parm_string(const char *servicename, const char *type, const char *option);
2368  char *lp_parm_string(const char *servicename, const char *type, const char *option)
2369 {
2370         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
2371 }
2372
2373 /* Return parametric option from a given service. Type is a part of option before ':' */
2374 /* Parametric option has following syntax: 'Type: option = value' */
2375 /* the returned value is talloced on the talloc_tos() */
2376 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
2377 {
2378         param_opt_struct *data = get_parametrics(snum, type, option);
2379         
2380         if (data == NULL||data->value==NULL) {
2381                 if (def) {
2382                         return lp_string(def);
2383                 } else {
2384                         return NULL;
2385                 }
2386         }
2387
2388         return lp_string(data->value);
2389 }
2390
2391 /* Return parametric option from a given service. Type is a part of option before ':' */
2392 /* Parametric option has following syntax: 'Type: option = value' */
2393 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
2394 {
2395         param_opt_struct *data = get_parametrics(snum, type, option);
2396         
2397         if (data == NULL||data->value==NULL)
2398                 return def;
2399                 
2400         return data->value;
2401 }
2402
2403 /* Return parametric option from a given service. Type is a part of option before ':' */
2404 /* Parametric option has following syntax: 'Type: option = value' */
2405
2406 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
2407 {
2408         param_opt_struct *data = get_parametrics(snum, type, option);
2409
2410         if (data == NULL||data->value==NULL)
2411                 return (const char **)def;
2412                 
2413         if (data->list==NULL) {
2414                 data->list = str_list_make(NULL, data->value, NULL);
2415         }
2416
2417         return (const char **)data->list;
2418 }
2419
2420 /* Return parametric option from a given service. Type is a part of option before ':' */
2421 /* Parametric option has following syntax: 'Type: option = value' */
2422
2423 int lp_parm_int(int snum, const char *type, const char *option, int def)
2424 {
2425         param_opt_struct *data = get_parametrics(snum, type, option);
2426         
2427         if (data && data->value && *data->value)
2428                 return lp_int(data->value);
2429
2430         return def;
2431 }
2432
2433 /* Return parametric option from a given service. Type is a part of option before ':' */
2434 /* Parametric option has following syntax: 'Type: option = value' */
2435
2436 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
2437 {
2438         param_opt_struct *data = get_parametrics(snum, type, option);
2439         
2440         if (data && data->value && *data->value)
2441                 return lp_ulong(data->value);
2442
2443         return def;
2444 }
2445
2446 /* Return parametric option from a given service. Type is a part of option before ':' */
2447 /* Parametric option has following syntax: 'Type: option = value' */
2448
2449 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
2450 {
2451         param_opt_struct *data = get_parametrics(snum, type, option);
2452         
2453         if (data && data->value && *data->value)
2454                 return lp_bool(data->value);
2455
2456         return def;
2457 }
2458
2459 /* Return parametric option from a given service. Type is a part of option before ':' */
2460 /* Parametric option has following syntax: 'Type: option = value' */
2461
2462 int lp_parm_enum(int snum, const char *type, const char *option,
2463                  const struct enum_list *_enum, int def)
2464 {
2465         param_opt_struct *data = get_parametrics(snum, type, option);
2466         
2467         if (data && data->value && *data->value && _enum)
2468                 return lp_enum(data->value, _enum);
2469
2470         return def;
2471 }
2472
2473
2474 /***************************************************************************
2475  Initialise a service to the defaults.
2476 ***************************************************************************/
2477
2478 static void init_service(service * pservice)
2479 {
2480         memset((char *)pservice, '\0', sizeof(service));
2481         copy_service(pservice, &sDefault, NULL);
2482 }
2483
2484 /***************************************************************************
2485  Free the dynamically allocated parts of a service struct.
2486 ***************************************************************************/
2487
2488 static void free_service(service *pservice)
2489 {
2490         int i;
2491         param_opt_struct *data, *pdata;
2492         if (!pservice)
2493                 return;
2494
2495         if (pservice->szService)
2496                 DEBUG(5, ("free_service: Freeing service %s\n",
2497                        pservice->szService));
2498
2499         string_free(&pservice->szService);
2500         bitmap_free(pservice->copymap);
2501
2502         for (i = 0; parm_table[i].label; i++) {
2503                 if ((parm_table[i].type == P_STRING ||
2504                      parm_table[i].type == P_USTRING) &&
2505                     parm_table[i].p_class == P_LOCAL)
2506                         string_free((char **)
2507                                     (((char *)pservice) +
2508                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2509                 else if (parm_table[i].type == P_LIST &&
2510                          parm_table[i].p_class == P_LOCAL)
2511                              TALLOC_FREE(*((char ***)
2512                                            (((char *)pservice) +
2513                                             PTR_DIFF(parm_table[i].ptr,
2514                                                      &sDefault))));
2515         }
2516
2517         data = pservice->param_opt;
2518         if (data)
2519                 DEBUG(5,("Freeing parametrics:\n"));
2520         while (data) {
2521                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2522                 string_free(&data->key);
2523                 string_free(&data->value);
2524                 TALLOC_FREE(data->list);
2525                 pdata = data->next;
2526                 SAFE_FREE(data);
2527                 data = pdata;
2528         }
2529
2530         ZERO_STRUCTP(pservice);
2531 }
2532
2533
2534 /***************************************************************************
2535  remove a service indexed in the ServicePtrs array from the ServiceHash
2536  and free the dynamically allocated parts
2537 ***************************************************************************/
2538
2539 static void free_service_byindex(int idx)
2540 {
2541         if ( !LP_SNUM_OK(idx) ) 
2542                 return;
2543
2544         ServicePtrs[idx]->valid = False;
2545         invalid_services[num_invalid_services++] = idx;
2546
2547         /* we have to cleanup the hash record */
2548
2549         if (ServicePtrs[idx]->szService) {
2550                 char *canon_name = canonicalize_servicename(
2551                         ServicePtrs[idx]->szService );
2552                 
2553                 dbwrap_delete_bystring(ServiceHash, canon_name );
2554                 TALLOC_FREE(canon_name);
2555         }
2556
2557         free_service(ServicePtrs[idx]);
2558 }
2559
2560 /***************************************************************************
2561  Add a new service to the services array initialising it with the given 
2562  service. 
2563 ***************************************************************************/
2564
2565 static int add_a_service(const service *pservice, const char *name)
2566 {
2567         int i;
2568         service tservice;
2569         int num_to_alloc = iNumServices + 1;
2570         param_opt_struct *data, *pdata;
2571
2572         tservice = *pservice;
2573
2574         /* it might already exist */
2575         if (name) {
2576                 i = getservicebyname(name, NULL);
2577                 if (i >= 0) {
2578                         /* Clean all parametric options for service */
2579                         /* They will be added during parsing again */
2580                         data = ServicePtrs[i]->param_opt;
2581                         while (data) {
2582                                 string_free(&data->key);
2583                                 string_free(&data->value);
2584                                 TALLOC_FREE(data->list);
2585                                 pdata = data->next;
2586                                 SAFE_FREE(data);
2587                                 data = pdata;
2588                         }
2589                         ServicePtrs[i]->param_opt = NULL;
2590                         return (i);
2591                 }
2592         }
2593
2594         /* find an invalid one */
2595         i = iNumServices;
2596         if (num_invalid_services > 0) {
2597                 i = invalid_services[--num_invalid_services];
2598         }
2599
2600         /* if not, then create one */
2601         if (i == iNumServices) {
2602                 service **tsp;
2603                 int *tinvalid;
2604                 
2605                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2606                 if (tsp == NULL) {
2607                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2608                         return (-1);
2609                 }
2610                 ServicePtrs = tsp;
2611                 ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2612                 if (!ServicePtrs[iNumServices]) {
2613                         DEBUG(0,("add_a_service: out of memory!\n"));
2614                         return (-1);
2615                 }
2616                 iNumServices++;
2617
2618                 /* enlarge invalid_services here for now... */
2619                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2620                                              num_to_alloc);
2621                 if (tinvalid == NULL) {
2622                         DEBUG(0,("add_a_service: failed to enlarge "
2623                                  "invalid_services!\n"));
2624                         return (-1);
2625                 }
2626                 invalid_services = tinvalid;
2627         } else {
2628                 free_service_byindex(i);
2629         }
2630
2631         ServicePtrs[i]->valid = True;
2632
2633         init_service(ServicePtrs[i]);
2634         copy_service(ServicePtrs[i], &tservice, NULL);
2635         if (name)
2636                 string_set(&ServicePtrs[i]->szService, name);
2637                 
2638         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2639                 i, ServicePtrs[i]->szService));
2640
2641         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2642                 return (-1);
2643         }
2644                 
2645         return (i);
2646 }
2647
2648 /***************************************************************************
2649   Convert a string to uppercase and remove whitespaces.
2650 ***************************************************************************/
2651
2652 static char *canonicalize_servicename(const char *src)
2653 {
2654         char *result;
2655
2656         if ( !src ) {
2657                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2658                 return NULL;
2659         }
2660
2661         result = talloc_strdup(talloc_tos(), src);
2662         SMB_ASSERT(result != NULL);
2663
2664         strlower_m(result);
2665         return result;
2666 }
2667
2668 /***************************************************************************
2669   Add a name/index pair for the services array to the hash table.
2670 ***************************************************************************/
2671
2672 static bool hash_a_service(const char *name, int idx)
2673 {
2674         char *canon_name;
2675
2676         if ( !ServiceHash ) {
2677                 DEBUG(10,("hash_a_service: creating servicehash\n"));
2678                 ServiceHash = db_open_rbt(NULL);
2679                 if ( !ServiceHash ) {
2680                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2681                         return False;
2682                 }
2683         }
2684
2685         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2686                 idx, name));
2687
2688         canon_name = canonicalize_servicename( name );
2689
2690         dbwrap_store_bystring(ServiceHash, canon_name,
2691                               make_tdb_data((uint8 *)&idx, sizeof(idx)),
2692                               TDB_REPLACE);
2693
2694         TALLOC_FREE(canon_name);
2695
2696         return True;
2697 }
2698
2699 /***************************************************************************
2700  Add a new home service, with the specified home directory, defaults coming
2701  from service ifrom.
2702 ***************************************************************************/
2703
2704 bool lp_add_home(const char *pszHomename, int iDefaultService,
2705                  const char *user, const char *pszHomedir)
2706 {
2707         int i;
2708
2709         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2710
2711         if (i < 0)
2712                 return (False);
2713
2714         if (!(*(ServicePtrs[iDefaultService]->szPath))
2715             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2716                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
2717         }
2718
2719         if (!(*(ServicePtrs[i]->comment))) {
2720                 char *comment = NULL;
2721                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
2722                         return false;
2723                 }
2724                 string_set(&ServicePtrs[i]->comment, comment);
2725                 SAFE_FREE(comment);
2726         }
2727
2728         /* set the browseable flag from the global default */
2729
2730         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2731
2732         ServicePtrs[i]->autoloaded = True;
2733
2734         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2735                user, ServicePtrs[i]->szPath ));
2736
2737         return (True);
2738 }
2739
2740 /***************************************************************************
2741  Add a new service, based on an old one.
2742 ***************************************************************************/
2743
2744 int lp_add_service(const char *pszService, int iDefaultService)
2745 {
2746         if (iDefaultService < 0) {
2747                 return add_a_service(&sDefault, pszService);
2748         }
2749
2750         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2751 }
2752
2753 /***************************************************************************
2754  Add the IPC service.
2755 ***************************************************************************/
2756
2757 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
2758 {
2759         char *comment = NULL;
2760         int i = add_a_service(&sDefault, ipc_name);
2761
2762         if (i < 0)
2763                 return (False);
2764
2765         if (asprintf(&comment, "IPC Service (%s)",
2766                                 Globals.szServerString) < 0) {
2767                 return (False);
2768         }
2769
2770         string_set(&ServicePtrs[i]->szPath, tmpdir());
2771         string_set(&ServicePtrs[i]->szUsername, "");
2772         string_set(&ServicePtrs[i]->comment, comment);
2773         string_set(&ServicePtrs[i]->fstype, "IPC");
2774         ServicePtrs[i]->iMaxConnections = 0;
2775         ServicePtrs[i]->bAvailable = True;
2776         ServicePtrs[i]->bRead_only = True;
2777         ServicePtrs[i]->bGuest_only = False;
2778         ServicePtrs[i]->bGuest_ok = guest_ok;
2779         ServicePtrs[i]->bPrint_ok = False;
2780         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2781
2782         DEBUG(3, ("adding IPC service\n"));
2783
2784         SAFE_FREE(comment);
2785         return (True);
2786 }
2787
2788 /***************************************************************************
2789  Add a new printer service, with defaults coming from service iFrom.
2790 ***************************************************************************/
2791
2792 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
2793 {
2794         const char *comment = "From Printcap";
2795         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2796
2797         if (i < 0)
2798                 return (False);
2799
2800         /* note that we do NOT default the availability flag to True - */
2801         /* we take it from the default service passed. This allows all */
2802         /* dynamic printers to be disabled by disabling the [printers] */
2803         /* entry (if/when the 'available' keyword is implemented!).    */
2804
2805         /* the printer name is set to the service name. */
2806         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2807         string_set(&ServicePtrs[i]->comment, comment);
2808
2809         /* set the browseable flag from the gloabl default */
2810         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2811
2812         /* Printers cannot be read_only. */
2813         ServicePtrs[i]->bRead_only = False;
2814         /* No share modes on printer services. */
2815         ServicePtrs[i]->bShareModes = False;
2816         /* No oplocks on printer services. */
2817         ServicePtrs[i]->bOpLocks = False;
2818         /* Printer services must be printable. */
2819         ServicePtrs[i]->bPrint_ok = True;
2820         
2821         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2822
2823         return (True);
2824 }
2825
2826
2827 /***************************************************************************
2828  Check whether the given parameter name is valid.
2829  Parametric options (names containing a colon) are considered valid.
2830 ***************************************************************************/
2831
2832 bool lp_parameter_is_valid(const char *pszParmName)
2833 {
2834         return ((map_parameter(pszParmName) != -1) ||
2835                 (strchr(pszParmName, ':') != NULL));
2836 }
2837
2838 /***************************************************************************
2839  Check whether the given name is the name of a global parameter.
2840  Returns True for strings belonging to parameters of class
2841  P_GLOBAL, False for all other strings, also for parametric options
2842  and strings not belonging to any option.
2843 ***************************************************************************/
2844
2845 bool lp_parameter_is_global(const char *pszParmName)
2846 {
2847         int num = map_parameter(pszParmName);
2848
2849         if (num >= 0) {
2850                 return (parm_table[num].p_class == P_GLOBAL);
2851         }
2852
2853         return False;
2854 }
2855
2856 /**************************************************************************
2857  Check whether the given name is the canonical name of a parameter.
2858  Returns False if it is not a valid parameter Name.
2859  For parametric options, True is returned.
2860 **************************************************************************/
2861
2862 bool lp_parameter_is_canonical(const char *parm_name)
2863 {
2864         if (!lp_parameter_is_valid(parm_name)) {
2865                 return False;
2866         }
2867
2868         return (map_parameter(parm_name) ==
2869                 map_parameter_canonical(parm_name, NULL));
2870 }
2871
2872 /**************************************************************************
2873  Determine the canonical name for a parameter.
2874  Indicate when it is an inverse (boolean) synonym instead of a
2875  "usual" synonym.
2876 **************************************************************************/
2877
2878 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
2879                                bool *inverse)
2880 {
2881         int num;
2882
2883         if (!lp_parameter_is_valid(parm_name)) {
2884                 *canon_parm = NULL;
2885                 return False;
2886         }
2887
2888         num = map_parameter_canonical(parm_name, inverse);
2889         if (num < 0) {
2890                 /* parametric option */
2891                 *canon_parm = parm_name;
2892         } else {
2893                 *canon_parm = parm_table[num].label;
2894         }
2895
2896         return True;
2897
2898 }
2899
2900 /**************************************************************************
2901  Determine the canonical name for a parameter.
2902  Turn the value given into the inverse boolean expression when
2903  the synonym is an invers boolean synonym.
2904
2905  Return True if parm_name is a valid parameter name and
2906  in case it is an invers boolean synonym, if the val string could
2907  successfully be converted to the reverse bool.
2908  Return false in all other cases.
2909 **************************************************************************/
2910
2911 bool lp_canonicalize_parameter_with_value(const char *parm_name,
2912                                           const char *val,
2913                                           const char **canon_parm,
2914                                           const char **canon_val)
2915 {
2916         int num;
2917         bool inverse;
2918
2919         if (!lp_parameter_is_valid(parm_name)) {
2920                 *canon_parm = NULL;
2921                 *canon_val = NULL;
2922                 return False;
2923         }
2924
2925         num = map_parameter_canonical(parm_name, &inverse);
2926         if (num < 0) {
2927                 /* parametric option */
2928                 *canon_parm = parm_name;
2929                 *canon_val = val;
2930         } else {
2931                 *canon_parm = parm_table[num].label;
2932                 if (inverse) {
2933                         if (!lp_invert_boolean(val, canon_val)) {
2934                                 *canon_val = NULL;
2935                                 return False;
2936                         }
2937                 } else {
2938                         *canon_val = val;
2939                 }
2940         }
2941
2942         return True;
2943 }
2944
2945 /***************************************************************************
2946  Map a parameter's string representation to something we can use. 
2947  Returns False if the parameter string is not recognised, else TRUE.
2948 ***************************************************************************/
2949
2950 static int map_parameter(const char *pszParmName)
2951 {
2952         int iIndex;
2953
2954         if (*pszParmName == '-')
2955                 return (-1);
2956
2957         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2958                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2959                         return (iIndex);
2960
2961         /* Warn only if it isn't parametric option */
2962         if (strchr(pszParmName, ':') == NULL)
2963                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2964         /* We do return 'fail' for parametric options as well because they are
2965            stored in different storage
2966          */
2967         return (-1);
2968 }
2969
2970 /***************************************************************************
2971  Map a parameter's string representation to the index of the canonical
2972  form of the parameter (it might be a synonym).
2973  Returns -1 if the parameter string is not recognised.
2974 ***************************************************************************/
2975
2976 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
2977 {
2978         int parm_num, canon_num;
2979         bool loc_inverse = False;
2980
2981         parm_num = map_parameter(pszParmName);
2982         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
2983                 /* invalid, parametric or no canidate for synonyms ... */
2984                 goto done;
2985         }
2986
2987         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
2988                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
2989                         parm_num = canon_num;
2990                         goto done;
2991                 }
2992         }
2993
2994 done:
2995         if (inverse != NULL) {
2996                 *inverse = loc_inverse;
2997         }
2998         return parm_num;
2999 }
3000
3001 /***************************************************************************
3002  return true if parameter number parm1 is a synonym of parameter
3003  number parm2 (parm2 being the principal name).
3004  set inverse to True if parm1 is P_BOOLREV and parm2 is P_BOOL,
3005  False otherwise.
3006 ***************************************************************************/
3007
3008 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
3009 {
3010         if ((parm_table[parm1].ptr == parm_table[parm2].ptr) &&
3011             (parm_table[parm1].flags & FLAG_HIDE) &&
3012             !(parm_table[parm2].flags & FLAG_HIDE))
3013         {
3014                 if (inverse != NULL) {
3015                         if ((parm_table[parm1].type == P_BOOLREV) &&
3016                             (parm_table[parm2].type == P_BOOL))
3017                         {
3018                                 *inverse = True;
3019                         } else {
3020                                 *inverse = False;
3021                         }
3022                 }
3023                 return True;
3024         }
3025         return False;
3026 }
3027
3028 /***************************************************************************
3029  Show one parameter's name, type, [values,] and flags.
3030  (helper functions for show_parameter_list)
3031 ***************************************************************************/
3032
3033 static void show_parameter(int parmIndex)
3034 {
3035         int enumIndex, flagIndex;
3036         int parmIndex2;
3037         bool hadFlag;
3038         bool hadSyn;
3039         bool inverse;
3040         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
3041                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
3042                 "P_ENUM", "P_SEP"};
3043         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
3044                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
3045                 FLAG_HIDE, FLAG_DOS_STRING};
3046         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
3047                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
3048                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
3049
3050         printf("%s=%s", parm_table[parmIndex].label,
3051                type[parm_table[parmIndex].type]);
3052         if (parm_table[parmIndex].type == P_ENUM) {
3053                 printf(",");
3054                 for (enumIndex=0;
3055                      parm_table[parmIndex].enum_list[enumIndex].name;
3056                      enumIndex++)
3057                 {
3058                         printf("%s%s",
3059                                enumIndex ? "|" : "",
3060                                parm_table[parmIndex].enum_list[enumIndex].name);
3061                 }
3062         }
3063         printf(",");
3064         hadFlag = False;
3065         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
3066                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
3067                         printf("%s%s",
3068                                 hadFlag ? "|" : "",
3069                                 flag_names[flagIndex]);
3070                         hadFlag = True;
3071                 }
3072         }
3073
3074         /* output synonyms */
3075         hadSyn = False;
3076         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
3077                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
3078                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
3079                                parm_table[parmIndex2].label);
3080                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
3081                         if (!hadSyn) {
3082                                 printf(" (synonyms: ");
3083                                 hadSyn = True;
3084                         } else {
3085                                 printf(", ");
3086                         }
3087                         printf("%s%s", parm_table[parmIndex2].label,
3088                                inverse ? "[i]" : "");
3089                 }
3090         }
3091         if (hadSyn) {
3092                 printf(")");
3093         }
3094
3095         printf("\n");
3096 }
3097
3098 /***************************************************************************
3099  Show all parameter's name, type, [values,] and flags.
3100 ***************************************************************************/
3101
3102 void show_parameter_list(void)
3103 {
3104         int classIndex, parmIndex;
3105         const char *section_names[] = { "local", "global", NULL};
3106
3107         for (classIndex=0; section_names[classIndex]; classIndex++) {
3108                 printf("[%s]\n", section_names[classIndex]);
3109                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
3110                         if (parm_table[parmIndex].p_class == classIndex) {
3111                                 show_parameter(parmIndex);
3112                         }
3113                 }
3114         }
3115 }
3116
3117 /***************************************************************************
3118  Set a boolean variable from the text value stored in the passed string.
3119  Returns True in success, False if the passed string does not correctly 
3120  represent a boolean.
3121 ***************************************************************************/
3122
3123 static bool set_boolean(bool *pb, const char *pszParmValue)
3124 {
3125         bool bRetval;
3126         bool value;
3127
3128         bRetval = True;
3129         value = False;
3130         if (strwicmp(pszParmValue, "yes") == 0 ||
3131             strwicmp(pszParmValue, "true") == 0 ||
3132             strwicmp(pszParmValue, "1") == 0)
3133                 value = True;
3134         else if (strwicmp(pszParmValue, "no") == 0 ||
3135                     strwicmp(pszParmValue, "False") == 0 ||
3136                     strwicmp(pszParmValue, "0") == 0)
3137                 value = False;
3138         else {
3139                 DEBUG(2,
3140                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
3141                        pszParmValue));
3142                 bRetval = False;
3143         }
3144
3145         if ((pb != NULL) && (bRetval != False)) {
3146                 *pb = value;
3147         }
3148
3149         return (bRetval);
3150 }
3151
3152
3153 /***************************************************************************
3154  Check if a given string correctly represents a boolean value.
3155 ***************************************************************************/
3156
3157 bool lp_string_is_valid_boolean(const char *parm_value)
3158 {
3159         return set_boolean(NULL, parm_value);
3160 }
3161
3162 /***************************************************************************
3163  Get the standard string representation of a boolean value ("yes" or "no")
3164 ***************************************************************************/
3165
3166 static const char *get_boolean(bool bool_value)
3167 {
3168         static const char *yes_str = "yes";
3169         static const char *no_str = "no";
3170
3171         return (bool_value ? yes_str : no_str);
3172 }
3173
3174 /***************************************************************************
3175  Provide the string of the negated boolean value associated to the boolean
3176  given as a string. Returns False if the passed string does not correctly
3177  represent a boolean.
3178 ***************************************************************************/
3179
3180 bool lp_invert_boolean(const char *str, const char **inverse_str)
3181 {
3182         bool val;
3183
3184         if (!set_boolean(&val, str)) {
3185                 return False;
3186         }
3187
3188         *inverse_str = get_boolean(!val);
3189         return True;
3190 }
3191
3192 /***************************************************************************
3193  Provide the canonical string representation of a boolean value given
3194  as a string. Return True on success, False if the string given does
3195  not correctly represent a boolean.
3196 ***************************************************************************/
3197
3198 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
3199 {
3200         bool val;
3201
3202         if (!set_boolean(&val, str)) {
3203                 return False;
3204         }
3205
3206         *canon_str = get_boolean(val);
3207         return True;
3208 }
3209
3210 /***************************************************************************
3211 Find a service by name. Otherwise works like get_service.
3212 ***************************************************************************/
3213
3214 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
3215 {
3216         int iService = -1;
3217         char *canon_name;
3218         TDB_DATA data;
3219
3220         if (ServiceHash == NULL) {
3221                 return -1;
3222         }
3223
3224         canon_name = canonicalize_servicename(pszServiceName);
3225
3226         data = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name);
3227
3228         if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
3229                 iService = *(int *)data.dptr;
3230         }
3231
3232         TALLOC_FREE(canon_name);
3233
3234         if ((iService != -1) && (LP_SNUM_OK(iService))
3235             && (pserviceDest != NULL)) {
3236                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
3237         }
3238
3239         return (iService);
3240 }
3241
3242 /***************************************************************************
3243  Copy a service structure to another.
3244  If pcopymapDest is NULL then copy all fields
3245 ***************************************************************************/
3246
3247 static void copy_service(service * pserviceDest, service * pserviceSource,
3248                          struct bitmap *pcopymapDest)
3249 {
3250         int i;
3251         bool bcopyall = (pcopymapDest == NULL);
3252         param_opt_struct *data, *pdata, *paramo;
3253         bool not_added;
3254
3255         for (i = 0; parm_table[i].label; i++)
3256                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
3257                     (bcopyall || bitmap_query(pcopymapDest,i))) {
3258                         void *def_ptr = parm_table[i].ptr;
3259                         void *src_ptr =
3260                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
3261                                                                     &sDefault);
3262                         void *dest_ptr =
3263                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
3264                                                                   &sDefault);
3265
3266                         switch (parm_table[i].type) {
3267                                 case P_BOOL:
3268                                 case P_BOOLREV:
3269                                         *(bool *)dest_ptr = *(bool *)src_ptr;
3270                                         break;
3271
3272                                 case P_INTEGER:
3273                                 case P_ENUM:
3274                                 case P_OCTAL:
3275                                         *(int *)dest_ptr = *(int *)src_ptr;
3276                                         break;
3277
3278                                 case P_CHAR:
3279                                         *(char *)dest_ptr = *(char *)src_ptr;
3280                                         break;
3281
3282                                 case P_STRING:
3283                                         string_set((char **)dest_ptr,
3284                                                    *(char **)src_ptr);
3285                                         break;
3286
3287                                 case P_USTRING:
3288                                         string_set((char **)dest_ptr,
3289                                                    *(char **)src_ptr);
3290                                         strupper_m(*(char **)dest_ptr);
3291                                         break;
3292                                 case P_LIST:
3293                                         TALLOC_FREE(*((char ***)dest_ptr));
3294                                         str_list_copy(NULL, (char ***)dest_ptr,
3295                                                       *(const char ***)src_ptr);
3296                                         break;
3297                                 default:
3298                                         break;
3299                         }
3300                 }
3301
3302         if (bcopyall) {
3303                 init_copymap(pserviceDest);
3304                 if (pserviceSource->copymap)
3305                         bitmap_copy(pserviceDest->copymap,
3306                                     pserviceSource->copymap);
3307         }
3308         
3309         data = pserviceSource->param_opt;
3310         while (data) {
3311                 not_added = True;
3312                 pdata = pserviceDest->param_opt;
3313                 /* Traverse destination */
3314                 while (pdata) {
3315                         /* If we already have same option, override it */
3316                         if (strcmp(pdata->key, data->key) == 0) {
3317                                 string_free(&pdata->value);
3318                                 TALLOC_FREE(data->list);
3319                                 pdata->value = SMB_STRDUP(data->value);
3320                                 not_added = False;
3321                                 break;
3322                         }
3323                         pdata = pdata->next;
3324                 }
3325                 if (not_added) {
3326                     paramo = SMB_XMALLOC_P(param_opt_struct);
3327                     paramo->key = SMB_STRDUP(data->key);
3328                     paramo->value = SMB_STRDUP(data->value);
3329                     paramo->list = NULL;
3330                     DLIST_ADD(pserviceDest->param_opt, paramo);
3331                 }
3332                 data = data->next;
3333         }
3334 }
3335
3336 /***************************************************************************
3337 Check a service for consistency. Return False if the service is in any way
3338 incomplete or faulty, else True.
3339 ***************************************************************************/
3340
3341 bool service_ok(int iService)
3342 {
3343         bool bRetval;
3344
3345         bRetval = True;
3346         if (ServicePtrs[iService]->szService[0] == '\0') {
3347                 DEBUG(0, ("The following message indicates an internal error:\n"));
3348                 DEBUG(0, ("No service name in service entry.\n"));
3349                 bRetval = False;
3350         }
3351
3352         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
3353         /* I can't see why you'd want a non-printable printer service...        */
3354         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
3355                 if (!ServicePtrs[iService]->bPrint_ok) {
3356                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
3357                                ServicePtrs[iService]->szService));
3358                         ServicePtrs[iService]->bPrint_ok = True;
3359                 }
3360                 /* [printers] service must also be non-browsable. */
3361                 if (ServicePtrs[iService]->bBrowseable)
3362                         ServicePtrs[iService]->bBrowseable = False;
3363         }
3364
3365         if (ServicePtrs[iService]->szPath[0] == '\0' &&
3366             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
3367             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
3368             ) {
3369                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
3370                         ServicePtrs[iService]->szService));
3371                 ServicePtrs[iService]->bAvailable = False;
3372         }
3373
3374         /* If a service is flagged unavailable, log the fact at level 1. */
3375         if (!ServicePtrs[iService]->bAvailable)
3376                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3377                           ServicePtrs[iService]->szService));
3378
3379         return (bRetval);
3380 }
3381
3382 /*
3383  * process_registry_globals
3384  */
3385 static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
3386 {
3387         WERROR werr;
3388         char **param_names;
3389         char **param_values;
3390         uint32_t num_params;
3391         uint32_t count;
3392         TALLOC_CTX *mem_ctx = talloc_stackframe();
3393         bool ret = false;
3394
3395         if (conf_ctx == NULL) {
3396                 /* first time */
3397                 werr = libnet_conf_open(NULL, &conf_ctx);
3398                 if (!W_ERROR_IS_OK(werr)) {
3399                         goto done;
3400                 }
3401         }
3402
3403         werr = libnet_conf_get_share(mem_ctx, conf_ctx, GLOBAL_NAME,
3404                                      &num_params, &param_names, &param_values);
3405         if (!W_ERROR_IS_OK(werr)) {
3406                 goto done;
3407         }
3408
3409         for (count = 0; count < num_params; count++) {
3410                 ret = pfunc(param_names[count], param_values[count]);
3411                 if (ret != true) {
3412                         goto done;
3413                 }
3414         }
3415
3416         ret = pfunc("registry shares", "yes");
3417         conf_last_seqnum = libnet_conf_get_seqnum(conf_ctx, NULL, NULL);
3418
3419 done:
3420         TALLOC_FREE(mem_ctx);
3421         return ret;
3422 }
3423
3424 static struct file_lists {
3425         struct file_lists *next;
3426         char *name;
3427         char *subfname;
3428         time_t modtime;
3429 } *file_lists = NULL;
3430
3431 /*******************************************************************
3432  Keep a linked list of all config files so we know when one has changed 
3433  it's date and needs to be reloaded.
3434 ********************************************************************/
3435
3436 static void add_to_file_list(const char *fname, const char *subfname)
3437 {
3438         struct file_lists *f = file_lists;
3439
3440         while (f) {
3441                 if (f->name && !strcmp(f->name, fname))
3442                         break;
3443                 f = f->next;
3444         }
3445
3446         if (!f) {
3447                 f = SMB_MALLOC_P(struct file_lists);
3448                 if (!f)
3449                         return;
3450                 f->next = file_lists;
3451                 f->name = SMB_STRDUP(fname);
3452                 if (!f->name) {
3453                         SAFE_FREE(f);
3454                         return;
3455                 }
3456                 f->subfname = SMB_STRDUP(subfname);
3457                 if (!f->subfname) {
3458                         SAFE_FREE(f);
3459                         return;
3460                 }
3461                 file_lists = f;
3462                 f->modtime = file_modtime(subfname);
3463         } else {
3464                 time_t t = file_modtime(subfname);
3465                 if (t)
3466                         f->modtime = t;
3467         }
3468 }
3469
3470 /**
3471  * Utility function for outsiders to check if we're running on registry.
3472  */
3473 bool lp_config_backend_is_registry(void)
3474 {
3475         return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
3476 }
3477
3478 /*******************************************************************
3479  Check if a config file has changed date.
3480 ********************************************************************/
3481
3482 bool lp_file_list_changed(void)
3483 {
3484         struct file_lists *f = file_lists;
3485
3486         DEBUG(6, ("lp_file_list_changed()\n"));
3487
3488         if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
3489                 if (conf_ctx == NULL) {
3490                         WERROR werr;
3491                         werr = libnet_conf_open(NULL, &conf_ctx);
3492                         if (!W_ERROR_IS_OK(werr)) {
3493                                 DEBUG(0, ("error opening configuration: %s\n",
3494                                           dos_errstr(werr)));
3495                                 return false;
3496                         }
3497                 }
3498                 if (conf_last_seqnum !=
3499                     libnet_conf_get_seqnum(conf_ctx, NULL, NULL))
3500                 {
3501                         DEBUGADD(6, ("regdb seqnum changed: old = %lu, "
3502                                      "new = %lu\n", conf_last_seqnum,
3503                                      libnet_conf_get_seqnum(conf_ctx, NULL, NULL)));
3504                         return true;
3505                 } else {
3506                         /*
3507                          * Don't check files when config_backend is registry.
3508                          * Remove this to obtain checking of files even with
3509                          * registry config backend. That would enable switching
3510                          * off registry configuration by changing smb.conf even
3511                          * without restarting smbd.
3512                          */
3513                         return false;
3514                 }
3515         }
3516
3517         while (f) {
3518                 char *n2 = NULL;
3519                 time_t mod_time;
3520
3521                 n2 = alloc_sub_basic(get_current_username(),
3522                                     current_user_info.domain,
3523                                     f->name);
3524                 if (!n2) {
3525                         return false;
3526                 }
3527                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3528                              f->name, n2, ctime(&f->modtime)));
3529
3530                 mod_time = file_modtime(n2);
3531
3532                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3533                         DEBUGADD(6,
3534                                  ("file %s modified: %s\n", n2,
3535                                   ctime(&mod_time)));
3536                         f->modtime = mod_time;
3537                         SAFE_FREE(f->subfname);
3538                         f->subfname = n2; /* Passing ownership of
3539                                              return from alloc_sub_basic
3540                                              above. */
3541                         return true;
3542                 }
3543                 SAFE_FREE(n2);
3544                 f = f->next;
3545         }
3546         return (False);
3547 }
3548
3549
3550 /***************************************************************************
3551  Run standard_sub_basic on netbios name... needed because global_myname
3552  is not accessed through any lp_ macro.
3553  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3554 ***************************************************************************/
3555
3556 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3557 {
3558         bool ret;
3559         char *netbios_name = alloc_sub_basic(get_current_username(),
3560                                         current_user_info.domain,
3561                                         pszParmValue);
3562
3563         ret = set_global_myname(netbios_name);
3564         SAFE_FREE(netbios_name);
3565         string_set(&Globals.szNetbiosName,global_myname());
3566
3567         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3568                global_myname()));
3569
3570         return ret;
3571 }
3572
3573 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
3574 {
3575         if (strcmp(*ptr, pszParmValue) != 0) {
3576                 string_set(ptr, pszParmValue);
3577                 init_iconv();
3578         }
3579         return True;
3580 }
3581
3582
3583
3584 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3585 {
3586         bool ret;
3587         
3588         ret = set_global_myworkgroup(pszParmValue);
3589         string_set(&Globals.szWorkgroup,lp_workgroup());
3590         
3591         return ret;
3592 }
3593
3594 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3595 {
3596         bool ret;
3597         
3598         ret = set_global_scope(pszParmValue);
3599         string_set(&Globals.szNetbiosScope,global_scope());
3600
3601         return ret;
3602 }
3603
3604 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3605 {
3606         TALLOC_FREE(Globals.szNetbiosAliases);
3607         Globals.szNetbiosAliases = str_list_make(NULL, pszParmValue, NULL);
3608         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3609 }
3610
3611 /***************************************************************************
3612  Handle the include operation.
3613 ***************************************************************************/
3614
3615 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
3616 {
3617         char *fname;
3618
3619         fname = alloc_sub_basic(get_current_username(),
3620                                 current_user_info.domain,
3621                                 pszParmValue);
3622
3623         add_to_file_list(pszParmValue, fname);
3624
3625         string_set(ptr, fname);
3626
3627         if (file_exist(fname, NULL)) {
3628                 bool ret = pm_process(fname, do_section, do_parameter);
3629                 SAFE_FREE(fname);
3630                 return ret;
3631         }
3632
3633         DEBUG(2, ("Can't find include file %s\n", fname));
3634         SAFE_FREE(fname);
3635         return false;
3636 }
3637
3638 /***************************************************************************
3639  Handle the interpretation of the copy parameter.
3640 ***************************************************************************/
3641
3642 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
3643 {
3644         bool bRetval;
3645         int iTemp;
3646         service serviceTemp;
3647
3648         string_set(ptr, pszParmValue);
3649
3650         init_service(&serviceTemp);
3651
3652         bRetval = False;
3653
3654         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3655
3656         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3657                 if (iTemp == iServiceIndex) {
3658                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3659                 } else {
3660                         copy_service(ServicePtrs[iServiceIndex],
3661                                      &serviceTemp,
3662                                      ServicePtrs[iServiceIndex]->copymap);
3663                         bRetval = True;
3664                 }
3665         } else {
3666                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3667                 bRetval = False;
3668         }
3669
3670         free_service(&serviceTemp);
3671         return (bRetval);
3672 }
3673
3674 static bool handle_ldap_debug_level(int snum, const char *pszParmValue, char **ptr)
3675 {
3676         Globals.ldap_debug_level = lp_int(pszParmValue);
3677         init_ldap_debugging();
3678         return true;
3679 }
3680
3681 /***************************************************************************
3682  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3683  parameters is:
3684
3685  [global]
3686
3687         idmap uid = 1000-1999
3688         idmap gid = 700-899
3689
3690  We only do simple parsing checks here.  The strings are parsed into useful
3691  structures in the idmap daemon code.
3692
3693 ***************************************************************************/
3694
3695 /* Some lp_ routines to return idmap [ug]id information */
3696
3697 static uid_t idmap_uid_low, idmap_uid_high;
3698 static gid_t idmap_gid_low, idmap_gid_high;
3699
3700 bool lp_idmap_uid(uid_t *low, uid_t *high)
3701 {
3702         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3703                 return False;
3704
3705         if (low)
3706                 *low = idmap_uid_low;
3707
3708         if (high)
3709                 *high = idmap_uid_high;
3710
3711         return True;
3712 }
3713
3714 bool lp_idmap_gid(gid_t *low, gid_t *high)
3715 {
3716         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3717                 return False;
3718
3719         if (low)
3720                 *low = idmap_gid_low;
3721
3722         if (high)
3723                 *high = idmap_gid_high;
3724
3725         return True;
3726 }
3727
3728 /* Do some simple checks on "idmap [ug]id" parameter values */
3729
3730 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3731 {
3732         uint32 low, high;
3733
3734         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3735                 return False;
3736
3737         /* Parse OK */
3738
3739         string_set(ptr, pszParmValue);
3740
3741         idmap_uid_low = low;
3742         idmap_uid_high = high;
3743
3744         return True;
3745 }
3746
3747 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3748 {
3749         uint32 low, high;
3750
3751         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3752                 return False;
3753
3754         /* Parse OK */
3755
3756         string_set(ptr, pszParmValue);
3757
3758         idmap_gid_low = low;
3759         idmap_gid_high = high;
3760
3761         return True;
3762 }
3763
3764 /***************************************************************************
3765  Handle the DEBUG level list.
3766 ***************************************************************************/
3767
3768 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3769 {
3770         string_set(ptr, pszParmValueIn);
3771         return debug_parse_levels(pszParmValueIn);
3772 }
3773
3774 /***************************************************************************
3775  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3776 ***************************************************************************/
3777
3778 static const char *append_ldap_suffix( const char *str )
3779 {
3780         const char *suffix_string;
3781
3782
3783         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
3784                                         Globals.szLdapSuffix );
3785         if ( !suffix_string ) {
3786                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3787                 return "";
3788         }
3789
3790         return suffix_string;
3791 }
3792
3793 const char *lp_ldap_machine_suffix(void)
3794 {
3795         if (Globals.szLdapMachineSuffix[0])
3796                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3797
3798         return lp_string(Globals.szLdapSuffix);
3799 }
3800
3801 const char *lp_ldap_user_suffix(void)
3802 {
3803         if (Globals.szLdapUserSuffix[0])
3804                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3805
3806         return lp_string(Globals.szLdapSuffix);
3807 }
3808
3809 const char *lp_ldap_group_suffix(void)
3810 {
3811         if (Globals.szLdapGroupSuffix[0])
3812                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3813
3814         return lp_string(Globals.szLdapSuffix);
3815 }
3816
3817 const char *lp_ldap_idmap_suffix(void)
3818 {
3819         if (Globals.szLdapIdmapSuffix[0])
3820                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3821
3822         return lp_string(Globals.szLdapSuffix);
3823 }
3824
3825 /****************************************************************************
3826  set the value for a P_ENUM
3827  ***************************************************************************/
3828
3829 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3830                               int *ptr )
3831 {
3832         int i;
3833
3834         for (i = 0; parm->enum_list[i].name; i++) {
3835                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3836                         *ptr = parm->enum_list[i].value;
3837                         break;
3838                 }
3839         }
3840 }
3841
3842 /***************************************************************************
3843 ***************************************************************************/
3844
3845 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
3846 {
3847         static int parm_num = -1;
3848         service *s;
3849
3850         if ( parm_num == -1 )
3851                 parm_num = map_parameter( "printing" );
3852
3853         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3854
3855         if ( snum < 0 )
3856                 s = &sDefault;
3857         else
3858                 s = ServicePtrs[snum];
3859
3860         init_printer_values( s );
3861
3862         return True;
3863 }
3864
3865
3866 /***************************************************************************
3867  Initialise a copymap.
3868 ***************************************************************************/
3869
3870 static void init_copymap(service * pservice)
3871 {
3872         int i;
3873         if (pservice->copymap) {
3874                 bitmap_free(pservice->copymap);
3875         }
3876         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
3877         if (!pservice->copymap)
3878                 DEBUG(0,
3879                       ("Couldn't allocate copymap!! (size %d)\n",
3880                        (int)NUMPARAMETERS));
3881         else
3882                 for (i = 0; i < NUMPARAMETERS; i++)
3883                         bitmap_set(pservice->copymap, i);
3884 }
3885
3886 /***************************************************************************
3887  Return the local pointer to a parameter given the service number and the 
3888  pointer into the default structure.
3889 ***************************************************************************/
3890
3891 void *lp_local_ptr(int snum, void *ptr)
3892 {
3893         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3894 }
3895
3896 /***************************************************************************
3897  Process a parameter for a particular service number. If snum < 0
3898  then assume we are in the globals.
3899 ***************************************************************************/
3900
3901 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3902 {
3903         int parmnum, i, slen;
3904         void *parm_ptr = NULL;  /* where we are going to store the result */
3905         void *def_ptr = NULL;
3906         char *param_key = NULL;
3907         char *sep;
3908         param_opt_struct *paramo, *data;
3909         bool not_added;
3910
3911         parmnum = map_parameter(pszParmName);
3912
3913         if (parmnum < 0) {
3914                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3915                         TALLOC_CTX *frame = talloc_stackframe();
3916
3917                         *sep = '\0';
3918                         param_key = talloc_asprintf(frame, "%s:", pszParmName);
3919                         if (!param_key) {
3920                                 TALLOC_FREE(frame);
3921                                 return false;
3922                         }
3923                         slen = strlen(param_key);
3924                         param_key = talloc_asprintf_append(param_key, sep+1);
3925                         if (!param_key) {
3926                                 TALLOC_FREE(frame);
3927                                 return false;
3928                         }
3929                         trim_char(param_key+slen, ' ', ' ');
3930                         not_added = True;
3931                         data = (snum < 0) ? Globals.param_opt :
3932                                 ServicePtrs[snum]->param_opt;
3933                         /* Traverse destination */
3934                         while (data) {
3935                                 /* If we already have same option, override it */
3936                                 if (strcmp(data->key, param_key) == 0) {
3937                                         string_free(&data->value);
3938                                         TALLOC_FREE(data->list);
3939                                         data->value = SMB_STRDUP(pszParmValue);
3940                                         not_added = False;
3941                                         break;
3942                                 }
3943                                 data = data->next;
3944                         }
3945                         if (not_added) {
3946                                 paramo = SMB_XMALLOC_P(param_opt_struct);
3947                                 paramo->key = SMB_STRDUP(param_key);
3948                                 paramo->value = SMB_STRDUP(pszParmValue);
3949                                 paramo->list = NULL;
3950                                 if (snum < 0) {
3951                                         DLIST_ADD(Globals.param_opt, paramo);
3952                                 } else {
3953                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3954                                 }
3955                         }
3956
3957                         *sep = ':';
3958                         TALLOC_FREE(frame);
3959                         return (True);
3960                 }
3961                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3962                 return (True);
3963         }
3964
3965         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3966                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3967                           pszParmName));
3968         }
3969
3970         def_ptr = parm_table[parmnum].ptr;
3971
3972         /* we might point at a service, the default service or a global */
3973         if (snum < 0) {
3974                 parm_ptr = def_ptr;
3975         } else {
3976                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3977                         DEBUG(0,
3978                               ("Global parameter %s found in service section!\n",
3979                                pszParmName));
3980                         return (True);
3981                 }
3982                 parm_ptr =
3983                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3984                                                             &sDefault);
3985         }
3986
3987         if (snum >= 0) {
3988                 if (!ServicePtrs[snum]->copymap)
3989                         init_copymap(ServicePtrs[snum]);
3990
3991                 /* this handles the aliases - set the copymap for other entries with
3992                    the same data pointer */
3993                 for (i = 0; parm_table[i].label; i++)
3994                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3995                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
3996         }
3997
3998         /* if it is a special case then go ahead */
3999         if (parm_table[parmnum].special) {
4000                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
4001                 return (True);
4002         }
4003
4004         /* now switch on the type of variable it is */
4005         switch (parm_table[parmnum].type)
4006         {
4007                 case P_BOOL:
4008                         *(bool *)parm_ptr = lp_bool(pszParmValue);
4009                         break;
4010
4011                 case P_BOOLREV:
4012                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
4013                         break;
4014
4015                 case P_INTEGER:
4016                         *(int *)parm_ptr = lp_int(pszParmValue);
4017                         break;
4018
4019                 case P_CHAR:
4020                         *(char *)parm_ptr = *pszParmValue;
4021                         break;
4022
4023                 case P_OCTAL:
4024                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
4025                         if ( i != 1 ) {
4026                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
4027                         }
4028                         break;
4029
4030                 case P_LIST:
4031                         TALLOC_FREE(*((char ***)parm_ptr));
4032                         *(char ***)parm_ptr = str_list_make(
4033                                 NULL, pszParmValue, NULL);
4034                         break;
4035
4036                 case P_STRING:
4037                         string_set((char **)parm_ptr, pszParmValue);
4038                         break;
4039
4040                 case P_USTRING:
4041                         string_set((char **)parm_ptr, pszParmValue);
4042                         strupper_m(*(char **)parm_ptr);
4043                         break;
4044
4045                 case P_ENUM:
4046                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
4047                         break;
4048                 case P_SEP:
4049                         break;
4050         }
4051
4052         return (True);
4053 }
4054
4055 /***************************************************************************
4056  Process a parameter.
4057 ***************************************************************************/
4058
4059 static bool do_parameter(const char *pszParmName, const char *pszParmValue)
4060 {
4061         if (!bInGlobalSection && bGlobalOnly)
4062                 return (True);
4063
4064         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
4065
4066         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
4067                                 pszParmName, pszParmValue));
4068 }
4069
4070 /***************************************************************************
4071  Print a parameter of the specified type.
4072 ***************************************************************************/
4073
4074 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
4075 {
4076         int i;
4077         switch (p->type)
4078         {
4079                 case P_ENUM:
4080                         for (i = 0; p->enum_list[i].name; i++) {
4081                                 if (*(int *)ptr == p->enum_list[i].value) {
4082                                         fprintf(f, "%s",
4083                                                 p->enum_list[i].name);
4084                                         break;
4085                                 }
4086                         }
4087                         break;
4088
4089                 case P_BOOL:
4090                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
4091                         break;
4092
4093                 case P_BOOLREV:
4094                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
4095                         break;
4096
4097                 case P_INTEGER:
4098                         fprintf(f, "%d", *(int *)ptr);
4099                         break;
4100
4101                 case P_CHAR:
4102                         fprintf(f, "%c", *(char *)ptr);
4103                         break;
4104
4105                 case P_OCTAL: {
4106                         char *o = octal_string(*(int *)ptr);
4107                         fprintf(f, "%s", o);
4108                         TALLOC_FREE(o);
4109                         break;
4110                 }
4111
4112                 case P_LIST:
4113                         if ((char ***)ptr && *(char ***)ptr) {
4114                                 char **list = *(char ***)ptr;
4115                                 for (; *list; list++) {
4116                                         /* surround strings with whitespace in double quotes */
4117                                         if ( strchr_m( *list, ' ' ) )
4118                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
4119                                         else
4120                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
4121                                 }
4122                         }
4123                         break;
4124
4125                 case P_STRING:
4126                 case P_USTRING:
4127                         if (*(char **)ptr) {
4128                                 fprintf(f, "%s", *(char **)ptr);
4129                         }
4130                         break;
4131                 case P_SEP:
4132                         break;
4133         }
4134 }
4135
4136 /***************************************************************************
4137  Check if two parameters are equal.
4138 ***************************************************************************/
4139
4140 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
4141 {
4142         switch (type) {
4143                 case P_BOOL:
4144                 case P_BOOLREV:
4145                         return (*((bool *)ptr1) == *((bool *)ptr2));
4146
4147                 case P_INTEGER:
4148                 case P_ENUM:
4149                 case P_OCTAL:
4150                         return (*((int *)ptr1) == *((int *)ptr2));
4151
4152                 case P_CHAR:
4153                         return (*((char *)ptr1) == *((char *)ptr2));
4154
4155                 case P_LIST:
4156                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
4157
4158                 case P_STRING:
4159                 case P_USTRING:
4160                 {
4161                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
4162                         if (p1 && !*p1)
4163                                 p1 = NULL;
4164                         if (p2 && !*p2)
4165                                 p2 = NULL;
4166                         return (p1 == p2 || strequal(p1, p2));
4167                 }
4168                 case P_SEP:
4169                         break;
4170         }
4171         return (False);
4172 }
4173
4174 /***************************************************************************
4175  Initialize any local varients in the sDefault table.
4176 ***************************************************************************/
4177
4178 void init_locals(void)
4179 {
4180         /* None as yet. */
4181 }
4182
4183 /***************************************************************************
4184  Process a new section (service). At this stage all sections are services.
4185  Later we'll have special sections that permit server parameters to be set.
4186  Returns True on success, False on failure. 
4187 ***************************************************************************/
4188
4189 static bool do_section(const char *pszSectionName)
4190 {
4191         bool bRetval;
4192         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
4193                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
4194         bRetval = False;
4195
4196         /* if we were in a global section then do the local inits */
4197         if (bInGlobalSection && !isglobal)
4198                 init_locals();
4199
4200         /* if we've just struck a global section, note the fact. */
4201         bInGlobalSection = isglobal;
4202
4203         /* check for multiple global sections */
4204         if (bInGlobalSection) {
4205                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
4206                 return (True);
4207         }
4208
4209         if (!bInGlobalSection && bGlobalOnly)
4210                 return (True);
4211
4212         /* if we have a current service, tidy it up before moving on */
4213         bRetval = True;
4214
4215         if (iServiceIndex >= 0)
4216                 bRetval = service_ok(iServiceIndex);
4217
4218         /* if all is still well, move to the next record in the services array */
4219         if (bRetval) {
4220                 /* We put this here to avoid an odd message order if messages are */
4221                 /* issued by the post-processing of a previous section. */
4222                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
4223
4224                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
4225                     < 0) {
4226                         DEBUG(0, ("Failed to add a new service\n"));
4227                         return (False);
4228                 }
4229         }
4230
4231         return (bRetval);
4232 }
4233
4234
4235 /***************************************************************************
4236  Determine if a partcular base parameter is currentl set to the default value.
4237 ***************************************************************************/
4238
4239 static bool is_default(int i)
4240 {
4241         if (!defaults_saved)
4242                 return False;
4243         switch (parm_table[i].type) {
4244                 case P_LIST:
4245                         return str_list_compare (parm_table[i].def.lvalue, 
4246                                                 *(char ***)parm_table[i].ptr);
4247                 case P_STRING:
4248                 case P_USTRING:
4249                         return strequal(parm_table[i].def.svalue,
4250                                         *(char **)parm_table[i].ptr);
4251                 case P_BOOL:
4252                 case P_BOOLREV:
4253                         return parm_table[i].def.bvalue ==
4254                                 *(bool *)parm_table[i].ptr;
4255                 case P_CHAR:
4256                         return parm_table[i].def.cvalue ==
4257                                 *(char *)parm_table[i].ptr;
4258                 case P_INTEGER:
4259                 case P_OCTAL:
4260                 case P_ENUM:
4261                         return parm_table[i].def.ivalue ==
4262                                 *(int *)parm_table[i].ptr;
4263                 case P_SEP:
4264                         break;
4265         }
4266         return False;
4267 }
4268
4269 /***************************************************************************
4270 Display the contents of the global structure.
4271 ***************************************************************************/
4272
4273 static void dump_globals(FILE *f)
4274 {
4275         int i;
4276         param_opt_struct *data;
4277         
4278         fprintf(f, "[global]\n");
4279
4280         for (i = 0; parm_table[i].label; i++)
4281                 if (parm_table[i].p_class == P_GLOBAL &&
4282                     parm_table[i].ptr &&
4283                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
4284                         if (defaults_saved && is_default(i))
4285                                 continue;
4286                         fprintf(f, "\t%s = ", parm_table[i].label);
4287                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
4288                         fprintf(f, "\n");
4289         }
4290         if (Globals.param_opt != NULL) {
4291                 data = Globals.param_opt;
4292                 while(data) {
4293                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4294                         data = data->next;
4295                 }
4296         }
4297
4298 }
4299
4300 /***************************************************************************
4301  Return True if a local parameter is currently set to the global default.
4302 ***************************************************************************/
4303
4304 bool lp_is_default(int snum, struct parm_struct *parm)
4305 {
4306         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
4307
4308         return equal_parameter(parm->type,
4309                                ((char *)ServicePtrs[snum]) + pdiff,
4310                                ((char *)&sDefault) + pdiff);
4311 }
4312
4313 /***************************************************************************
4314  Display the contents of a single services record.
4315 ***************************************************************************/
4316
4317 static void dump_a_service(service * pService, FILE * f)
4318 {
4319         int i;
4320         param_opt_struct *data;
4321         
4322         if (pService != &sDefault)
4323                 fprintf(f, "[%s]\n", pService->szService);
4324
4325         for (i = 0; parm_table[i].label; i++) {
4326
4327                 if (parm_table[i].p_class == P_LOCAL &&
4328                     parm_table[i].ptr &&
4329                     (*parm_table[i].label != '-') &&
4330                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4331                 {
4332                 
4333                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
4334
4335                         if (pService == &sDefault) {
4336                                 if (defaults_saved && is_default(i))
4337                                         continue;
4338                         } else {
4339                                 if (equal_parameter(parm_table[i].type,
4340                                                     ((char *)pService) +
4341                                                     pdiff,
4342                                                     ((char *)&sDefault) +
4343                                                     pdiff))
4344                                         continue;
4345                         }
4346
4347                         fprintf(f, "\t%s = ", parm_table[i].label);
4348                         print_parameter(&parm_table[i],
4349                                         ((char *)pService) + pdiff, f);
4350                         fprintf(f, "\n");
4351                 }
4352         }
4353
4354                 if (pService->param_opt != NULL) {
4355                         data = pService->param_opt;
4356                         while(data) {
4357                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
4358                                 data = data->next;
4359                         }
4360                 }
4361 }
4362
4363 /***************************************************************************
4364  Display the contents of a parameter of a single services record.
4365 ***************************************************************************/
4366
4367 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
4368 {
4369         int i;
4370         bool result = False;
4371         parm_class p_class;
4372         unsigned flag = 0;
4373         fstring local_parm_name;
4374         char *parm_opt;
4375         const char *parm_opt_value;
4376
4377         /* check for parametrical option */
4378         fstrcpy( local_parm_name, parm_name);
4379         parm_opt = strchr( local_parm_name, ':');
4380
4381         if (parm_opt) {
4382                 *parm_opt = '\0';
4383                 parm_opt++;
4384                 if (strlen(parm_opt)) {
4385                         parm_opt_value = lp_parm_const_string( snum,
4386                                 local_parm_name, parm_opt, NULL);
4387                         if (parm_opt_value) {
4388                                 printf( "%s\n", parm_opt_value);
4389                                 result = True;
4390                         }
4391                 }
4392                 return result;
4393         }
4394
4395         /* check for a key and print the value */
4396         if (isGlobal) {
4397                 p_class = P_GLOBAL;
4398                 flag = FLAG_GLOBAL;
4399         } else
4400                 p_class = P_LOCAL;
4401
4402         for (i = 0; parm_table[i].label; i++) {
4403                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
4404                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
4405                     parm_table[i].ptr &&
4406                     (*parm_table[i].label != '-') &&
4407                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4408                 {
4409                         void *ptr;
4410
4411                         if (isGlobal) {
4412                                 ptr = parm_table[i].ptr;
4413                         } else {
4414                                 service * pService = ServicePtrs[snum];
4415                                 ptr = ((char *)pService) +
4416                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
4417                         }
4418
4419                         print_parameter(&parm_table[i],
4420                                         ptr, f);
4421                         fprintf(f, "\n");
4422                         result = True;
4423                         break;
4424                 }
4425         }
4426
4427         return result;
4428 }
4429
4430 /***************************************************************************
4431  Return info about the requested parameter (given as a string).
4432  Return NULL when the string is not a valid parameter name.
4433 ***************************************************************************/
4434
4435 struct parm_struct *lp_get_parameter(const char *param_name)
4436 {
4437         int num = map_parameter(param_name);
4438
4439         if (num < 0) {
4440                 return NULL;
4441         }
4442
4443         return &parm_table[num];
4444 }
4445
4446 /***************************************************************************
4447  Return info about the next parameter in a service.
4448  snum==GLOBAL_SECTION_SNUM gives the globals.
4449  Return NULL when out of parameters.
4450 ***************************************************************************/
4451
4452 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4453 {
4454         if (snum < 0) {
4455                 /* do the globals */
4456                 for (; parm_table[*i].label; (*i)++) {
4457                         if (parm_table[*i].p_class == P_SEPARATOR)
4458                                 return &parm_table[(*i)++];
4459
4460                         if (!parm_table[*i].ptr
4461                             || (*parm_table[*i].label == '-'))
4462                                 continue;
4463
4464                         if ((*i) > 0
4465                             && (parm_table[*i].ptr ==
4466                                 parm_table[(*i) - 1].ptr))
4467                                 continue;
4468                         
4469                         if (is_default(*i) && !allparameters)
4470                                 continue;
4471
4472                         return &parm_table[(*i)++];
4473                 }
4474         } else {
4475                 service *pService = ServicePtrs[snum];
4476
4477                 for (; parm_table[*i].label; (*i)++) {
4478                         if (parm_table[*i].p_class == P_SEPARATOR)
4479                                 return &parm_table[(*i)++];
4480
4481                         if (parm_table[*i].p_class == P_LOCAL &&
4482                             parm_table[*i].ptr &&
4483                             (*parm_table[*i].label != '-') &&
4484                             ((*i) == 0 ||
4485                              (parm_table[*i].ptr !=
4486                               parm_table[(*i) - 1].ptr)))
4487                         {
4488                                 int pdiff =
4489                                         PTR_DIFF(parm_table[*i].ptr,
4490                                                  &sDefault);
4491
4492                                 if (allparameters ||
4493                                     !equal_parameter(parm_table[*i].type,
4494                                                      ((char *)pService) +
4495                                                      pdiff,
4496                                                      ((char *)&sDefault) +
4497                                                      pdiff))
4498                                 {
4499                                         return &parm_table[(*i)++];
4500                                 }
4501                         }
4502                 }
4503         }
4504
4505         return NULL;
4506 }
4507
4508
4509 #if 0
4510 /***************************************************************************
4511  Display the contents of a single copy structure.
4512 ***************************************************************************/
4513 static void dump_copy_map(bool *pcopymap)
4514 {
4515         int i;
4516         if (!pcopymap)
4517                 return;
4518
4519         printf("\n\tNon-Copied parameters:\n");
4520
4521         for (i = 0; parm_table[i].label; i++)
4522                 if (parm_table[i].p_class == P_LOCAL &&
4523                     parm_table[i].ptr && !pcopymap[i] &&
4524                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4525                 {
4526                         printf("\t\t%s\n", parm_table[i].label);
4527                 }
4528 }
4529 #endif
4530
4531 /***************************************************************************
4532  Return TRUE if the passed service number is within range.
4533 ***************************************************************************/
4534
4535 bool lp_snum_ok(int iService)
4536 {
4537         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4538 }
4539
4540 /***************************************************************************
4541  Auto-load some home services.
4542 ***************************************************************************/
4543
4544 static void lp_add_auto_services(char *str)
4545 {
4546         char *s;
4547         char *p;
4548         int homes;
4549         char *saveptr;
4550
4551         if (!str)
4552                 return;
4553
4554         s = SMB_STRDUP(str);
4555         if (!s)
4556                 return;
4557
4558         homes = lp_servicenumber(HOMES_NAME);
4559
4560         for (p = strtok_r(s, LIST_SEP, &saveptr); p;
4561              p = strtok_r(NULL, LIST_SEP, &saveptr)) {
4562                 char *home;
4563
4564                 if (lp_servicenumber(p) >= 0)
4565                         continue;
4566
4567                 home = get_user_home_dir(talloc_tos(), p);
4568
4569                 if (home && homes >= 0)
4570                         lp_add_home(p, homes, p, home);
4571
4572                 TALLOC_FREE(home);
4573         }
4574         SAFE_FREE(s);
4575 }
4576
4577 /***************************************************************************
4578  Auto-load one printer.
4579 ***************************************************************************/
4580
4581 void lp_add_one_printer(char *name, char *comment)
4582 {
4583         int printers = lp_servicenumber(PRINTERS_NAME);
4584         int i;
4585
4586         if (lp_servicenumber(name) < 0) {
4587                 lp_add_printer(name, printers);
4588                 if ((i = lp_servicenumber(name)) >= 0) {
4589                         string_set(&ServicePtrs[i]->comment, comment);
4590                         ServicePtrs[i]->autoloaded = True;
4591                 }
4592         }
4593 }
4594
4595 /***************************************************************************
4596  Have we loaded a services file yet?
4597 ***************************************************************************/
4598
4599 bool lp_loaded(void)
4600 {
4601         return (bLoaded);
4602 }
4603
4604 /***************************************************************************
4605  Unload unused services.
4606 ***************************************************************************/
4607
4608 void lp_killunused(bool (*snumused) (int))
4609 {
4610         int i;
4611         for (i = 0; i < iNumServices; i++) {
4612                 if (!VALID(i))
4613                         continue;
4614
4615                 /* don't kill autoloaded or usershare services */
4616                 if ( ServicePtrs[i]->autoloaded ||
4617                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4618                         continue;
4619                 }
4620
4621                 if (!snumused || !snumused(i)) {
4622                         free_service_byindex(i);
4623                 }
4624         }
4625 }
4626
4627 /***************************************************************************
4628  Unload a service.
4629 ***************************************************************************/
4630
4631 void lp_killservice(int iServiceIn)
4632 {
4633         if (VALID(iServiceIn)) {
4634                 free_service_byindex(iServiceIn);
4635         }
4636 }
4637
4638 /***************************************************************************
4639  Save the curent values of all global and sDefault parameters into the 
4640  defaults union. This allows swat and testparm to show only the
4641  changed (ie. non-default) parameters.
4642 ***************************************************************************/
4643
4644 static void lp_save_defaults(void)
4645 {
4646         int i;
4647         for (i = 0; parm_table[i].label; i++) {
4648                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4649                         continue;
4650                 switch (parm_table[i].type) {
4651                         case P_LIST:
4652                                 str_list_copy(
4653                                         NULL, &(parm_table[i].def.lvalue),
4654                                         *(const char ***)parm_table[i].ptr);
4655                                 break;
4656                         case P_STRING:
4657                         case P_USTRING:
4658                                 if (parm_table[i].ptr) {
4659                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4660                                 } else {
4661                                         parm_table[i].def.svalue = NULL;
4662                                 }
4663                                 break;
4664                         case P_BOOL:
4665                         case P_BOOLREV:
4666                                 parm_table[i].def.bvalue =
4667                                         *(bool *)parm_table[i].ptr;
4668                                 break;
4669                         case P_CHAR:
4670                                 parm_table[i].def.cvalue =
4671                                         *(char *)parm_table[i].ptr;
4672                                 break;
4673                         case P_INTEGER:
4674                         case P_OCTAL:
4675                         case P_ENUM:
4676                                 parm_table[i].def.ivalue =
4677                                         *(int *)parm_table[i].ptr;
4678                                 break;
4679                         case P_SEP:
4680                                 break;
4681                 }
4682         }
4683         defaults_saved = True;
4684 }
4685
4686 /*******************************************************************
4687  Set the server type we will announce as via nmbd.
4688 ********************************************************************/
4689
4690 static const struct srv_role_tab {
4691         uint32 role;
4692         const char *role_str;
4693 } srv_role_tab [] = {
4694         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4695         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4696         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4697         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4698         { 0, NULL }
4699 };
4700
4701 const char* server_role_str(uint32 role)
4702 {
4703         int i = 0;
4704         for (i=0; srv_role_tab[i].role_str; i++) {
4705                 if (role == srv_role_tab[i].role) {
4706                         return srv_role_tab[i].role_str;
4707                 }
4708         }
4709         return NULL;
4710 }
4711
4712 static void set_server_role(void)
4713 {
4714         server_role = ROLE_STANDALONE;
4715
4716         switch (lp_security()) {
4717                 case SEC_SHARE:
4718                         if (lp_domain_logons())
4719                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4720                         break;
4721                 case SEC_SERVER:
4722                         if (lp_domain_logons())
4723                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4724                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4725                         server_role = ROLE_STANDALONE;
4726                         break;
4727                 case SEC_DOMAIN:
4728                         if (lp_domain_logons()) {
4729                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4730                                 server_role = ROLE_DOMAIN_BDC;
4731                                 break;
4732                         }
4733                         server_role = ROLE_DOMAIN_MEMBER;
4734                         break;
4735                 case SEC_ADS:
4736                         if (lp_domain_logons()) {
4737                                 server_role = ROLE_DOMAIN_PDC;
4738                                 break;
4739                         }
4740                         server_role = ROLE_DOMAIN_MEMBER;
4741                         break;
4742                 case SEC_USER:
4743                         if (lp_domain_logons()) {
4744
4745                                 if (Globals.iDomainMaster) /* auto or yes */ 
4746                                         server_role = ROLE_DOMAIN_PDC;
4747                                 else
4748                                         server_role = ROLE_DOMAIN_BDC;
4749                         }
4750                         break;
4751                 default:
4752                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4753                         break;
4754         }
4755
4756         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4757 }
4758
4759 /***********************************************************
4760  If we should send plaintext/LANMAN passwords in the clinet
4761 ************************************************************/
4762
4763 static void set_allowed_client_auth(void)
4764 {
4765         if (Globals.bClientNTLMv2Auth) {
4766                 Globals.bClientLanManAuth = False;
4767         }
4768         if (!Globals.bClientLanManAuth) {
4769                 Globals.bClientPlaintextAuth = False;
4770         }
4771 }
4772
4773 /***************************************************************************
4774  JRA.
4775  The following code allows smbd to read a user defined share file.
4776  Yes, this is my intent. Yes, I'm comfortable with that...
4777
4778  THE FOLLOWING IS SECURITY CRITICAL CODE.
4779
4780  It washes your clothes, it cleans your house, it guards you while you sleep...
4781  Do not f%^k with it....
4782 ***************************************************************************/
4783
4784 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4785
4786 /***************************************************************************
4787  Check allowed stat state of a usershare file.
4788  Ensure we print out who is dicking with us so the admin can
4789  get their sorry ass fired.
4790 ***************************************************************************/
4791
4792 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4793 {
4794         if (!S_ISREG(psbuf->st_mode)) {
4795                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4796                         "not a regular file\n",
4797                         fname, (unsigned int)psbuf->st_uid ));
4798                 return False;
4799         }
4800
4801         /* Ensure this doesn't have the other write bit set. */
4802         if (psbuf->st_mode & S_IWOTH) {
4803                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4804                         "public write. Refusing to allow as a usershare file.\n",
4805                         fname, (unsigned int)psbuf->st_uid ));
4806                 return False;
4807         }
4808
4809         /* Should be 10k or less. */
4810         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4811                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4812                         "too large (%u) to be a user share file.\n",
4813                         fname, (unsigned int)psbuf->st_uid,
4814                         (unsigned int)psbuf->st_size ));
4815                 return False;
4816         }
4817
4818         return True;
4819 }
4820
4821 /***************************************************************************
4822  Parse the contents of a usershare file.
4823 ***************************************************************************/
4824
4825 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4826                         SMB_STRUCT_STAT *psbuf,
4827                         const char *servicename,
4828                         int snum,
4829                         char **lines,
4830                         int numlines,
4831                         char **pp_sharepath,
4832                         char **pp_comment,
4833                         SEC_DESC **ppsd,
4834                         bool *pallow_guest)
4835 {
4836         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4837         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4838         int us_vers;
4839         SMB_STRUCT_DIR *dp;
4840         SMB_STRUCT_STAT sbuf;
4841         char *sharepath = NULL;
4842         char *comment = NULL;
4843
4844         *pp_sharepath = NULL;
4845         *pp_comment = NULL;
4846
4847         *pallow_guest = False;
4848
4849         if (numlines < 4) {
4850                 return USERSHARE_MALFORMED_FILE;
4851         }
4852
4853         if (strcmp(lines[0], "#VERSION 1") == 0) {
4854                 us_vers = 1;
4855         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4856                 us_vers = 2;
4857                 if (numlines < 5) {
4858                         return USERSHARE_MALFORMED_FILE;
4859                 }
4860         } else {
4861                 return USERSHARE_BAD_VERSION;
4862         }
4863
4864         if (strncmp(lines[1], "path=", 5) != 0) {
4865                 return USERSHARE_MALFORMED_PATH;
4866         }
4867
4868         sharepath = talloc_strdup(ctx, &lines[1][5]);
4869         if (!sharepath) {
4870                 return USERSHARE_POSIX_ERR;
4871         }
4872         trim_string(sharepath, " ", " ");
4873
4874         if (strncmp(lines[2], "comment=", 8) != 0) {
4875                 return USERSHARE_MALFORMED_COMMENT_DEF;
4876         }
4877
4878         comment = talloc_strdup(ctx, &lines[2][8]);
4879         if (!comment) {
4880                 return USERSHARE_POSIX_ERR;
4881         }
4882         trim_string(comment, " ", " ");
4883         trim_char(comment, '"', '"');
4884
4885         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4886                 return USERSHARE_MALFORMED_ACL_DEF;
4887         }
4888
4889         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4890                 return USERSHARE_ACL_ERR;
4891         }
4892
4893         if (us_vers == 2) {
4894                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4895                         return USERSHARE_MALFORMED_ACL_DEF;
4896                 }
4897                 if (lines[4][9] == 'y') {
4898                         *pallow_guest = True;
4899                 }
4900         }
4901
4902         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4903                 /* Path didn't change, no checks needed. */
4904                 *pp_sharepath = sharepath;
4905                 *pp_comment = comment;
4906                 return USERSHARE_OK;
4907         }
4908
4909         /* The path *must* be absolute. */
4910         if (sharepath[0] != '/') {
4911                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4912                         servicename, sharepath));
4913                 return USERSHARE_PATH_NOT_ABSOLUTE;
4914         }
4915
4916         /* If there is a usershare prefix deny list ensure one of these paths
4917            doesn't match the start of the user given path. */
4918         if (prefixdenylist) {
4919                 int i;
4920                 for ( i=0; prefixdenylist[i]; i++ ) {
4921                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4922                                 servicename, i, prefixdenylist[i], sharepath ));
4923                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4924                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4925                                         "usershare prefix deny list entries.\n",
4926                                         servicename, sharepath));
4927                                 return USERSHARE_PATH_IS_DENIED;
4928                         }
4929                 }
4930         }
4931
4932         /* If there is a usershare prefix allow list ensure one of these paths
4933            does match the start of the user given path. */
4934
4935         if (prefixallowlist) {
4936                 int i;
4937                 for ( i=0; prefixallowlist[i]; i++ ) {
4938                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4939                                 servicename, i, prefixallowlist[i], sharepath ));
4940                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4941                                 break;
4942                         }
4943                 }
4944                 if (prefixallowlist[i] == NULL) {
4945                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4946                                 "usershare prefix allow list entries.\n",
4947                                 servicename, sharepath));
4948                         return USERSHARE_PATH_NOT_ALLOWED;
4949                 }
4950         }
4951
4952         /* Ensure this is pointing to a directory. */
4953         dp = sys_opendir(sharepath);
4954
4955         if (!dp) {
4956                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4957                         servicename, sharepath));
4958                 return USERSHARE_PATH_NOT_DIRECTORY;
4959         }
4960
4961         /* Ensure the owner of the usershare file has permission to share
4962            this directory. */
4963
4964         if (sys_stat(sharepath, &sbuf) == -1) {
4965                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4966                         servicename, sharepath, strerror(errno) ));
4967                 sys_closedir(dp);
4968                 return USERSHARE_POSIX_ERR;
4969         }
4970
4971         sys_closedir(dp);
4972
4973         if (!S_ISDIR(sbuf.st_mode)) {
4974                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4975                         servicename, sharepath ));
4976                 return USERSHARE_PATH_NOT_DIRECTORY;
4977         }
4978
4979         /* Check if sharing is restricted to owner-only. */
4980         /* psbuf is the stat of the usershare definition file,
4981            sbuf is the stat of the target directory to be shared. */
4982
4983         if (lp_usershare_owner_only()) {
4984                 /* root can share anything. */
4985                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4986                         return USERSHARE_PATH_NOT_ALLOWED;
4987                 }
4988         }
4989
4990         *pp_sharepath = sharepath;
4991         *pp_comment = comment;
4992         return USERSHARE_OK;
4993 }
4994
4995 /***************************************************************************
4996  Deal with a usershare file.
4997  Returns:
4998         >= 0 - snum
4999         -1 - Bad name, invalid contents.
5000            - service name already existed and not a usershare, problem
5001             with permissions to share directory etc.
5002 ***************************************************************************/
5003
5004 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
5005 {
5006         SMB_STRUCT_STAT sbuf;
5007         SMB_STRUCT_STAT lsbuf;
5008         char *fname = NULL;
5009         char *sharepath = NULL;
5010         char *comment = NULL;
5011         fstring service_name;
5012         char **lines = NULL;
5013         int numlines = 0;
5014         int fd = -1;
5015         int iService = -1;
5016         TALLOC_CTX *ctx = NULL;
5017         SEC_DESC *psd = NULL;
5018         bool guest_ok = False;
5019
5020         /* Ensure share name doesn't contain invalid characters. */
5021         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
5022                 DEBUG(0,("process_usershare_file: share name %s contains "
5023                         "invalid characters (any of %s)\n",
5024                         file_name, INVALID_SHARENAME_CHARS ));
5025                 return -1;
5026         }
5027
5028         fstrcpy(service_name, file_name);
5029
5030         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
5031         }
5032
5033         /* Minimize the race condition by doing an lstat before we
5034            open and fstat. Ensure this isn't a symlink link. */
5035
5036         if (sys_lstat(fname, &lsbuf) != 0) {
5037                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
5038                         fname, strerror(errno) ));
5039                 SAFE_FREE(fname);
5040                 return -1;
5041         }
5042
5043         /* This must be a regular file, not a symlink, directory or
5044            other strange filetype. */
5045         if (!check_usershare_stat(fname, &lsbuf)) {
5046                 SAFE_FREE(fname);
5047                 return -1;
5048         }
5049
5050         {
5051                 char *canon_name = canonicalize_servicename(service_name);
5052                 TDB_DATA data = dbwrap_fetch_bystring(
5053                         ServiceHash, canon_name, canon_name);
5054
5055                 iService = -1;
5056
5057                 if ((data.dptr != NULL) && (data.dsize == sizeof(iService))) {
5058                         iService = *(int *)data.dptr;
5059                 }
5060                 TALLOC_FREE(canon_name);
5061         }
5062
5063         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
5064                 /* Nothing changed - Mark valid and return. */
5065                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
5066                         service_name ));
5067                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
5068                 SAFE_FREE(fname);
5069                 return iService;
5070         }
5071
5072         /* Try and open the file read only - no symlinks allowed. */
5073 #ifdef O_NOFOLLOW
5074         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
5075 #else
5076         fd = sys_open(fname, O_RDONLY, 0);
5077 #endif
5078
5079         if (fd == -1) {
5080                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
5081                         fname, strerror(errno) ));
5082                 SAFE_FREE(fname);
5083                 return -1;
5084         }
5085
5086         /* Now fstat to be *SURE* it's a regular file. */
5087         if (sys_fstat(fd, &sbuf) != 0) {
5088                 close(fd);
5089                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
5090                         fname, strerror(errno) ));
5091                 SAFE_FREE(fname);
5092                 return -1;
5093         }
5094
5095         /* Is it the same dev/inode as was lstated ? */
5096         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
5097                 close(fd);
5098                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
5099                         "Symlink spoofing going on ?\n", fname ));
5100                 SAFE_FREE(fname);
5101                 return -1;
5102         }
5103
5104         /* This must be a regular file, not a symlink, directory or
5105            other strange filetype. */
5106         if (!check_usershare_stat(fname, &sbuf)) {
5107                 SAFE_FREE(fname);
5108                 return -1;
5109         }
5110
5111         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
5112
5113         close(fd);
5114         if (lines == NULL) {
5115                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
5116                         fname, (unsigned int)sbuf.st_uid ));
5117                 SAFE_FREE(fname);
5118                 return -1;
5119         }
5120
5121         SAFE_FREE(fname);
5122
5123         /* Should we allow printers to be shared... ? */
5124         ctx = talloc_init("usershare_sd_xctx");
5125         if (!ctx) {
5126                 file_lines_free(lines);
5127                 return 1;
5128         }
5129
5130         if (parse_usershare_file(ctx, &sbuf, service_name,
5131                         iService, lines, numlines, &sharepath,
5132                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
5133                 talloc_destroy(ctx);
5134                 file_lines_free(lines);
5135                 return -1;
5136         }
5137
5138         file_lines_free(lines);
5139
5140         /* Everything ok - add the service possibly using a template. */
5141         if (iService < 0) {
5142                 const service *sp = &sDefault;
5143                 if (snum_template != -1) {
5144                         sp = ServicePtrs[snum_template];
5145                 }
5146
5147                 if ((iService = add_a_service(sp, service_name)) < 0) {
5148                         DEBUG(0, ("process_usershare_file: Failed to add "
5149                                 "new service %s\n", service_name));
5150                         talloc_destroy(ctx);
5151                         return -1;
5152                 }
5153
5154                 /* Read only is controlled by usershare ACL below. */
5155                 ServicePtrs[iService]->bRead_only = False;
5156         }
5157
5158         /* Write the ACL of the new/modified share. */
5159         if (!set_share_security(service_name, psd)) {
5160                  DEBUG(0, ("process_usershare_file: Failed to set share "
5161                         "security for user share %s\n",
5162                         service_name ));
5163                 lp_remove_service(iService);
5164                 talloc_destroy(ctx);
5165                 return -1;
5166         }
5167
5168         /* If from a template it may be marked invalid. */
5169         ServicePtrs[iService]->valid = True;
5170
5171         /* Set the service as a valid usershare. */
5172         ServicePtrs[iService]->usershare = USERSHARE_VALID;
5173
5174         /* Set guest access. */
5175         if (lp_usershare_allow_guests()) {
5176                 ServicePtrs[iService]->bGuest_ok = guest_ok;
5177         }
5178
5179         /* And note when it was loaded. */
5180         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
5181         string_set(&ServicePtrs[iService]->szPath, sharepath);
5182         string_set(&ServicePtrs[iService]->comment, comment);
5183
5184         talloc_destroy(ctx);
5185
5186         return iService;
5187 }
5188
5189 /***************************************************************************
5190  Checks if a usershare entry has been modified since last load.
5191 ***************************************************************************/
5192
5193 static bool usershare_exists(int iService, time_t *last_mod)
5194 {
5195         SMB_STRUCT_STAT lsbuf;
5196         const char *usersharepath = Globals.szUsersharePath;
5197         char *fname;
5198
5199         if (asprintf(&fname, "%s/%s",
5200                                 usersharepath,
5201                                 ServicePtrs[iService]->szService) < 0) {
5202                 return false;
5203         }
5204
5205         if (sys_lstat(fname, &lsbuf) != 0) {
5206                 SAFE_FREE(fname);
5207                 return false;
5208         }
5209
5210         if (!S_ISREG(lsbuf.st_mode)) {
5211                 SAFE_FREE(fname);
5212                 return false;
5213         }
5214
5215         SAFE_FREE(fname);
5216         *last_mod = lsbuf.st_mtime;
5217         return true;
5218 }
5219
5220 /***************************************************************************
5221  Load a usershare service by name. Returns a valid servicenumber or -1.
5222 ***************************************************************************/
5223
5224 int load_usershare_service(const char *servicename)
5225 {
5226         SMB_STRUCT_STAT sbuf;
5227         const char *usersharepath = Globals.szUsersharePath;
5228         int max_user_shares = Globals.iUsershareMaxShares;
5229         int snum_template = -1;
5230
5231         if (*usersharepath == 0 ||  max_user_shares == 0) {
5232                 return -1;
5233         }
5234
5235         if (sys_stat(usersharepath, &sbuf) != 0) {
5236                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
5237                         usersharepath, strerror(errno) ));
5238                 return -1;
5239         }
5240
5241         if (!S_ISDIR(sbuf.st_mode)) {
5242                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
5243                         usersharepath ));
5244                 return -1;
5245         }
5246
5247         /*
5248          * This directory must be owned by root, and have the 't' bit set.
5249          * It also must not be writable by "other".
5250          */
5251
5252 #ifdef S_ISVTX
5253         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5254 #else
5255         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5256 #endif
5257                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
5258                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5259                         usersharepath ));
5260                 return -1;
5261         }
5262
5263         /* Ensure the template share exists if it's set. */
5264         if (Globals.szUsershareTemplateShare[0]) {
5265                 /* We can't use lp_servicenumber here as we are recommending that
5266                    template shares have -valid=False set. */
5267                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5268                         if (ServicePtrs[snum_template]->szService &&
5269                                         strequal(ServicePtrs[snum_template]->szService,
5270                                                 Globals.szUsershareTemplateShare)) {
5271                                 break;
5272                         }
5273                 }
5274
5275                 if (snum_template == -1) {
5276                         DEBUG(0,("load_usershare_service: usershare template share %s "
5277                                 "does not exist.\n",
5278                                 Globals.szUsershareTemplateShare ));
5279                         return -1;
5280                 }
5281         }
5282
5283         return process_usershare_file(usersharepath, servicename, snum_template);
5284 }
5285
5286 /***************************************************************************
5287  Load all user defined shares from the user share directory.
5288  We only do this if we're enumerating the share list.
5289  This is the function that can delete usershares that have
5290  been removed.
5291 ***************************************************************************/
5292
5293 int load_usershare_shares(void)
5294 {
5295         SMB_STRUCT_DIR *dp;
5296         SMB_STRUCT_STAT sbuf;
5297         SMB_STRUCT_DIRENT *de;
5298         int num_usershares = 0;
5299         int max_user_shares = Globals.iUsershareMaxShares;
5300         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
5301         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
5302         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
5303         int iService;
5304         int snum_template = -1;
5305         const char *usersharepath = Globals.szUsersharePath;
5306         int ret = lp_numservices();
5307
5308         if (max_user_shares == 0 || *usersharepath == '\0') {
5309                 return lp_numservices();
5310         }
5311
5312         if (sys_stat(usersharepath, &sbuf) != 0) {
5313                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
5314                         usersharepath, strerror(errno) ));
5315                 return ret;
5316         }
5317
5318         /*
5319          * This directory must be owned by root, and have the 't' bit set.
5320          * It also must not be writable by "other".
5321          */
5322
5323 #ifdef S_ISVTX
5324         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5325 #else
5326         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5327 #endif
5328                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
5329                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5330                         usersharepath ));
5331                 return ret;
5332         }
5333
5334         /* Ensure the template share exists if it's set. */
5335         if (Globals.szUsershareTemplateShare[0]) {
5336                 /* We can't use lp_servicenumber here as we are recommending that
5337                    template shares have -valid=False set. */
5338                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5339                         if (ServicePtrs[snum_template]->szService &&
5340                                         strequal(ServicePtrs[snum_template]->szService,
5341                                                 Globals.szUsershareTemplateShare)) {
5342                                 break;
5343                         }
5344                 }
5345
5346                 if (snum_template == -1) {
5347                         DEBUG(0,("load_usershare_shares: usershare template share %s "
5348                                 "does not exist.\n",
5349                                 Globals.szUsershareTemplateShare ));
5350                         return ret;
5351                 }
5352         }
5353
5354         /* Mark all existing usershares as pending delete. */
5355         for (iService = iNumServices - 1; iService >= 0; iService--) {
5356                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
5357                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
5358                 }
5359         }
5360
5361         dp = sys_opendir(usersharepath);
5362         if (!dp) {
5363                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
5364                         usersharepath, strerror(errno) ));
5365                 return ret;
5366         }
5367
5368         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
5369                         (de = sys_readdir(dp));
5370                         num_dir_entries++ ) {
5371                 int r;
5372                 const char *n = de->d_name;
5373
5374                 /* Ignore . and .. */
5375                 if (*n == '.') {
5376                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
5377                                 continue;
5378                         }
5379                 }
5380
5381                 if (n[0] == ':') {
5382                         /* Temporary file used when creating a share. */
5383                         num_tmp_dir_entries++;
5384                 }
5385
5386                 /* Allow 20% tmp entries. */
5387                 if (num_tmp_dir_entries > allowed_tmp_entries) {
5388                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
5389                                 "in directory %s\n",
5390                                 num_tmp_dir_entries, usersharepath));
5391                         break;
5392                 }
5393
5394                 r = process_usershare_file(usersharepath, n, snum_template);
5395                 if (r == 0) {
5396                         /* Update the services count. */
5397                         num_usershares++;
5398                         if (num_usershares >= max_user_shares) {
5399                                 DEBUG(0,("load_usershare_shares: max user shares reached "
5400                                         "on file %s in directory %s\n",
5401                                         n, usersharepath ));
5402                                 break;
5403                         }
5404                 } else if (r == -1) {
5405                         num_bad_dir_entries++;
5406                 }
5407
5408                 /* Allow 20% bad entries. */
5409                 if (num_bad_dir_entries > allowed_bad_entries) {
5410                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
5411                                 "in directory %s\n",
5412                                 num_bad_dir_entries, usersharepath));
5413                         break;
5414                 }
5415
5416                 /* Allow 20% bad entries. */
5417                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
5418                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
5419                         "in directory %s\n",
5420                         num_dir_entries, usersharepath));
5421                         break;
5422                 }
5423         }
5424
5425         sys_closedir(dp);
5426
5427         /* Sweep through and delete any non-refreshed usershares that are
5428            not currently in use. */
5429         for (iService = iNumServices - 1; iService >= 0; iService--) {
5430                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
5431                         if (conn_snum_used(iService)) {
5432                                 continue;
5433                         }
5434                         /* Remove from the share ACL db. */
5435                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
5436                                 lp_servicename(iService) ));
5437                         delete_share_security(lp_servicename(iService));
5438                         free_service_byindex(iService);
5439                 }
5440         }
5441
5442         return lp_numservices();
5443 }
5444
5445 /********************************************************
5446  Destroy global resources allocated in this file
5447 ********************************************************/
5448
5449 void gfree_loadparm(void)
5450 {
5451         struct file_lists *f;
5452         struct file_lists *next;
5453         int i;
5454
5455         /* Free the file lists */
5456
5457         f = file_lists;
5458         while( f ) {
5459                 next = f->next;
5460                 SAFE_FREE( f->name );
5461                 SAFE_FREE( f->subfname );
5462                 SAFE_FREE( f );
5463                 f = next;
5464         }
5465
5466         /* Free resources allocated to services */
5467
5468         for ( i = 0; i < iNumServices; i++ ) {
5469                 if ( VALID(i) ) {
5470                         free_service_byindex(i);
5471                 }
5472         }
5473
5474         SAFE_FREE( ServicePtrs );
5475         iNumServices = 0;
5476
5477         /* Now release all resources allocated to global
5478            parameters and the default service */
5479
5480         for (i = 0; parm_table[i].label; i++) 
5481         {
5482                 if ( parm_table[i].type == P_STRING 
5483                         || parm_table[i].type == P_USTRING ) 
5484                 {
5485                         string_free( (char**)parm_table[i].ptr );
5486                 }
5487                 else if (parm_table[i].type == P_LIST) {
5488                         TALLOC_FREE( *((char***)parm_table[i].ptr) );
5489                 }
5490         }
5491 }
5492
5493 /***************************************************************************
5494  Load the services array from the services file. Return True on success, 
5495  False on failure.
5496 ***************************************************************************/
5497
5498 bool lp_load(const char *pszFname,
5499              bool global_only,
5500              bool save_defaults,
5501              bool add_ipc,
5502              bool initialize_globals)
5503 {
5504         char *n2 = NULL;
5505         bool bRetval;
5506         param_opt_struct *data, *pdata;
5507
5508         bRetval = False;
5509
5510         DEBUG(3, ("lp_load: refreshing parameters\n"));
5511
5512         bInGlobalSection = True;
5513         bGlobalOnly = global_only;
5514
5515         init_globals(! initialize_globals);
5516         debug_init();
5517
5518         if (save_defaults) {
5519                 init_locals();
5520                 lp_save_defaults();
5521         }
5522
5523         if (Globals.param_opt != NULL) {
5524                 data = Globals.param_opt;
5525                 while (data) {
5526                         string_free(&data->key);
5527                         string_free(&data->value);
5528                         TALLOC_FREE(data->list);
5529                         pdata = data->next;
5530                         SAFE_FREE(data);
5531                         data = pdata;
5532                 }
5533                 Globals.param_opt = NULL;
5534         }
5535
5536         if (lp_config_backend() == CONFIG_BACKEND_FILE) {
5537                 n2 = alloc_sub_basic(get_current_username(),
5538                                         current_user_info.domain,
5539                                         pszFname);
5540                 if (!n2) {
5541                         smb_panic("lp_load: out of memory");
5542                 }
5543
5544                 add_to_file_list(pszFname, n2);
5545
5546                 /* We get sections first, so have to start 'behind' to make up */
5547                 iServiceIndex = -1;
5548                 bRetval = pm_process(n2, do_section, do_parameter);
5549                 SAFE_FREE(n2);
5550
5551                 /* finish up the last section */
5552                 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5553                 if (bRetval) {
5554                         if (iServiceIndex >= 0) {
5555                                 bRetval = service_ok(iServiceIndex);
5556                         }
5557                 }
5558
5559                 if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5560                         /*
5561                          * We need to use this extra global variable here to
5562                          * survive restart: init_globals usese this as a default
5563                          * for ConfigBackend. Otherwise, init_globals would
5564                          *  send us into an endless loop here.
5565                          */
5566                         config_backend = CONFIG_BACKEND_REGISTRY;
5567                         /* start over */
5568                         init_globals(false);
5569                         return lp_load(pszFname, global_only, save_defaults,
5570                                        add_ipc, initialize_globals);
5571                 }
5572         } else if (lp_config_backend() == CONFIG_BACKEND_REGISTRY) {
5573                 bRetval = process_registry_globals(do_parameter);
5574         } else {
5575                 DEBUG(0, ("Illegal config  backend given: %d\n",
5576                           lp_config_backend()));
5577                 bRetval = false;
5578         }
5579
5580         lp_add_auto_services(lp_auto_services());
5581
5582         if (add_ipc) {
5583                 /* When 'restrict anonymous = 2' guest connections to ipc$
5584                    are denied */
5585                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5586                 if ( lp_enable_asu_support() ) {
5587                         lp_add_ipc("ADMIN$", false);
5588                 }
5589         }
5590
5591         set_server_role();
5592         set_default_server_announce_type();
5593         set_allowed_client_auth();
5594
5595         bLoaded = True;
5596
5597         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5598         /* if bWINSsupport is true and we are in the client            */
5599         if (in_client && Globals.bWINSsupport) {
5600                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5601         }
5602
5603         init_iconv();
5604
5605         return (bRetval);
5606 }
5607
5608 /***************************************************************************
5609  Reset the max number of services.
5610 ***************************************************************************/
5611
5612 void lp_resetnumservices(void)
5613 {
5614         iNumServices = 0;
5615 }
5616
5617 /***************************************************************************
5618  Return the max number of services.
5619 ***************************************************************************/
5620
5621 int lp_numservices(void)
5622 {
5623         return (iNumServices);
5624 }
5625
5626 /***************************************************************************
5627 Display the contents of the services array in human-readable form.
5628 ***************************************************************************/
5629
5630 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5631 {
5632         int iService;
5633
5634         if (show_defaults)
5635                 defaults_saved = False;
5636
5637         dump_globals(f);
5638
5639         dump_a_service(&sDefault, f);
5640
5641         for (iService = 0; iService < maxtoprint; iService++) {
5642                 fprintf(f,"\n");
5643                 lp_dump_one(f, show_defaults, iService);
5644         }
5645 }
5646
5647 /***************************************************************************
5648 Display the contents of one service in human-readable form.
5649 ***************************************************************************/
5650
5651 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5652 {
5653         if (VALID(snum)) {
5654                 if (ServicePtrs[snum]->szService[0] == '\0')
5655                         return;
5656                 dump_a_service(ServicePtrs[snum], f);
5657         }
5658 }
5659
5660 /***************************************************************************
5661 Return the number of the service with the given name, or -1 if it doesn't
5662 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5663 getservicebyname()! This works ONLY if all services have been loaded, and
5664 does not copy the found service.
5665 ***************************************************************************/
5666
5667 int lp_servicenumber(const char *pszServiceName)
5668 {
5669         int iService;
5670         fstring serviceName;
5671         
5672         if (!pszServiceName) {
5673                 return GLOBAL_SECTION_SNUM;
5674         }
5675         
5676         for (iService = iNumServices - 1; iService >= 0; iService--) {
5677                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5678                         /*
5679                          * The substitution here is used to support %U is
5680                          * service names
5681                          */
5682                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5683                         standard_sub_basic(get_current_username(),
5684                                            current_user_info.domain,
5685                                            serviceName,sizeof(serviceName));
5686                         if (strequal(serviceName, pszServiceName)) {
5687                                 break;
5688                         }
5689                 }
5690         }
5691
5692         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5693                 time_t last_mod;
5694
5695                 if (!usershare_exists(iService, &last_mod)) {
5696                         /* Remove the share security tdb entry for it. */
5697                         delete_share_security(lp_servicename(iService));
5698                         /* Remove it from the array. */
5699                         free_service_byindex(iService);
5700                         /* Doesn't exist anymore. */
5701                         return GLOBAL_SECTION_SNUM;
5702                 }
5703
5704                 /* Has it been modified ? If so delete and reload. */
5705                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5706                         /* Remove it from the array. */
5707                         free_service_byindex(iService);
5708                         /* and now reload it. */
5709                         iService = load_usershare_service(pszServiceName);
5710                 }
5711         }
5712
5713         if (iService < 0) {
5714                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5715                 return GLOBAL_SECTION_SNUM;
5716         }
5717
5718         return (iService);
5719 }
5720
5721 bool share_defined(const char *service_name)
5722 {
5723         return (lp_servicenumber(service_name) != -1);
5724 }
5725
5726 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5727                                       const char *sharename)
5728 {
5729         struct share_params *result;
5730         char *sname;
5731         int snum;
5732
5733         if (!(sname = SMB_STRDUP(sharename))) {
5734                 return NULL;
5735         }
5736
5737         snum = find_service(sname);
5738         SAFE_FREE(sname);
5739
5740         if (snum < 0) {
5741                 return NULL;
5742         }
5743
5744         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5745                 DEBUG(0, ("talloc failed\n"));
5746                 return NULL;
5747         }
5748
5749         result->service = snum;
5750         return result;
5751 }
5752
5753 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5754 {
5755         struct share_iterator *result;
5756
5757         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5758                 DEBUG(0, ("talloc failed\n"));
5759                 return NULL;
5760         }
5761
5762         result->next_id = 0;
5763         return result;
5764 }
5765
5766 struct share_params *next_share(struct share_iterator *list)
5767 {
5768         struct share_params *result;
5769
5770         while (!lp_snum_ok(list->next_id) &&
5771                (list->next_id < lp_numservices())) {
5772                 list->next_id += 1;
5773         }
5774
5775         if (list->next_id >= lp_numservices()) {
5776                 return NULL;
5777         }
5778
5779         if (!(result = TALLOC_P(list, struct share_params))) {
5780                 DEBUG(0, ("talloc failed\n"));
5781                 return NULL;
5782         }
5783
5784         result->service = list->next_id;
5785         list->next_id += 1;
5786         return result;
5787 }
5788
5789 struct share_params *next_printer(struct share_iterator *list)
5790 {
5791         struct share_params *result;
5792
5793         while ((result = next_share(list)) != NULL) {
5794                 if (lp_print_ok(result->service)) {
5795                         break;
5796                 }
5797         }
5798         return result;
5799 }
5800
5801 /*
5802  * This is a hack for a transition period until we transformed all code from
5803  * service numbers to struct share_params.
5804  */
5805
5806 struct share_params *snum2params_static(int snum)
5807 {
5808         static struct share_params result;
5809         result.service = snum;
5810         return &result;
5811 }
5812
5813 /*******************************************************************
5814  A useful volume label function. 
5815 ********************************************************************/
5816
5817 const char *volume_label(int snum)
5818 {
5819         char *ret;
5820         const char *label = lp_volume(snum);
5821         if (!*label) {
5822                 label = lp_servicename(snum);
5823         }
5824                 
5825         /* This returns a 33 byte guarenteed null terminated string. */
5826         ret = talloc_strndup(talloc_tos(), label, 32);
5827         if (!ret) {
5828                 return "";
5829         }               
5830         return ret;
5831 }
5832
5833 /*******************************************************************
5834  Set the server type we will announce as via nmbd.
5835 ********************************************************************/
5836
5837 static void set_default_server_announce_type(void)
5838 {
5839         default_server_announce = 0;
5840         default_server_announce |= SV_TYPE_WORKSTATION;
5841         default_server_announce |= SV_TYPE_SERVER;
5842         default_server_announce |= SV_TYPE_SERVER_UNIX;
5843
5844         /* note that the flag should be set only if we have a 
5845            printer service but nmbd doesn't actually load the 
5846            services so we can't tell   --jerry */
5847
5848         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5849
5850         switch (lp_announce_as()) {
5851                 case ANNOUNCE_AS_NT_SERVER:
5852                         default_server_announce |= SV_TYPE_SERVER_NT;
5853                         /* fall through... */
5854                 case ANNOUNCE_AS_NT_WORKSTATION:
5855                         default_server_announce |= SV_TYPE_NT;
5856                         break;
5857                 case ANNOUNCE_AS_WIN95:
5858                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5859                         break;
5860                 case ANNOUNCE_AS_WFW:
5861                         default_server_announce |= SV_TYPE_WFW;
5862                         break;
5863                 default:
5864                         break;
5865         }
5866
5867         switch (lp_server_role()) {
5868                 case ROLE_DOMAIN_MEMBER:
5869                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5870                         break;
5871                 case ROLE_DOMAIN_PDC:
5872                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5873                         break;
5874                 case ROLE_DOMAIN_BDC:
5875                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5876                         break;
5877                 case ROLE_STANDALONE:
5878                 default:
5879                         break;
5880         }
5881         if (lp_time_server())
5882                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5883
5884         if (lp_host_msdfs())
5885                 default_server_announce |= SV_TYPE_DFS_SERVER;
5886 }
5887
5888 /***********************************************************
5889  returns role of Samba server
5890 ************************************************************/
5891
5892 int lp_server_role(void)
5893 {
5894         return server_role;
5895 }
5896
5897 /***********************************************************
5898  If we are PDC then prefer us as DMB
5899 ************************************************************/
5900
5901 bool lp_domain_master(void)
5902 {
5903         if (Globals.iDomainMaster == Auto)
5904                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5905
5906         return (bool)Globals.iDomainMaster;
5907 }
5908
5909 /***********************************************************
5910  If we are DMB then prefer us as LMB
5911 ************************************************************/
5912
5913 bool lp_preferred_master(void)
5914 {
5915         if (Globals.iPreferredMaster == Auto)
5916                 return (lp_local_master() && lp_domain_master());
5917
5918         return (bool)Globals.iPreferredMaster;
5919 }
5920
5921 /*******************************************************************
5922  Remove a service.
5923 ********************************************************************/
5924
5925 void lp_remove_service(int snum)
5926 {
5927         ServicePtrs[snum]->valid = False;
5928         invalid_services[num_invalid_services++] = snum;
5929 }
5930
5931 /*******************************************************************
5932  Copy a service.
5933 ********************************************************************/
5934
5935 void lp_copy_service(int snum, const char *new_name)
5936 {
5937         do_section(new_name);
5938         if (snum >= 0) {
5939                 snum = lp_servicenumber(new_name);
5940                 if (snum >= 0)
5941                         lp_do_parameter(snum, "copy", lp_servicename(snum));
5942         }
5943 }
5944
5945
5946 /*******************************************************************
5947  Get the default server type we will announce as via nmbd.
5948 ********************************************************************/
5949
5950 int lp_default_server_announce(void)
5951 {
5952         return default_server_announce;
5953 }
5954
5955 /*******************************************************************
5956  Split the announce version into major and minor numbers.
5957 ********************************************************************/
5958
5959 int lp_major_announce_version(void)
5960 {
5961         static bool got_major = False;
5962         static int major_version = DEFAULT_MAJOR_VERSION;
5963         char *vers;
5964         char *p;
5965
5966         if (got_major)
5967                 return major_version;
5968
5969         got_major = True;
5970         if ((vers = lp_announce_version()) == NULL)
5971                 return major_version;
5972
5973         if ((p = strchr_m(vers, '.')) == 0)
5974                 return major_version;
5975
5976         *p = '\0';
5977         major_version = atoi(vers);
5978         return major_version;
5979 }
5980
5981 int lp_minor_announce_version(void)
5982 {
5983         static bool got_minor = False;
5984         static int minor_version = DEFAULT_MINOR_VERSION;
5985         char *vers;
5986         char *p;
5987
5988         if (got_minor)
5989                 return minor_version;
5990
5991         got_minor = True;
5992         if ((vers = lp_announce_version()) == NULL)
5993                 return minor_version;
5994
5995         if ((p = strchr_m(vers, '.')) == 0)
5996                 return minor_version;
5997
5998         p++;
5999         minor_version = atoi(p);
6000         return minor_version;
6001 }
6002
6003 /***********************************************************
6004  Set the global name resolution order (used in smbclient).
6005 ************************************************************/
6006
6007 void lp_set_name_resolve_order(const char *new_order)
6008 {
6009         string_set(&Globals.szNameResolveOrder, new_order);
6010 }
6011
6012 const char *lp_printername(int snum)
6013 {
6014         const char *ret = _lp_printername(snum);
6015         if (ret == NULL || (ret != NULL && *ret == '\0'))
6016                 ret = lp_const_servicename(snum);
6017
6018         return ret;
6019 }
6020
6021
6022 /***********************************************************
6023  Allow daemons such as winbindd to fix their logfile name.
6024 ************************************************************/
6025
6026 void lp_set_logfile(const char *name)
6027 {
6028         string_set(&Globals.szLogFile, name);
6029         debug_set_logfile(name);
6030 }
6031
6032 /*******************************************************************
6033  Return the max print jobs per queue.
6034 ********************************************************************/
6035
6036 int lp_maxprintjobs(int snum)
6037 {
6038         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
6039         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
6040                 maxjobs = PRINT_MAX_JOBID - 1;
6041
6042         return maxjobs;
6043 }
6044
6045 const char *lp_printcapname(void)
6046 {
6047         if ((Globals.szPrintcapname != NULL) &&
6048             (Globals.szPrintcapname[0] != '\0'))
6049                 return Globals.szPrintcapname;
6050
6051         if (sDefault.iPrinting == PRINT_CUPS) {
6052 #ifdef HAVE_CUPS
6053                 return "cups";
6054 #else
6055                 return "lpstat";
6056 #endif
6057         }
6058
6059         if (sDefault.iPrinting == PRINT_BSD)
6060                 return "/etc/printcap";
6061
6062         return PRINTCAP_NAME;
6063 }
6064
6065 /*******************************************************************
6066  Ensure we don't use sendfile if server smb signing is active.
6067 ********************************************************************/
6068
6069 static uint32 spoolss_state;
6070
6071 bool lp_disable_spoolss( void )
6072 {
6073         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
6074                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6075
6076         return spoolss_state == SVCCTL_STOPPED ? True : False;
6077 }
6078
6079 void lp_set_spoolss_state( uint32 state )
6080 {
6081         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
6082
6083         spoolss_state = state;
6084 }
6085
6086 uint32 lp_get_spoolss_state( void )
6087 {
6088         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6089 }
6090
6091 /*******************************************************************
6092  Ensure we don't use sendfile if server smb signing is active.
6093 ********************************************************************/
6094
6095 bool lp_use_sendfile(int snum)
6096 {
6097         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
6098         if (Protocol < PROTOCOL_NT1) {
6099                 return False;
6100         }
6101         return (_lp_use_sendfile(snum) &&
6102                         (get_remote_arch() != RA_WIN95) &&
6103                         !srv_is_signing_active());
6104 }
6105
6106 /*******************************************************************
6107  Turn off sendfile if we find the underlying OS doesn't support it.
6108 ********************************************************************/
6109
6110 void set_use_sendfile(int snum, bool val)
6111 {
6112         if (LP_SNUM_OK(snum))
6113                 ServicePtrs[snum]->bUseSendfile = val;
6114         else
6115                 sDefault.bUseSendfile = val;
6116 }
6117
6118 /*******************************************************************
6119  Turn off storing DOS attributes if this share doesn't support it.
6120 ********************************************************************/
6121
6122 void set_store_dos_attributes(int snum, bool val)
6123 {
6124         if (!LP_SNUM_OK(snum))
6125                 return;
6126         ServicePtrs[(snum)]->bStoreDosAttributes = val;
6127 }
6128
6129 void lp_set_mangling_method(const char *new_method)
6130 {
6131         string_set(&Globals.szManglingMethod, new_method);
6132 }
6133
6134 /*******************************************************************
6135  Global state for POSIX pathname processing.
6136 ********************************************************************/
6137
6138 static bool posix_pathnames;
6139
6140 bool lp_posix_pathnames(void)
6141 {
6142         return posix_pathnames;
6143 }
6144
6145 /*******************************************************************
6146  Change everything needed to ensure POSIX pathname processing (currently
6147  not much).
6148 ********************************************************************/
6149
6150 void lp_set_posix_pathnames(void)
6151 {
6152         posix_pathnames = True;
6153 }
6154
6155 /*******************************************************************
6156  Global state for POSIX lock processing - CIFS unix extensions.
6157 ********************************************************************/
6158
6159 bool posix_default_lock_was_set;
6160 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
6161
6162 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
6163 {
6164         if (posix_default_lock_was_set) {
6165                 return posix_cifsx_locktype;
6166         } else {
6167                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
6168         }
6169 }
6170
6171 /*******************************************************************
6172 ********************************************************************/
6173
6174 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
6175 {
6176         posix_default_lock_was_set = True;
6177         posix_cifsx_locktype = val;
6178 }
6179
6180 int lp_min_receive_file_size(void)
6181 {
6182         if (Globals.iminreceivefile < 0) {
6183                 return 0;
6184         }
6185         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
6186 }