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