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