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