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