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