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