r19963: Add 'registry shares = yes' and registry key security descriptors.
[kai/samba.git] / source / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 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 *szAddShareCommand;
185         char *szChangeShareCommand;
186         char *szDeleteShareCommand;
187         char **szEventLogs;
188         char *szGuestaccount;
189         char *szManglingMethod;
190         char **szServicesList;
191         char *szUsersharePath;
192         char *szUsershareTemplateShare;
193         char **szUsersharePrefixAllowList;
194         char **szUsersharePrefixDenyList;
195         int mangle_prefix;
196         int max_log_size;
197         char *szLogLevel;
198         int max_xmit;
199         int max_mux;
200         int max_open_files;
201         int open_files_db_hash_size;
202         int pwordlevel;
203         int unamelevel;
204         int deadtime;
205         int maxprotocol;
206         int minprotocol;
207         int security;
208         char **AuthMethods;
209         BOOL paranoid_server_security;
210         int maxdisksize;
211         int lpqcachetime;
212         int iMaxSmbdProcesses;
213         BOOL bDisableSpoolss;
214         int syslog;
215         int os_level;
216         int enhanced_browsing;
217         int max_ttl;
218         int max_wins_ttl;
219         int min_wins_ttl;
220         int lm_announce;
221         int lm_interval;
222         int announce_as;        /* This is initialised in init_globals */
223         int machine_password_timeout;
224         int map_to_guest;
225         int oplock_break_wait_time;
226         int winbind_cache_time;
227         int winbind_max_idle_children;
228         char **szWinbindNssInfo;
229         int iLockSpinCount;
230         int iLockSpinTime;
231         char *szLdapMachineSuffix;
232         char *szLdapUserSuffix;
233         char *szLdapIdmapSuffix;
234         char *szLdapGroupSuffix;
235         int ldap_ssl;
236         char *szLdapSuffix;
237         char *szLdapAdminDn;
238         int iAclCompat;
239         char *szCupsServer;
240         char *szIPrintServer;
241         int ldap_passwd_sync; 
242         int ldap_replication_sleep;
243         int ldap_timeout; /* This is initialised in init_globals */
244         int ldap_page_size;
245         BOOL ldap_delete_dn;
246         BOOL bMsAddPrinterWizard;
247         BOOL bDNSproxy;
248         BOOL bWINSsupport;
249         BOOL bWINSproxy;
250         BOOL bLocalMaster;
251         BOOL bPreferredMaster;
252         BOOL bDomainMaster;
253         BOOL bDomainLogons;
254         BOOL bEncryptPasswords;
255         BOOL bUpdateEncrypt;
256         int  clientSchannel;
257         int  serverSchannel;
258         BOOL bNullPasswords;
259         BOOL bObeyPamRestrictions;
260         BOOL bLoadPrinters;
261         int PrintcapCacheTime;
262         BOOL bLargeReadwrite;
263         BOOL bReadRaw;
264         BOOL bWriteRaw;
265         BOOL bReadbmpx;
266         BOOL bSyslogOnly;
267         BOOL bBrowseList;
268         BOOL bNISHomeMap;
269         BOOL bTimeServer;
270         BOOL bBindInterfacesOnly;
271         BOOL bPamPasswordChange;
272         BOOL bUnixPasswdSync;
273         BOOL bPasswdChatDebug;
274         int iPasswdChatTimeout;
275         BOOL bTimestampLogs;
276         BOOL bNTSmbSupport;
277         BOOL bNTPipeSupport;
278         BOOL bNTStatusSupport;
279         BOOL bStatCache;
280         int iMaxStatCacheSize;
281         BOOL bKernelOplocks;
282         BOOL bAllowTrustedDomains;
283         BOOL bLanmanAuth;
284         BOOL bNTLMAuth;
285         BOOL bUseSpnego;
286         BOOL bClientLanManAuth;
287         BOOL bClientNTLMv2Auth;
288         BOOL bClientPlaintextAuth;
289         BOOL bClientUseSpnego;
290         BOOL bDebugHiresTimestamp;
291         BOOL bDebugPid;
292         BOOL bDebugUid;
293         BOOL bEnableCoreFiles;
294         BOOL bHostMSDfs;
295         BOOL bUseMmap;
296         BOOL bHostnameLookups;
297         BOOL bUnixExtensions;
298         BOOL bDisableNetbios;
299         BOOL bKernelChangeNotify;
300         BOOL bFamChangeNotify;
301         BOOL bUseKerberosKeytab;
302         BOOL bDeferSharingViolations;
303         BOOL bEnablePrivileges;
304         BOOL bASUSupport;
305         BOOL bUsershareOwnerOnly;
306         BOOL bUsershareAllowGuests;
307         BOOL bRegistryShares;
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         {"registry shares", P_BOOL, P_GLOBAL, &Globals.bRegistryShares, NULL, NULL, FLAG_ADVANCED},
1230         {"usershare allow guests", P_BOOL, P_GLOBAL, &Globals.bUsershareAllowGuests, NULL, NULL, FLAG_ADVANCED},
1231         {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
1232         {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
1233         {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
1234         {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
1235         {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
1236         {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
1237         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
1238         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1239         {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1240         {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1241         {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1242         {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1243         {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1244         {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1245         {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1246         {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1247         {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1248         {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1249
1250         {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
1251         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED}, 
1252
1253         {N_("VFS module options"), P_SEP, P_SEPARATOR}, 
1254
1255         {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1256         {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE}, 
1257
1258
1259         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1260         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
1261         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED}, 
1262
1263         {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
1264
1265         {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
1266         {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, 
1267         {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, 
1268         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE}, 
1269         {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, 
1270         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE}, 
1271         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
1272         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
1273         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
1274         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, 
1275         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, 
1276         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, 
1277         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, 
1278         {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, 
1279         {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
1280         {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
1281         {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
1282         {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, 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 = 1024; /* one Meg 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
1630         Globals.bPassdbExpandExplicit = False;
1631
1632         Globals.name_cache_timeout = 660; /* In seconds */
1633
1634         Globals.bUseSpnego = True;
1635         Globals.bClientUseSpnego = True;
1636
1637         Globals.client_signing = Auto;
1638         Globals.server_signing = False;
1639
1640         Globals.bDeferSharingViolations = True;
1641         string_set(&Globals.smb_ports, SMB_PORTS);
1642
1643         Globals.bEnablePrivileges = True;
1644         Globals.bHostMSDfs        = True;
1645         Globals.bASUSupport       = False;
1646         
1647         /* User defined shares. */
1648         pstrcpy(s, dyn_LOCKDIR);
1649         pstrcat(s, "/usershares");
1650         string_set(&Globals.szUsersharePath, s);
1651         string_set(&Globals.szUsershareTemplateShare, "");
1652         Globals.iUsershareMaxShares = 0;
1653         /* By default disallow sharing of directories not owned by the sharer. */
1654         Globals.bUsershareOwnerOnly = True;
1655         /* By default disallow guest access to usershares. */
1656         Globals.bUsershareAllowGuests = False;
1657
1658         /* By default no shares out of the registry */
1659         Globals.bRegistryShares = False;
1660 }
1661
1662 static TALLOC_CTX *lp_talloc;
1663
1664 /******************************************************************* a
1665  Free up temporary memory - called from the main loop.
1666 ********************************************************************/
1667
1668 void lp_TALLOC_FREE(void)
1669 {
1670         if (!lp_talloc)
1671                 return;
1672         TALLOC_FREE(lp_talloc);
1673         lp_talloc = NULL;
1674 }
1675
1676 TALLOC_CTX *tmp_talloc_ctx(void)
1677 {
1678         if (lp_talloc == NULL) {
1679                 lp_talloc = talloc_init("tmp_talloc_ctx");
1680         }
1681
1682         if (lp_talloc == NULL) {
1683                 smb_panic("Could not create temporary talloc context\n");
1684         }
1685
1686         return lp_talloc;
1687 }
1688
1689 /*******************************************************************
1690  Convenience routine to grab string parameters into temporary memory
1691  and run standard_sub_basic on them. The buffers can be written to by
1692  callers without affecting the source string.
1693 ********************************************************************/
1694
1695 static char *lp_string(const char *s)
1696 {
1697         char *ret, *tmpstr;
1698
1699         /* The follow debug is useful for tracking down memory problems
1700            especially if you have an inner loop that is calling a lp_*()
1701            function that returns a string.  Perhaps this debug should be
1702            present all the time? */
1703
1704 #if 0
1705         DEBUG(10, ("lp_string(%s)\n", s));
1706 #endif
1707
1708         if (!lp_talloc)
1709                 lp_talloc = talloc_init("lp_talloc");
1710
1711         tmpstr = alloc_sub_basic(get_current_username(),
1712                                  current_user_info.domain, s);
1713         if (trim_char(tmpstr, '\"', '\"')) {
1714                 if (strchr(tmpstr,'\"') != NULL) {
1715                         SAFE_FREE(tmpstr);
1716                         tmpstr = alloc_sub_basic(get_current_username(),
1717                                                  current_user_info.domain, s);
1718                 }
1719         }
1720         ret = talloc_strdup(lp_talloc, tmpstr);
1721         SAFE_FREE(tmpstr);
1722                         
1723         return (ret);
1724 }
1725
1726 /*
1727    In this section all the functions that are used to access the 
1728    parameters from the rest of the program are defined 
1729 */
1730
1731 #define FN_GLOBAL_STRING(fn_name,ptr) \
1732  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1733 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1734  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1735 #define FN_GLOBAL_LIST(fn_name,ptr) \
1736  const char **fn_name(void) {return(*(const char ***)(ptr));}
1737 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1738  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1739 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1740  char fn_name(void) {return(*(char *)(ptr));}
1741 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1742  int fn_name(void) {return(*(int *)(ptr));}
1743
1744 #define FN_LOCAL_STRING(fn_name,val) \
1745  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1746 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1747  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1748 #define FN_LOCAL_LIST(fn_name,val) \
1749  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1750 #define FN_LOCAL_BOOL(fn_name,val) \
1751  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1752 #define FN_LOCAL_INTEGER(fn_name,val) \
1753  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1754
1755 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1756  BOOL fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1757 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1758  int fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1759 #define FN_LOCAL_PARM_STRING(fn_name,val) \
1760  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));}
1761 #define FN_LOCAL_CHAR(fn_name,val) \
1762  char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1763
1764 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1765 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1766 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1767 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1768 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1769 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1770 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1771 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1772 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1773 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
1774 FN_GLOBAL_STRING(lp_addport_cmd, &Globals.szAddPortCommand)
1775 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1776 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1777 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1778 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1779 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1780 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1781 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1782 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1783 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1784 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1785 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1786 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1787 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1788 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1789 FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota)
1790 FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota)
1791 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1792 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1793 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1794 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1795 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1796 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1797 FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
1798 FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
1799 FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
1800 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1801 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1802 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1803 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1804 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1805 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1806 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1807 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1808 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1809 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1810 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1811 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1812 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1813 FN_GLOBAL_STRING(lp_passdb_backend, &Globals.szPassdbBackend)
1814 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1815 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1816 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1817 FN_GLOBAL_STRING(lp_renameuser_script, &Globals.szRenameUserScript)
1818 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1819
1820 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1821 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1822 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1823 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1824 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1825 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1826
1827 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1828
1829 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1830 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1831 FN_GLOBAL_STRING(lp_username_map_script, &Globals.szUsernameMapScript)
1832
1833 FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
1834
1835 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1836 FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1837 FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
1838 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1839 FN_GLOBAL_INTEGER(lp_acl_compatibility, &Globals.iAclCompat)
1840 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1841 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1842 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1843 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
1844 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
1845 FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
1846 FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
1847
1848 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
1849 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
1850
1851 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1852 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1853 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1854 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1855 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1856 FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep)
1857 FN_GLOBAL_INTEGER(lp_ldap_timeout, &Globals.ldap_timeout)
1858 FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
1859 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1860 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1861 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1862 FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
1863 FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
1864 FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
1865
1866 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
1867
1868 FN_GLOBAL_BOOL(lp_registry_shares, &Globals.bRegistryShares)
1869 FN_GLOBAL_BOOL(lp_usershare_allow_guests, &Globals.bUsershareAllowGuests)
1870 FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
1871 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1872 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
1873 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1874 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1875 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1876 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1877 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1878 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1879 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1880 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1881 FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx)
1882 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1883 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1884 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1885 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1886 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1887 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1888 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1889 FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
1890 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
1891 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
1892 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
1893 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
1894 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
1895 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
1896 FN_GLOBAL_BOOL(lp_enable_core_files, &Globals.bEnableCoreFiles)
1897 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
1898 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
1899 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1900 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1901 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1902 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1903 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
1904 FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
1905 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
1906 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1907 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
1908 FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize)
1909 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1910 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1911 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1912 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1913 FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth)
1914 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1915 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1916 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1917 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
1918 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1919 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1920 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1921 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1922 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
1923 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1924 FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
1925 FN_GLOBAL_BOOL(lp_fam_change_notify, &Globals.bFamChangeNotify)
1926 FN_GLOBAL_BOOL(lp_use_kerberos_keytab, &Globals.bUseKerberosKeytab)
1927 FN_GLOBAL_BOOL(lp_defer_sharing_violations, &Globals.bDeferSharingViolations)
1928 FN_GLOBAL_BOOL(lp_enable_privileges, &Globals.bEnablePrivileges)
1929 FN_GLOBAL_BOOL(lp_enable_asu_support, &Globals.bASUSupport)
1930 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1931 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1932 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1933 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1934 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
1935 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
1936 FN_GLOBAL_INTEGER(lp_open_files_db_hash_size, &Globals.open_files_db_hash_size)
1937 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
1938 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1939 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1940 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1941 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
1942 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1943 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1944 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1945 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1946 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1947 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
1948 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1949 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
1950 FN_GLOBAL_INTEGER(_lp_disable_spoolss, &Globals.bDisableSpoolss)
1951 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
1952 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1953 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1954 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1955 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1956 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
1957 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
1958 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1959 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
1960 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
1961
1962 FN_LOCAL_STRING(lp_preexec, szPreExec)
1963 FN_LOCAL_STRING(lp_postexec, szPostExec)
1964 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
1965 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
1966 FN_LOCAL_STRING(lp_servicename, szService)
1967 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1968 FN_LOCAL_STRING(lp_pathname, szPath)
1969 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
1970 FN_LOCAL_STRING(lp_username, szUsername)
1971 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1972 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1973 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1974 FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
1975 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
1976 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
1977 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
1978 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1979 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1980 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1981 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1982 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1983 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1984 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1985 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1986 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1987 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1988 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
1989 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
1990 FN_LOCAL_STRING(lp_comment, comment)
1991 FN_LOCAL_STRING(lp_force_user, force_user)
1992 FN_LOCAL_STRING(lp_force_group, force_group)
1993 FN_LOCAL_LIST(lp_readlist, readlist)
1994 FN_LOCAL_LIST(lp_writelist, writelist)
1995 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
1996 FN_LOCAL_STRING(lp_fstype, fstype)
1997 FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects)
1998 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1999 static FN_LOCAL_STRING(lp_volume, volume)
2000 FN_LOCAL_PARM_STRING(lp_mangled_map, szMangledMap)
2001 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
2002 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
2003 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
2004 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
2005 FN_LOCAL_STRING(lp_aio_write_behind, szAioWriteBehind)
2006 FN_LOCAL_STRING(lp_dfree_command, szDfree)
2007 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
2008 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
2009 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
2010 FN_LOCAL_INTEGER(lp_casesensitive, iCaseSensitive)
2011 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
2012 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
2013 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
2014 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
2015 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
2016 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
2017 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
2018 FN_LOCAL_BOOL(lp_readonly, bRead_only)
2019 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
2020 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
2021 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
2022 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
2023 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
2024 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
2025 FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
2026 FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
2027 FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
2028 FN_LOCAL_PARM_INTEGER(lp_strict_locking, iStrictLocking)
2029 FN_LOCAL_PARM_BOOL(lp_posix_locking, bPosixLocking)
2030 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
2031 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
2032 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
2033 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
2034 FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames)
2035 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
2036 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
2037 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
2038 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
2039 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
2040 FN_LOCAL_BOOL(lp_map_system, bMap_system)
2041 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
2042 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
2043 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
2044 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
2045 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
2046 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
2047 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
2048 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
2049 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
2050 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
2051 FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner)
2052 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
2053 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
2054 FN_LOCAL_BOOL(lp_force_printername, bForcePrintername)
2055 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
2056 FN_LOCAL_BOOL(lp_force_unknown_acl_user, bForceUnknownAclUser)
2057 FN_LOCAL_BOOL(lp_ea_support, bEASupport)
2058 FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
2059 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
2060 FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
2061 FN_LOCAL_BOOL(lp_afs_share, bAfs_Share)
2062 FN_LOCAL_BOOL(lp_acl_check_permissions, bAclCheckPermissions)
2063 FN_LOCAL_BOOL(lp_acl_group_control, bAclGroupControl)
2064 FN_LOCAL_BOOL(lp_acl_map_full_control, bAclMapFullControl)
2065 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
2066 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
2067 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
2068 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
2069 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
2070 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
2071 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
2072 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
2073 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
2074 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
2075 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
2076 FN_LOCAL_INTEGER(lp_printing, iPrinting)
2077 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
2078 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
2079 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
2080 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
2081 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
2082 FN_LOCAL_INTEGER(lp_dfree_cache_time, iDfreeCacheTime)
2083 FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
2084 FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
2085 FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
2086 FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
2087 FN_LOCAL_INTEGER(lp_change_notify_timeout, ichange_notify_timeout)
2088 FN_LOCAL_CHAR(lp_magicchar, magic_char)
2089 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
2090 FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo)
2091 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
2092 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
2093 FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
2094 FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
2095
2096 /* local prototypes */
2097
2098 static int map_parameter(const char *pszParmName);
2099 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
2100 static int getservicebyname(const char *pszServiceName,
2101                             service * pserviceDest);
2102 static void copy_service(service * pserviceDest,
2103                          service * pserviceSource, BOOL *pcopymapDest);
2104 static BOOL service_ok(int iService);
2105 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
2106 static BOOL do_section(const char *pszSectionName);
2107 static void init_copymap(service * pservice);
2108 static BOOL hash_a_service(const char *name, int number);
2109 static void free_service_byindex(int iService);
2110 static char * canonicalize_servicename(const char *name);
2111
2112 /* This is a helper function for parametrical options support. */
2113 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
2114 /* Actual parametrical functions are quite simple */
2115 static param_opt_struct *get_parametrics(int snum, const char *type, const char *option)
2116 {
2117         BOOL global_section = False;
2118         char* param_key;
2119         param_opt_struct *data;
2120         
2121         if (snum >= iNumServices) return NULL;
2122         
2123         if (snum < 0) { 
2124                 data = Globals.param_opt;
2125                 global_section = True;
2126         } else {
2127                 data = ServicePtrs[snum]->param_opt;
2128         }
2129     
2130         asprintf(&param_key, "%s:%s", type, option);
2131         if (!param_key) {
2132                 DEBUG(0,("asprintf failed!\n"));
2133                 return NULL;
2134         }
2135
2136         while (data) {
2137                 if (strcmp(data->key, param_key) == 0) {
2138                         string_free(&param_key);
2139                         return data;
2140                 }
2141                 data = data->next;
2142         }
2143
2144         if (!global_section) {
2145                 /* Try to fetch the same option but from globals */
2146                 /* but only if we are not already working with Globals */
2147                 data = Globals.param_opt;
2148                 while (data) {
2149                         if (strcmp(data->key, param_key) == 0) {
2150                                 string_free(&param_key);
2151                                 return data;
2152                         }
2153                         data = data->next;
2154                 }
2155         }
2156
2157         string_free(&param_key);
2158         
2159         return NULL;
2160 }
2161
2162
2163 #define MISSING_PARAMETER(name) \
2164     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
2165
2166 /*******************************************************************
2167 convenience routine to return int parameters.
2168 ********************************************************************/
2169 static int lp_int(const char *s)
2170 {
2171
2172         if (!s || !*s) {
2173                 MISSING_PARAMETER(lp_int);
2174                 return (-1);
2175         }
2176
2177         return atoi(s); 
2178 }
2179
2180 /*******************************************************************
2181 convenience routine to return unsigned long parameters.
2182 ********************************************************************/
2183 static unsigned long lp_ulong(const char *s)
2184 {
2185
2186         if (!s || !*s) {
2187                 MISSING_PARAMETER(lp_ulong);
2188                 return (0);
2189         }
2190
2191         return strtoul(s, NULL, 10);
2192 }
2193
2194 /*******************************************************************
2195 convenience routine to return boolean parameters.
2196 ********************************************************************/
2197 static BOOL lp_bool(const char *s)
2198 {
2199         BOOL ret = False;
2200
2201         if (!s || !*s) {
2202                 MISSING_PARAMETER(lp_bool);
2203                 return False;
2204         }
2205         
2206         if (!set_boolean(&ret,s)) {
2207                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
2208                 return False;
2209         }
2210
2211         return ret;
2212 }
2213
2214 /*******************************************************************
2215 convenience routine to return enum parameters.
2216 ********************************************************************/
2217 static int lp_enum(const char *s,const struct enum_list *_enum)
2218 {
2219         int i;
2220
2221         if (!s || !*s || !_enum) {
2222                 MISSING_PARAMETER(lp_enum);
2223                 return (-1);
2224         }
2225         
2226         for (i=0; _enum[i].name; i++) {
2227                 if (strequal(_enum[i].name,s))
2228                         return _enum[i].value;
2229         }
2230
2231         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
2232         return (-1);
2233 }
2234
2235 #undef MISSING_PARAMETER
2236
2237 /* DO NOT USE lp_parm_string ANYMORE!!!!
2238  * use lp_parm_const_string or lp_parm_talloc_string
2239  *
2240  * lp_parm_string is only used to let old modules find this symbol
2241  */
2242 #undef lp_parm_string
2243  char *lp_parm_string(const char *servicename, const char *type, const char *option)
2244 {
2245         return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL);
2246 }
2247
2248 /* Return parametric option from a given service. Type is a part of option before ':' */
2249 /* Parametric option has following syntax: 'Type: option = value' */
2250 /* the returned value is talloced in lp_talloc */
2251 char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def)
2252 {
2253         param_opt_struct *data = get_parametrics(snum, type, option);
2254         
2255         if (data == NULL||data->value==NULL) {
2256                 if (def) {
2257                         return lp_string(def);
2258                 } else {
2259                         return NULL;
2260                 }
2261         }
2262
2263         return lp_string(data->value);
2264 }
2265
2266 /* Return parametric option from a given service. Type is a part of option before ':' */
2267 /* Parametric option has following syntax: 'Type: option = value' */
2268 const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
2269 {
2270         param_opt_struct *data = get_parametrics(snum, type, option);
2271         
2272         if (data == NULL||data->value==NULL)
2273                 return def;
2274                 
2275         return data->value;
2276 }
2277
2278 /* Return parametric option from a given service. Type is a part of option before ':' */
2279 /* Parametric option has following syntax: 'Type: option = value' */
2280
2281 const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
2282 {
2283         param_opt_struct *data = get_parametrics(snum, type, option);
2284
2285         if (data == NULL||data->value==NULL)
2286                 return (const char **)def;
2287                 
2288         if (data->list==NULL) {
2289                 data->list = str_list_make(data->value, NULL);
2290         }
2291
2292         return (const char **)data->list;
2293 }
2294
2295 /* Return parametric option from a given service. Type is a part of option before ':' */
2296 /* Parametric option has following syntax: 'Type: option = value' */
2297
2298 int lp_parm_int(int snum, const char *type, const char *option, int def)
2299 {
2300         param_opt_struct *data = get_parametrics(snum, type, option);
2301         
2302         if (data && data->value && *data->value)
2303                 return lp_int(data->value);
2304
2305         return def;
2306 }
2307
2308 /* Return parametric option from a given service. Type is a part of option before ':' */
2309 /* Parametric option has following syntax: 'Type: option = value' */
2310
2311 unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
2312 {
2313         param_opt_struct *data = get_parametrics(snum, type, option);
2314         
2315         if (data && data->value && *data->value)
2316                 return lp_ulong(data->value);
2317
2318         return def;
2319 }
2320
2321 /* Return parametric option from a given service. Type is a part of option before ':' */
2322 /* Parametric option has following syntax: 'Type: option = value' */
2323
2324 BOOL lp_parm_bool(int snum, const char *type, const char *option, BOOL def)
2325 {
2326         param_opt_struct *data = get_parametrics(snum, type, option);
2327         
2328         if (data && data->value && *data->value)
2329                 return lp_bool(data->value);
2330
2331         return def;
2332 }
2333
2334 /* Return parametric option from a given service. Type is a part of option before ':' */
2335 /* Parametric option has following syntax: 'Type: option = value' */
2336
2337 int lp_parm_enum(int snum, const char *type, const char *option,
2338                  const struct enum_list *_enum, int def)
2339 {
2340         param_opt_struct *data = get_parametrics(snum, type, option);
2341         
2342         if (data && data->value && *data->value && _enum)
2343                 return lp_enum(data->value, _enum);
2344
2345         return def;
2346 }
2347
2348
2349 /***************************************************************************
2350  Initialise a service to the defaults.
2351 ***************************************************************************/
2352
2353 static void init_service(service * pservice)
2354 {
2355         memset((char *)pservice, '\0', sizeof(service));
2356         copy_service(pservice, &sDefault, NULL);
2357 }
2358
2359 /***************************************************************************
2360  Free the dynamically allocated parts of a service struct.
2361 ***************************************************************************/
2362
2363 static void free_service(service *pservice)
2364 {
2365         int i;
2366         param_opt_struct *data, *pdata;
2367         if (!pservice)
2368                 return;
2369
2370         if (pservice->szService)
2371                 DEBUG(5, ("free_service: Freeing service %s\n",
2372                        pservice->szService));
2373
2374         string_free(&pservice->szService);
2375         SAFE_FREE(pservice->copymap);
2376
2377         for (i = 0; parm_table[i].label; i++) {
2378                 if ((parm_table[i].type == P_STRING ||
2379                      parm_table[i].type == P_USTRING) &&
2380                     parm_table[i].p_class == P_LOCAL)
2381                         string_free((char **)
2382                                     (((char *)pservice) +
2383                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2384                 else if (parm_table[i].type == P_LIST &&
2385                          parm_table[i].p_class == P_LOCAL)
2386                              str_list_free((char ***)
2387                                             (((char *)pservice) +
2388                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
2389         }
2390
2391         data = pservice->param_opt;
2392         if (data)
2393                 DEBUG(5,("Freeing parametrics:\n"));
2394         while (data) {
2395                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2396                 string_free(&data->key);
2397                 string_free(&data->value);
2398                 str_list_free(&data->list);
2399                 pdata = data->next;
2400                 SAFE_FREE(data);
2401                 data = pdata;
2402         }
2403
2404         ZERO_STRUCTP(pservice);
2405 }
2406
2407
2408 /***************************************************************************
2409  remove a service indexed in the ServicePtrs array from the ServiceHash
2410  and free the dynamically allocated parts
2411 ***************************************************************************/
2412
2413 static void free_service_byindex(int idx)
2414 {
2415         if ( !LP_SNUM_OK(idx) ) 
2416                 return;
2417
2418         ServicePtrs[idx]->valid = False;
2419         invalid_services[num_invalid_services++] = idx;
2420
2421         /* we have to cleanup the hash record */
2422
2423         if (ServicePtrs[idx]->szService) {
2424                 char *canon_name = canonicalize_servicename( ServicePtrs[idx]->szService );
2425                 
2426                 tdb_delete_bystring(ServiceHash, canon_name );
2427         }
2428
2429         free_service(ServicePtrs[idx]);
2430 }
2431
2432 /***************************************************************************
2433  Add a new service to the services array initialising it with the given 
2434  service. 
2435 ***************************************************************************/
2436
2437 static int add_a_service(const service *pservice, const char *name)
2438 {
2439         int i;
2440         service tservice;
2441         int num_to_alloc = iNumServices + 1;
2442         param_opt_struct *data, *pdata;
2443
2444         tservice = *pservice;
2445
2446         /* it might already exist */
2447         if (name) {
2448                 i = getservicebyname(name, NULL);
2449                 if (i >= 0) {
2450                         /* Clean all parametric options for service */
2451                         /* They will be added during parsing again */
2452                         data = ServicePtrs[i]->param_opt;
2453                         while (data) {
2454                                 string_free(&data->key);
2455                                 string_free(&data->value);
2456                                 str_list_free(&data->list);
2457                                 pdata = data->next;
2458                                 SAFE_FREE(data);
2459                                 data = pdata;
2460                         }
2461                         ServicePtrs[i]->param_opt = NULL;
2462                         return (i);
2463                 }
2464         }
2465
2466         /* find an invalid one */
2467         i = iNumServices;
2468         if (num_invalid_services > 0) {
2469                 i = invalid_services[--num_invalid_services];
2470         }
2471
2472         /* if not, then create one */
2473         if (i == iNumServices) {
2474                 service **tsp;
2475                 int *tinvalid;
2476                 
2477                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2478                 if (tsp == NULL) {
2479                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2480                         return (-1);
2481                 }
2482                 ServicePtrs = tsp;
2483                 ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2484                 if (!ServicePtrs[iNumServices]) {
2485                         DEBUG(0,("add_a_service: out of memory!\n"));
2486                         return (-1);
2487                 }
2488                 iNumServices++;
2489
2490                 /* enlarge invalid_services here for now... */
2491                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2492                                              num_to_alloc);
2493                 if (tinvalid == NULL) {
2494                         DEBUG(0,("add_a_service: failed to enlarge "
2495                                  "invalid_services!\n"));
2496                         return (-1);
2497                 }
2498                 invalid_services = tinvalid;
2499         } else {
2500                 free_service_byindex(i);
2501         }
2502
2503         ServicePtrs[i]->valid = True;
2504
2505         init_service(ServicePtrs[i]);
2506         copy_service(ServicePtrs[i], &tservice, NULL);
2507         if (name)
2508                 string_set(&ServicePtrs[i]->szService, name);
2509                 
2510         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2511                 i, ServicePtrs[i]->szService));
2512
2513         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2514                 return (-1);
2515         }
2516                 
2517         return (i);
2518 }
2519
2520 /***************************************************************************
2521   Convert a string to uppercase and remove whitespaces.
2522 ***************************************************************************/
2523
2524 static char *canonicalize_servicename(const char *src)
2525 {
2526         static fstring canon; /* is fstring large enough? */
2527
2528         if ( !src ) {
2529                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2530                 return NULL;
2531         }
2532
2533         fstrcpy( canon, src );
2534         strlower_m( canon );
2535
2536         return canon;
2537 }
2538
2539 /***************************************************************************
2540   Add a name/index pair for the services array to the hash table.
2541 ***************************************************************************/
2542
2543 static BOOL hash_a_service(const char *name, int idx)
2544 {
2545         char *canon_name;
2546
2547         if ( !ServiceHash ) {
2548                 DEBUG(10,("hash_a_service: creating tdb servicehash\n"));
2549                 ServiceHash = tdb_open("servicehash", 1031, TDB_INTERNAL, 
2550                                         (O_RDWR|O_CREAT), 0600);
2551                 if ( !ServiceHash ) {
2552                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2553                         return False;
2554                 }
2555         }
2556
2557         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2558                 idx, name));
2559
2560         if ( !(canon_name = canonicalize_servicename( name )) )
2561                 return False;
2562
2563         tdb_store_int32(ServiceHash, canon_name, idx);
2564
2565         return True;
2566 }
2567
2568 /***************************************************************************
2569  Add a new home service, with the specified home directory, defaults coming 
2570  from service ifrom.
2571 ***************************************************************************/
2572
2573 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
2574                  const char *user, const char *pszHomedir)
2575 {
2576         int i;
2577         pstring newHomedir;
2578
2579         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2580
2581         if (i < 0)
2582                 return (False);
2583
2584         if (!(*(ServicePtrs[iDefaultService]->szPath))
2585             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2586                 pstrcpy(newHomedir, pszHomedir);
2587                 string_set(&ServicePtrs[i]->szPath, newHomedir);
2588         } 
2589
2590         if (!(*(ServicePtrs[i]->comment))) {
2591                 pstring comment;
2592                 slprintf(comment, sizeof(comment) - 1,
2593                          "Home directory of %s", user);
2594                 string_set(&ServicePtrs[i]->comment, comment);
2595         }
2596
2597         /* set the browseable flag from the global default */
2598
2599         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2600
2601         ServicePtrs[i]->autoloaded = True;
2602
2603         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2604                user, ServicePtrs[i]->szPath ));
2605         
2606         return (True);
2607 }
2608
2609 /***************************************************************************
2610  Add a new service, based on an old one.
2611 ***************************************************************************/
2612
2613 int lp_add_service(const char *pszService, int iDefaultService)
2614 {
2615         if (iDefaultService < 0) {
2616                 return add_a_service(&sDefault, pszService);
2617         }
2618
2619         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2620 }
2621
2622 /***************************************************************************
2623  Add the IPC service.
2624 ***************************************************************************/
2625
2626 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
2627 {
2628         pstring comment;
2629         int i = add_a_service(&sDefault, ipc_name);
2630
2631         if (i < 0)
2632                 return (False);
2633
2634         slprintf(comment, sizeof(comment) - 1,
2635                  "IPC Service (%s)", Globals.szServerString);
2636
2637         string_set(&ServicePtrs[i]->szPath, tmpdir());
2638         string_set(&ServicePtrs[i]->szUsername, "");
2639         string_set(&ServicePtrs[i]->comment, comment);
2640         string_set(&ServicePtrs[i]->fstype, "IPC");
2641         ServicePtrs[i]->iMaxConnections = 0;
2642         ServicePtrs[i]->bAvailable = True;
2643         ServicePtrs[i]->bRead_only = True;
2644         ServicePtrs[i]->bGuest_only = False;
2645         ServicePtrs[i]->bGuest_ok = guest_ok;
2646         ServicePtrs[i]->bPrint_ok = False;
2647         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2648
2649         DEBUG(3, ("adding IPC service\n"));
2650
2651         return (True);
2652 }
2653
2654 /***************************************************************************
2655  Add a new printer service, with defaults coming from service iFrom.
2656 ***************************************************************************/
2657
2658 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
2659 {
2660         const char *comment = "From Printcap";
2661         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2662
2663         if (i < 0)
2664                 return (False);
2665
2666         /* note that we do NOT default the availability flag to True - */
2667         /* we take it from the default service passed. This allows all */
2668         /* dynamic printers to be disabled by disabling the [printers] */
2669         /* entry (if/when the 'available' keyword is implemented!).    */
2670
2671         /* the printer name is set to the service name. */
2672         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2673         string_set(&ServicePtrs[i]->comment, comment);
2674
2675         /* set the browseable flag from the gloabl default */
2676         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2677
2678         /* Printers cannot be read_only. */
2679         ServicePtrs[i]->bRead_only = False;
2680         /* No share modes on printer services. */
2681         ServicePtrs[i]->bShareModes = False;
2682         /* No oplocks on printer services. */
2683         ServicePtrs[i]->bOpLocks = False;
2684         /* Printer services must be printable. */
2685         ServicePtrs[i]->bPrint_ok = True;
2686         
2687         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2688
2689         return (True);
2690 }
2691
2692 /***************************************************************************
2693  Map a parameter's string representation to something we can use. 
2694  Returns False if the parameter string is not recognised, else TRUE.
2695 ***************************************************************************/
2696
2697 static int map_parameter(const char *pszParmName)
2698 {
2699         int iIndex;
2700
2701         if (*pszParmName == '-')
2702                 return (-1);
2703
2704         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2705                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2706                         return (iIndex);
2707
2708         /* Warn only if it isn't parametric option */
2709         if (strchr(pszParmName, ':') == NULL)
2710                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2711         /* We do return 'fail' for parametric options as well because they are
2712            stored in different storage
2713          */
2714         return (-1);
2715 }
2716
2717 /***************************************************************************
2718  Show all parameter's name, type, [values,] and flags.
2719 ***************************************************************************/
2720
2721 void show_parameter_list(void)
2722 {
2723         int classIndex, parmIndex, enumIndex, flagIndex;
2724         BOOL hadFlag;
2725         const char *section_names[] = { "local", "global", NULL};
2726         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
2727                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING", "P_GSTRING",
2728                 "P_UGSTRING", "P_ENUM", "P_SEP"};
2729         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
2730                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
2731                 FLAG_HIDE, FLAG_DOS_STRING};
2732         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
2733                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2734                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
2735
2736         for ( classIndex=0; section_names[classIndex]; classIndex++) {
2737                 printf("[%s]\n", section_names[classIndex]);
2738                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
2739                         if (parm_table[parmIndex].p_class == classIndex) {
2740                                 printf("%s=%s", 
2741                                         parm_table[parmIndex].label,
2742                                         type[parm_table[parmIndex].type]);
2743                                 switch (parm_table[parmIndex].type) {
2744                                 case P_ENUM:
2745                                         printf(",");
2746                                         for (enumIndex=0; parm_table[parmIndex].enum_list[enumIndex].name; enumIndex++)
2747                                                 printf("%s%s",
2748                                                         enumIndex ? "|" : "",
2749                                                         parm_table[parmIndex].enum_list[enumIndex].name);
2750                                         break;
2751                                 default:
2752                                         break;
2753                                 }
2754                                 printf(",");
2755                                 hadFlag = False;
2756                                 for ( flagIndex=0; flag_names[flagIndex]; flagIndex++ ) {
2757                                         if (parm_table[parmIndex].flags & flags[flagIndex]) {
2758                                                 printf("%s%s",
2759                                                         hadFlag ? "|" : "",
2760                                                         flag_names[flagIndex]);
2761                                                 hadFlag = True;
2762                                         }
2763                                 }
2764                                 printf("\n");
2765                         }
2766                 }
2767         }
2768 }
2769
2770 /***************************************************************************
2771  Set a boolean variable from the text value stored in the passed string.
2772  Returns True in success, False if the passed string does not correctly 
2773  represent a boolean.
2774 ***************************************************************************/
2775
2776 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
2777 {
2778         BOOL bRetval;
2779
2780         bRetval = True;
2781         if (strwicmp(pszParmValue, "yes") == 0 ||
2782             strwicmp(pszParmValue, "true") == 0 ||
2783             strwicmp(pszParmValue, "1") == 0)
2784                 *pb = True;
2785         else if (strwicmp(pszParmValue, "no") == 0 ||
2786                     strwicmp(pszParmValue, "False") == 0 ||
2787                     strwicmp(pszParmValue, "0") == 0)
2788                 *pb = False;
2789         else {
2790                 DEBUG(0,
2791                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
2792                        pszParmValue));
2793                 bRetval = False;
2794         }
2795         return (bRetval);
2796 }
2797
2798 /***************************************************************************
2799 Find a service by name. Otherwise works like get_service.
2800 ***************************************************************************/
2801
2802 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
2803 {
2804         int iService = -1;
2805         char *canon_name;
2806
2807         if (ServiceHash != NULL) {
2808                 if ( !(canon_name = canonicalize_servicename( pszServiceName )) )
2809                         return -1;
2810
2811                 iService = tdb_fetch_int32(ServiceHash, canon_name );
2812
2813                 if (LP_SNUM_OK(iService)) {
2814                         if (pserviceDest != NULL) {
2815                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2816                         }
2817                 } else {
2818                         iService = -1;
2819                 }
2820         }
2821
2822         return (iService);
2823 }
2824
2825 /***************************************************************************
2826  Copy a service structure to another.
2827  If pcopymapDest is NULL then copy all fields
2828 ***************************************************************************/
2829
2830 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
2831 {
2832         int i;
2833         BOOL bcopyall = (pcopymapDest == NULL);
2834         param_opt_struct *data, *pdata, *paramo;
2835         BOOL not_added;
2836
2837         for (i = 0; parm_table[i].label; i++)
2838                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
2839                     (bcopyall || pcopymapDest[i])) {
2840                         void *def_ptr = parm_table[i].ptr;
2841                         void *src_ptr =
2842                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
2843                                                                     &sDefault);
2844                         void *dest_ptr =
2845                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
2846                                                                   &sDefault);
2847
2848                         switch (parm_table[i].type) {
2849                                 case P_BOOL:
2850                                 case P_BOOLREV:
2851                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
2852                                         break;
2853
2854                                 case P_INTEGER:
2855                                 case P_ENUM:
2856                                 case P_OCTAL:
2857                                         *(int *)dest_ptr = *(int *)src_ptr;
2858                                         break;
2859
2860                                 case P_CHAR:
2861                                         *(char *)dest_ptr = *(char *)src_ptr;
2862                                         break;
2863
2864                                 case P_STRING:
2865                                         string_set((char **)dest_ptr,
2866                                                    *(char **)src_ptr);
2867                                         break;
2868
2869                                 case P_USTRING:
2870                                         string_set((char **)dest_ptr,
2871                                                    *(char **)src_ptr);
2872                                         strupper_m(*(char **)dest_ptr);
2873                                         break;
2874                                 case P_LIST:
2875                                         str_list_free((char ***)dest_ptr);
2876                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
2877                                         break;
2878                                 default:
2879                                         break;
2880                         }
2881                 }
2882
2883         if (bcopyall) {
2884                 init_copymap(pserviceDest);
2885                 if (pserviceSource->copymap)
2886                         memcpy((void *)pserviceDest->copymap,
2887                                (void *)pserviceSource->copymap,
2888                                sizeof(BOOL) * NUMPARAMETERS);
2889         }
2890         
2891         data = pserviceSource->param_opt;
2892         while (data) {
2893                 not_added = True;
2894                 pdata = pserviceDest->param_opt;
2895                 /* Traverse destination */
2896                 while (pdata) {
2897                         /* If we already have same option, override it */
2898                         if (strcmp(pdata->key, data->key) == 0) {
2899                                 string_free(&pdata->value);
2900                                 str_list_free(&data->list);
2901                                 pdata->value = SMB_STRDUP(data->value);
2902                                 not_added = False;
2903                                 break;
2904                         }
2905                         pdata = pdata->next;
2906                 }
2907                 if (not_added) {
2908                     paramo = SMB_XMALLOC_P(param_opt_struct);
2909                     paramo->key = SMB_STRDUP(data->key);
2910                     paramo->value = SMB_STRDUP(data->value);
2911                     paramo->list = NULL;
2912                     DLIST_ADD(pserviceDest->param_opt, paramo);
2913                 }
2914                 data = data->next;
2915         }
2916 }
2917
2918 /***************************************************************************
2919 Check a service for consistency. Return False if the service is in any way
2920 incomplete or faulty, else True.
2921 ***************************************************************************/
2922
2923 static BOOL service_ok(int iService)
2924 {
2925         BOOL bRetval;
2926
2927         bRetval = True;
2928         if (ServicePtrs[iService]->szService[0] == '\0') {
2929                 DEBUG(0, ("The following message indicates an internal error:\n"));
2930                 DEBUG(0, ("No service name in service entry.\n"));
2931                 bRetval = False;
2932         }
2933
2934         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2935         /* I can't see why you'd want a non-printable printer service...        */
2936         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2937                 if (!ServicePtrs[iService]->bPrint_ok) {
2938                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2939                                ServicePtrs[iService]->szService));
2940                         ServicePtrs[iService]->bPrint_ok = True;
2941                 }
2942                 /* [printers] service must also be non-browsable. */
2943                 if (ServicePtrs[iService]->bBrowseable)
2944                         ServicePtrs[iService]->bBrowseable = False;
2945         }
2946
2947         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2948             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
2949             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
2950             ) {
2951                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2952                         ServicePtrs[iService]->szService));
2953                 ServicePtrs[iService]->bAvailable = False;
2954         }
2955
2956         /* If a service is flagged unavailable, log the fact at level 0. */
2957         if (!ServicePtrs[iService]->bAvailable)
2958                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2959                           ServicePtrs[iService]->szService));
2960
2961         return (bRetval);
2962 }
2963
2964 static struct file_lists {
2965         struct file_lists *next;
2966         char *name;
2967         char *subfname;
2968         time_t modtime;
2969 } *file_lists = NULL;
2970
2971 /*******************************************************************
2972  Keep a linked list of all config files so we know when one has changed 
2973  it's date and needs to be reloaded.
2974 ********************************************************************/
2975
2976 static void add_to_file_list(const char *fname, const char *subfname)
2977 {
2978         struct file_lists *f = file_lists;
2979
2980         while (f) {
2981                 if (f->name && !strcmp(f->name, fname))
2982                         break;
2983                 f = f->next;
2984         }
2985
2986         if (!f) {
2987                 f = SMB_MALLOC_P(struct file_lists);
2988                 if (!f)
2989                         return;
2990                 f->next = file_lists;
2991                 f->name = SMB_STRDUP(fname);
2992                 if (!f->name) {
2993                         SAFE_FREE(f);
2994                         return;
2995                 }
2996                 f->subfname = SMB_STRDUP(subfname);
2997                 if (!f->subfname) {
2998                         SAFE_FREE(f);
2999                         return;
3000                 }
3001                 file_lists = f;
3002                 f->modtime = file_modtime(subfname);
3003         } else {
3004                 time_t t = file_modtime(subfname);
3005                 if (t)
3006                         f->modtime = t;
3007         }
3008 }
3009
3010 /*******************************************************************
3011  Check if a config file has changed date.
3012 ********************************************************************/
3013
3014 BOOL lp_file_list_changed(void)
3015 {
3016         struct file_lists *f = file_lists;
3017
3018         DEBUG(6, ("lp_file_list_changed()\n"));
3019
3020         while (f) {
3021                 pstring n2;
3022                 time_t mod_time;
3023
3024                 pstrcpy(n2, f->name);
3025                 standard_sub_basic( get_current_username(),
3026                                     current_user_info.domain,
3027                                     n2, sizeof(n2) );
3028
3029                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3030                              f->name, n2, ctime(&f->modtime)));
3031
3032                 mod_time = file_modtime(n2);
3033
3034                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3035                         DEBUGADD(6,
3036                                  ("file %s modified: %s\n", n2,
3037                                   ctime(&mod_time)));
3038                         f->modtime = mod_time;
3039                         SAFE_FREE(f->subfname);
3040                         f->subfname = SMB_STRDUP(n2);
3041                         return (True);
3042                 }
3043                 f = f->next;
3044         }
3045         return (False);
3046 }
3047
3048 /***************************************************************************
3049  Run standard_sub_basic on netbios name... needed because global_myname
3050  is not accessed through any lp_ macro.
3051  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3052 ***************************************************************************/
3053
3054 static BOOL handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3055 {
3056         BOOL ret;
3057         pstring netbios_name;
3058
3059         pstrcpy(netbios_name, pszParmValue);
3060
3061         standard_sub_basic(get_current_username(), current_user_info.domain,
3062                            netbios_name, sizeof(netbios_name));
3063
3064         ret = set_global_myname(netbios_name);
3065         string_set(&Globals.szNetbiosName,global_myname());
3066         
3067         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3068                global_myname()));
3069
3070         return ret;
3071 }
3072
3073 static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr)
3074 {
3075         if (strcmp(*ptr, pszParmValue) != 0) {
3076                 string_set(ptr, pszParmValue);
3077                 init_iconv();
3078         }
3079         return True;
3080 }
3081
3082
3083
3084 static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3085 {
3086         BOOL ret;
3087         
3088         ret = set_global_myworkgroup(pszParmValue);
3089         string_set(&Globals.szWorkgroup,lp_workgroup());
3090         
3091         return ret;
3092 }
3093
3094 static BOOL handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3095 {
3096         BOOL ret;
3097         
3098         ret = set_global_scope(pszParmValue);
3099         string_set(&Globals.szNetbiosScope,global_scope());
3100
3101         return ret;
3102 }
3103
3104 static BOOL handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3105 {
3106         str_list_free(&Globals.szNetbiosAliases);
3107         Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
3108         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3109 }
3110
3111 /***************************************************************************
3112  Handle the include operation.
3113 ***************************************************************************/
3114
3115 static BOOL handle_include(int snum, const char *pszParmValue, char **ptr)
3116 {
3117         pstring fname;
3118         pstrcpy(fname, pszParmValue);
3119
3120         standard_sub_basic(get_current_username(), current_user_info.domain,
3121                            fname,sizeof(fname));
3122
3123         add_to_file_list(pszParmValue, fname);
3124
3125         string_set(ptr, fname);
3126
3127         if (file_exist(fname, NULL))
3128                 return (pm_process(fname, do_section, do_parameter));
3129
3130         DEBUG(2, ("Can't find include file %s\n", fname));
3131
3132         return (False);
3133 }
3134
3135 /***************************************************************************
3136  Handle the interpretation of the copy parameter.
3137 ***************************************************************************/
3138
3139 static BOOL handle_copy(int snum, const char *pszParmValue, char **ptr)
3140 {
3141         BOOL bRetval;
3142         int iTemp;
3143         service serviceTemp;
3144
3145         string_set(ptr, pszParmValue);
3146
3147         init_service(&serviceTemp);
3148
3149         bRetval = False;
3150
3151         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3152
3153         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3154                 if (iTemp == iServiceIndex) {
3155                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3156                 } else {
3157                         copy_service(ServicePtrs[iServiceIndex],
3158                                      &serviceTemp,
3159                                      ServicePtrs[iServiceIndex]->copymap);
3160                         bRetval = True;
3161                 }
3162         } else {
3163                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3164                 bRetval = False;
3165         }
3166
3167         free_service(&serviceTemp);
3168         return (bRetval);
3169 }
3170
3171 /***************************************************************************
3172  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3173  parameters is:
3174
3175  [global]
3176
3177         idmap uid = 1000-1999
3178         idmap gid = 700-899
3179
3180  We only do simple parsing checks here.  The strings are parsed into useful
3181  structures in the idmap daemon code.
3182
3183 ***************************************************************************/
3184
3185 /* Some lp_ routines to return idmap [ug]id information */
3186
3187 static uid_t idmap_uid_low, idmap_uid_high;
3188 static gid_t idmap_gid_low, idmap_gid_high;
3189
3190 BOOL lp_idmap_uid(uid_t *low, uid_t *high)
3191 {
3192         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3193                 return False;
3194
3195         if (low)
3196                 *low = idmap_uid_low;
3197
3198         if (high)
3199                 *high = idmap_uid_high;
3200
3201         return True;
3202 }
3203
3204 BOOL lp_idmap_gid(gid_t *low, gid_t *high)
3205 {
3206         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3207                 return False;
3208
3209         if (low)
3210                 *low = idmap_gid_low;
3211
3212         if (high)
3213                 *high = idmap_gid_high;
3214
3215         return True;
3216 }
3217
3218 /* Do some simple checks on "idmap [ug]id" parameter values */
3219
3220 static BOOL handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3221 {
3222         uint32 low, high;
3223
3224         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3225                 return False;
3226
3227         /* Parse OK */
3228
3229         string_set(ptr, pszParmValue);
3230
3231         idmap_uid_low = low;
3232         idmap_uid_high = high;
3233
3234         return True;
3235 }
3236
3237 static BOOL handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3238 {
3239         uint32 low, high;
3240
3241         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3242                 return False;
3243
3244         /* Parse OK */
3245
3246         string_set(ptr, pszParmValue);
3247
3248         idmap_gid_low = low;
3249         idmap_gid_high = high;
3250
3251         return True;
3252 }
3253
3254 /***************************************************************************
3255  Handle the DEBUG level list.
3256 ***************************************************************************/
3257
3258 static BOOL handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3259 {
3260         pstring pszParmValue;
3261
3262         pstrcpy(pszParmValue, pszParmValueIn);
3263         string_set(ptr, pszParmValueIn);
3264         return debug_parse_levels( pszParmValue );
3265 }
3266
3267 /***************************************************************************
3268  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3269 ***************************************************************************/
3270
3271 static const char *append_ldap_suffix( const char *str )
3272 {
3273         const char *suffix_string;
3274
3275
3276         if (!lp_talloc)
3277                 lp_talloc = talloc_init("lp_talloc");
3278
3279         suffix_string = talloc_asprintf( lp_talloc, "%s,%s", str, Globals.szLdapSuffix );
3280         if ( !suffix_string ) {
3281                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3282                 return "";
3283         }
3284
3285         return suffix_string;
3286 }
3287
3288 const char *lp_ldap_machine_suffix(void)
3289 {
3290         if (Globals.szLdapMachineSuffix[0])
3291                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3292
3293         return lp_string(Globals.szLdapSuffix);
3294 }
3295
3296 const char *lp_ldap_user_suffix(void)
3297 {
3298         if (Globals.szLdapUserSuffix[0])
3299                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3300
3301         return lp_string(Globals.szLdapSuffix);
3302 }
3303
3304 const char *lp_ldap_group_suffix(void)
3305 {
3306         if (Globals.szLdapGroupSuffix[0])
3307                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3308
3309         return lp_string(Globals.szLdapSuffix);
3310 }
3311
3312 const char *lp_ldap_idmap_suffix(void)
3313 {
3314         if (Globals.szLdapIdmapSuffix[0])
3315                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3316
3317         return lp_string(Globals.szLdapSuffix);
3318 }
3319
3320 /****************************************************************************
3321  set the value for a P_ENUM
3322  ***************************************************************************/
3323
3324 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3325                               int *ptr )
3326 {
3327         int i;
3328
3329         for (i = 0; parm->enum_list[i].name; i++) {
3330                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3331                         *ptr = parm->enum_list[i].value;
3332                         break;
3333                 }
3334         }
3335 }
3336
3337 /***************************************************************************
3338 ***************************************************************************/
3339
3340 static BOOL handle_printing(int snum, const char *pszParmValue, char **ptr)
3341 {
3342         static int parm_num = -1;
3343         service *s;
3344
3345         if ( parm_num == -1 )
3346                 parm_num = map_parameter( "printing" );
3347
3348         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3349
3350         if ( snum < 0 )
3351                 s = &sDefault;
3352         else
3353                 s = ServicePtrs[snum];
3354
3355         init_printer_values( s );
3356
3357         return True;
3358 }
3359
3360
3361 /***************************************************************************
3362  Initialise a copymap.
3363 ***************************************************************************/
3364
3365 static void init_copymap(service * pservice)
3366 {
3367         int i;
3368         SAFE_FREE(pservice->copymap);
3369         pservice->copymap = SMB_MALLOC_ARRAY(BOOL,NUMPARAMETERS);
3370         if (!pservice->copymap)
3371                 DEBUG(0,
3372                       ("Couldn't allocate copymap!! (size %d)\n",
3373                        (int)NUMPARAMETERS));
3374         else
3375                 for (i = 0; i < NUMPARAMETERS; i++)
3376                         pservice->copymap[i] = True;
3377 }
3378
3379 /***************************************************************************
3380  Return the local pointer to a parameter given the service number and the 
3381  pointer into the default structure.
3382 ***************************************************************************/
3383
3384 void *lp_local_ptr(int snum, void *ptr)
3385 {
3386         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3387 }
3388
3389 /***************************************************************************
3390  Process a parameter for a particular service number. If snum < 0
3391  then assume we are in the globals.
3392 ***************************************************************************/
3393
3394 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3395 {
3396         int parmnum, i, slen;
3397         void *parm_ptr = NULL;  /* where we are going to store the result */
3398         void *def_ptr = NULL;
3399         pstring param_key;
3400         char *sep;
3401         param_opt_struct *paramo, *data;
3402         BOOL not_added;
3403
3404         parmnum = map_parameter(pszParmName);
3405
3406         if (parmnum < 0) {
3407                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3408                         *sep = '\0';
3409                         ZERO_STRUCT(param_key);
3410                         pstr_sprintf(param_key, "%s:", pszParmName);
3411                         slen = strlen(param_key);
3412                         pstrcat(param_key, sep+1);
3413                         trim_char(param_key+slen, ' ', ' ');
3414                         not_added = True;
3415                         data = (snum < 0) ? Globals.param_opt : 
3416                                 ServicePtrs[snum]->param_opt;
3417                         /* Traverse destination */
3418                         while (data) {
3419                                 /* If we already have same option, override it */
3420                                 if (strcmp(data->key, param_key) == 0) {
3421                                         string_free(&data->value);
3422                                         str_list_free(&data->list);
3423                                         data->value = SMB_STRDUP(pszParmValue);
3424                                         not_added = False;
3425                                         break;
3426                                 }
3427                                 data = data->next;
3428                         }
3429                         if (not_added) {
3430                                 paramo = SMB_XMALLOC_P(param_opt_struct);
3431                                 paramo->key = SMB_STRDUP(param_key);
3432                                 paramo->value = SMB_STRDUP(pszParmValue);
3433                                 paramo->list = NULL;
3434                                 if (snum < 0) {
3435                                         DLIST_ADD(Globals.param_opt, paramo);
3436                                 } else {
3437                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3438                                 }
3439                         }
3440
3441                         *sep = ':';
3442                         return (True);
3443                 }
3444                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3445                 return (True);
3446         }
3447
3448         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3449                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3450                           pszParmName));
3451         }
3452
3453         def_ptr = parm_table[parmnum].ptr;
3454
3455         /* we might point at a service, the default service or a global */
3456         if (snum < 0) {
3457                 parm_ptr = def_ptr;
3458         } else {
3459                 if (parm_table[parmnum].p_class == P_GLOBAL) {
3460                         DEBUG(0,
3461                               ("Global parameter %s found in service section!\n",
3462                                pszParmName));
3463                         return (True);
3464                 }
3465                 parm_ptr =
3466                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3467                                                             &sDefault);
3468         }
3469
3470         if (snum >= 0) {
3471                 if (!ServicePtrs[snum]->copymap)
3472                         init_copymap(ServicePtrs[snum]);
3473
3474                 /* this handles the aliases - set the copymap for other entries with
3475                    the same data pointer */
3476                 for (i = 0; parm_table[i].label; i++)
3477                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3478                                 ServicePtrs[snum]->copymap[i] = False;
3479         }
3480
3481         /* if it is a special case then go ahead */
3482         if (parm_table[parmnum].special) {
3483                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
3484                 return (True);
3485         }
3486
3487         /* now switch on the type of variable it is */
3488         switch (parm_table[parmnum].type)
3489         {
3490                 case P_BOOL:
3491                         *(BOOL *)parm_ptr = lp_bool(pszParmValue);
3492                         break;
3493
3494                 case P_BOOLREV:
3495                         *(BOOL *)parm_ptr = !lp_bool(pszParmValue);
3496                         break;
3497
3498                 case P_INTEGER:
3499                         *(int *)parm_ptr = lp_int(pszParmValue);
3500                         break;
3501
3502                 case P_CHAR:
3503                         *(char *)parm_ptr = *pszParmValue;
3504                         break;
3505
3506                 case P_OCTAL:
3507                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
3508                         if ( i != 1 ) {
3509                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
3510                         }
3511                         break;
3512
3513                 case P_LIST:
3514                         str_list_free((char ***)parm_ptr);
3515                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
3516                         break;
3517
3518                 case P_STRING:
3519                         string_set((char **)parm_ptr, pszParmValue);
3520                         break;
3521
3522                 case P_USTRING:
3523                         string_set((char **)parm_ptr, pszParmValue);
3524                         strupper_m(*(char **)parm_ptr);
3525                         break;
3526
3527                 case P_GSTRING:
3528                         pstrcpy((char *)parm_ptr, pszParmValue);
3529                         break;
3530
3531                 case P_UGSTRING:
3532                         pstrcpy((char *)parm_ptr, pszParmValue);
3533                         strupper_m((char *)parm_ptr);
3534                         break;
3535
3536                 case P_ENUM:
3537                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
3538                         break;
3539                 case P_SEP:
3540                         break;
3541         }
3542
3543         return (True);
3544 }
3545
3546 /***************************************************************************
3547  Process a parameter.
3548 ***************************************************************************/
3549
3550 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
3551 {
3552         if (!bInGlobalSection && bGlobalOnly)
3553                 return (True);
3554
3555         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3556
3557         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3558                                 pszParmName, pszParmValue));
3559 }
3560
3561 /***************************************************************************
3562  Print a parameter of the specified type.
3563 ***************************************************************************/
3564
3565 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3566 {
3567         int i;
3568         switch (p->type)
3569         {
3570                 case P_ENUM:
3571                         for (i = 0; p->enum_list[i].name; i++) {
3572                                 if (*(int *)ptr == p->enum_list[i].value) {
3573                                         fprintf(f, "%s",
3574                                                 p->enum_list[i].name);
3575                                         break;
3576                                 }
3577                         }
3578                         break;
3579
3580                 case P_BOOL:
3581                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
3582                         break;
3583
3584                 case P_BOOLREV:
3585                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
3586                         break;
3587
3588                 case P_INTEGER:
3589                         fprintf(f, "%d", *(int *)ptr);
3590                         break;
3591
3592                 case P_CHAR:
3593                         fprintf(f, "%c", *(char *)ptr);
3594                         break;
3595
3596                 case P_OCTAL:
3597                         fprintf(f, "%s", octal_string(*(int *)ptr));
3598                         break;
3599
3600                 case P_LIST:
3601                         if ((char ***)ptr && *(char ***)ptr) {
3602                                 char **list = *(char ***)ptr;
3603                                 
3604                                 for (; *list; list++) {
3605                                         /* surround strings with whitespace in double quotes */
3606                                         if ( strchr_m( *list, ' ' ) )
3607                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
3608                                         else
3609                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
3610                                 }
3611                         }
3612                         break;
3613
3614                 case P_GSTRING:
3615                 case P_UGSTRING:
3616                         if ((char *)ptr) {
3617                                 fprintf(f, "%s", (char *)ptr);
3618                         }
3619                         break;
3620
3621                 case P_STRING:
3622                 case P_USTRING:
3623                         if (*(char **)ptr) {
3624                                 fprintf(f, "%s", *(char **)ptr);
3625                         }
3626                         break;
3627                 case P_SEP:
3628                         break;
3629         }
3630 }
3631
3632 /***************************************************************************
3633  Check if two parameters are equal.
3634 ***************************************************************************/
3635
3636 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
3637 {
3638         switch (type) {
3639                 case P_BOOL:
3640                 case P_BOOLREV:
3641                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
3642
3643                 case P_INTEGER:
3644                 case P_ENUM:
3645                 case P_OCTAL:
3646                         return (*((int *)ptr1) == *((int *)ptr2));
3647
3648                 case P_CHAR:
3649                         return (*((char *)ptr1) == *((char *)ptr2));
3650                 
3651                 case P_LIST:
3652                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
3653
3654                 case P_GSTRING:
3655                 case P_UGSTRING:
3656                 {
3657                         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
3658                         if (p1 && !*p1)
3659                                 p1 = NULL;
3660                         if (p2 && !*p2)
3661                                 p2 = NULL;
3662                         return (p1 == p2 || strequal(p1, p2));
3663                 }
3664                 case P_STRING:
3665                 case P_USTRING:
3666                 {
3667                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3668                         if (p1 && !*p1)
3669                                 p1 = NULL;
3670                         if (p2 && !*p2)
3671                                 p2 = NULL;
3672                         return (p1 == p2 || strequal(p1, p2));
3673                 }
3674                 case P_SEP:
3675                         break;
3676         }
3677         return (False);
3678 }
3679
3680 /***************************************************************************
3681  Initialize any local varients in the sDefault table.
3682 ***************************************************************************/
3683
3684 void init_locals(void)
3685 {
3686         /* None as yet. */
3687 }
3688
3689 /***************************************************************************
3690  Process a new section (service). At this stage all sections are services.
3691  Later we'll have special sections that permit server parameters to be set.
3692  Returns True on success, False on failure. 
3693 ***************************************************************************/
3694
3695 static BOOL do_section(const char *pszSectionName)
3696 {
3697         BOOL bRetval;
3698         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3699                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3700         bRetval = False;
3701
3702         /* if we were in a global section then do the local inits */
3703         if (bInGlobalSection && !isglobal)
3704                 init_locals();
3705
3706         /* if we've just struck a global section, note the fact. */
3707         bInGlobalSection = isglobal;
3708
3709         /* check for multiple global sections */
3710         if (bInGlobalSection) {
3711                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3712                 return (True);
3713         }
3714
3715         if (!bInGlobalSection && bGlobalOnly)
3716                 return (True);
3717
3718         /* if we have a current service, tidy it up before moving on */
3719         bRetval = True;
3720
3721         if (iServiceIndex >= 0)
3722                 bRetval = service_ok(iServiceIndex);
3723
3724         /* if all is still well, move to the next record in the services array */
3725         if (bRetval) {
3726                 /* We put this here to avoid an odd message order if messages are */
3727                 /* issued by the post-processing of a previous section. */
3728                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3729
3730                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
3731                     < 0) {
3732                         DEBUG(0, ("Failed to add a new service\n"));
3733                         return (False);
3734                 }
3735         }
3736
3737         return (bRetval);
3738 }
3739
3740
3741 /***************************************************************************
3742  Determine if a partcular base parameter is currentl set to the default value.
3743 ***************************************************************************/
3744
3745 static BOOL is_default(int i)
3746 {
3747         if (!defaults_saved)
3748                 return False;
3749         switch (parm_table[i].type) {
3750                 case P_LIST:
3751                         return str_list_compare (parm_table[i].def.lvalue, 
3752                                                 *(char ***)parm_table[i].ptr);
3753                 case P_STRING:
3754                 case P_USTRING:
3755                         return strequal(parm_table[i].def.svalue,
3756                                         *(char **)parm_table[i].ptr);
3757                 case P_GSTRING:
3758                 case P_UGSTRING:
3759                         return strequal(parm_table[i].def.svalue,
3760                                         (char *)parm_table[i].ptr);
3761                 case P_BOOL:
3762                 case P_BOOLREV:
3763                         return parm_table[i].def.bvalue ==
3764                                 *(BOOL *)parm_table[i].ptr;
3765                 case P_CHAR:
3766                         return parm_table[i].def.cvalue ==
3767                                 *(char *)parm_table[i].ptr;
3768                 case P_INTEGER:
3769                 case P_OCTAL:
3770                 case P_ENUM:
3771                         return parm_table[i].def.ivalue ==
3772                                 *(int *)parm_table[i].ptr;
3773                 case P_SEP:
3774                         break;
3775         }
3776         return False;
3777 }
3778
3779 /***************************************************************************
3780 Display the contents of the global structure.
3781 ***************************************************************************/
3782
3783 static void dump_globals(FILE *f)
3784 {
3785         int i;
3786         param_opt_struct *data;
3787         
3788         fprintf(f, "[global]\n");
3789
3790         for (i = 0; parm_table[i].label; i++)
3791                 if (parm_table[i].p_class == P_GLOBAL &&
3792                     parm_table[i].ptr &&
3793                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3794                         if (defaults_saved && is_default(i))
3795                                 continue;
3796                         fprintf(f, "\t%s = ", parm_table[i].label);
3797                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
3798                         fprintf(f, "\n");
3799         }
3800         if (Globals.param_opt != NULL) {
3801                 data = Globals.param_opt;
3802                 while(data) {
3803                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3804                         data = data->next;
3805                 }
3806         }
3807
3808 }
3809
3810 /***************************************************************************
3811  Return True if a local parameter is currently set to the global default.
3812 ***************************************************************************/
3813
3814 BOOL lp_is_default(int snum, struct parm_struct *parm)
3815 {
3816         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
3817
3818         return equal_parameter(parm->type,
3819                                ((char *)ServicePtrs[snum]) + pdiff,
3820                                ((char *)&sDefault) + pdiff);
3821 }
3822
3823 /***************************************************************************
3824  Display the contents of a single services record.
3825 ***************************************************************************/
3826
3827 static void dump_a_service(service * pService, FILE * f)
3828 {
3829         int i;
3830         param_opt_struct *data;
3831         
3832         if (pService != &sDefault)
3833                 fprintf(f, "[%s]\n", pService->szService);
3834
3835         for (i = 0; parm_table[i].label; i++) {
3836
3837                 if (parm_table[i].p_class == P_LOCAL &&
3838                     parm_table[i].ptr &&
3839                     (*parm_table[i].label != '-') &&
3840                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3841                 {
3842                 
3843                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
3844
3845                         if (pService == &sDefault) {
3846                                 if (defaults_saved && is_default(i))
3847                                         continue;
3848                         } else {
3849                                 if (equal_parameter(parm_table[i].type,
3850                                                     ((char *)pService) +
3851                                                     pdiff,
3852                                                     ((char *)&sDefault) +
3853                                                     pdiff))
3854                                         continue;
3855                         }
3856
3857                         fprintf(f, "\t%s = ", parm_table[i].label);
3858                         print_parameter(&parm_table[i],
3859                                         ((char *)pService) + pdiff, f);
3860                         fprintf(f, "\n");
3861                 }
3862         }
3863
3864                 if (pService->param_opt != NULL) {
3865                         data = pService->param_opt;
3866                         while(data) {
3867                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
3868                                 data = data->next;
3869                         }
3870                 }
3871 }
3872
3873 /***************************************************************************
3874  Display the contents of a parameter of a single services record.
3875 ***************************************************************************/
3876
3877 BOOL dump_a_parameter(int snum, char *parm_name, FILE * f, BOOL isGlobal)
3878 {
3879         int i;
3880         BOOL result = False;
3881         parm_class p_class;
3882         unsigned flag = 0;
3883         fstring local_parm_name;
3884         char *parm_opt;
3885         const char *parm_opt_value;
3886
3887         /* check for parametrical option */
3888         fstrcpy( local_parm_name, parm_name);
3889         parm_opt = strchr( local_parm_name, ':');
3890
3891         if (parm_opt) {
3892                 *parm_opt = '\0';
3893                 parm_opt++;
3894                 if (strlen(parm_opt)) {
3895                         parm_opt_value = lp_parm_const_string( snum,
3896                                 local_parm_name, parm_opt, NULL);
3897                         if (parm_opt_value) {
3898                                 printf( "%s\n", parm_opt_value);
3899                                 result = True;
3900                         }
3901                 }
3902                 return result;
3903         }
3904
3905         /* check for a key and print the value */
3906         if (isGlobal) {
3907                 p_class = P_GLOBAL;
3908                 flag = FLAG_GLOBAL;
3909         } else
3910                 p_class = P_LOCAL;
3911
3912         for (i = 0; parm_table[i].label; i++) {
3913                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
3914                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
3915                     parm_table[i].ptr &&
3916                     (*parm_table[i].label != '-') &&
3917                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
3918                 {
3919                         void *ptr;
3920
3921                         if (isGlobal) {
3922                                 ptr = parm_table[i].ptr;
3923                         } else {
3924                                 service * pService = ServicePtrs[snum];
3925                                 ptr = ((char *)pService) +
3926                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
3927                         }
3928
3929                         print_parameter(&parm_table[i],
3930                                         ptr, f);
3931                         fprintf(f, "\n");
3932                         result = True;
3933                         break;
3934                 }
3935         }
3936
3937         return result;
3938 }
3939
3940 /***************************************************************************
3941  Return info about the next service  in a service. snum==GLOBAL_SECTION_SNUM gives the globals.
3942  Return NULL when out of parameters.
3943 ***************************************************************************/
3944
3945 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3946 {
3947         if (snum < 0) {
3948                 /* do the globals */
3949                 for (; parm_table[*i].label; (*i)++) {
3950                         if (parm_table[*i].p_class == P_SEPARATOR)
3951                                 return &parm_table[(*i)++];
3952
3953                         if (!parm_table[*i].ptr
3954                             || (*parm_table[*i].label == '-'))
3955                                 continue;
3956
3957                         if ((*i) > 0
3958                             && (parm_table[*i].ptr ==
3959                                 parm_table[(*i) - 1].ptr))
3960                                 continue;
3961
3962                         return &parm_table[(*i)++];
3963                 }
3964         } else {
3965                 service *pService = ServicePtrs[snum];
3966
3967                 for (; parm_table[*i].label; (*i)++) {
3968                         if (parm_table[*i].p_class == P_SEPARATOR)
3969                                 return &parm_table[(*i)++];
3970
3971                         if (parm_table[*i].p_class == P_LOCAL &&
3972                             parm_table[*i].ptr &&
3973                             (*parm_table[*i].label != '-') &&
3974                             ((*i) == 0 ||
3975                              (parm_table[*i].ptr !=
3976                               parm_table[(*i) - 1].ptr)))
3977                         {
3978                                 int pdiff =
3979                                         PTR_DIFF(parm_table[*i].ptr,
3980                                                  &sDefault);
3981
3982                                 if (allparameters ||
3983                                     !equal_parameter(parm_table[*i].type,
3984                                                      ((char *)pService) +
3985                                                      pdiff,
3986                                                      ((char *)&sDefault) +
3987                                                      pdiff))
3988                                 {
3989                                         return &parm_table[(*i)++];
3990                                 }
3991                         }
3992                 }
3993         }
3994
3995         return NULL;
3996 }
3997
3998
3999 #if 0
4000 /***************************************************************************
4001  Display the contents of a single copy structure.
4002 ***************************************************************************/
4003 static void dump_copy_map(BOOL *pcopymap)
4004 {
4005         int i;
4006         if (!pcopymap)
4007                 return;
4008
4009         printf("\n\tNon-Copied parameters:\n");
4010
4011         for (i = 0; parm_table[i].label; i++)
4012                 if (parm_table[i].p_class == P_LOCAL &&
4013                     parm_table[i].ptr && !pcopymap[i] &&
4014                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4015                 {
4016                         printf("\t\t%s\n", parm_table[i].label);
4017                 }
4018 }
4019 #endif
4020
4021 /***************************************************************************
4022  Return TRUE if the passed service number is within range.
4023 ***************************************************************************/
4024
4025 BOOL lp_snum_ok(int iService)
4026 {
4027         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4028 }
4029
4030 /***************************************************************************
4031  Auto-load some home services.
4032 ***************************************************************************/
4033
4034 static void lp_add_auto_services(char *str)
4035 {
4036         char *s;
4037         char *p;
4038         int homes;
4039
4040         if (!str)
4041                 return;
4042
4043         s = SMB_STRDUP(str);
4044         if (!s)
4045                 return;
4046
4047         homes = lp_servicenumber(HOMES_NAME);
4048
4049         for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
4050                 char *home = get_user_home_dir(p);
4051
4052                 if (lp_servicenumber(p) >= 0)
4053                         continue;
4054
4055                 if (home && homes >= 0)
4056                         lp_add_home(p, homes, p, home);
4057         }
4058         SAFE_FREE(s);
4059 }
4060
4061 /***************************************************************************
4062  Auto-load one printer.
4063 ***************************************************************************/
4064
4065 void lp_add_one_printer(char *name, char *comment)
4066 {
4067         int printers = lp_servicenumber(PRINTERS_NAME);
4068         int i;
4069
4070         if (lp_servicenumber(name) < 0) {
4071                 lp_add_printer(name, printers);
4072                 if ((i = lp_servicenumber(name)) >= 0) {
4073                         string_set(&ServicePtrs[i]->comment, comment);
4074                         ServicePtrs[i]->autoloaded = True;
4075                 }
4076         }
4077 }
4078
4079 /***************************************************************************
4080  Have we loaded a services file yet?
4081 ***************************************************************************/
4082
4083 BOOL lp_loaded(void)
4084 {
4085         return (bLoaded);
4086 }
4087
4088 /***************************************************************************
4089  Unload unused services.
4090 ***************************************************************************/
4091
4092 void lp_killunused(BOOL (*snumused) (int))
4093 {
4094         int i;
4095         for (i = 0; i < iNumServices; i++) {
4096                 if (!VALID(i))
4097                         continue;
4098
4099                 /* don't kill autoloaded or usershare services */
4100                 if ( ServicePtrs[i]->autoloaded ||
4101                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4102                         continue;
4103                 }
4104
4105                 if (!snumused || !snumused(i)) {
4106                         free_service_byindex(i);
4107                 }
4108         }
4109 }
4110
4111 /***************************************************************************
4112  Unload a service.
4113 ***************************************************************************/
4114
4115 void lp_killservice(int iServiceIn)
4116 {
4117         if (VALID(iServiceIn)) {
4118                 free_service_byindex(iServiceIn);
4119         }
4120 }
4121
4122 /***************************************************************************
4123  Save the curent values of all global and sDefault parameters into the 
4124  defaults union. This allows swat and testparm to show only the
4125  changed (ie. non-default) parameters.
4126 ***************************************************************************/
4127
4128 static void lp_save_defaults(void)
4129 {
4130         int i;
4131         for (i = 0; parm_table[i].label; i++) {
4132                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4133                         continue;
4134                 switch (parm_table[i].type) {
4135                         case P_LIST:
4136                                 str_list_copy(&(parm_table[i].def.lvalue),
4137                                             *(const char ***)parm_table[i].ptr);
4138                                 break;
4139                         case P_STRING:
4140                         case P_USTRING:
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_GSTRING:
4148                         case P_UGSTRING:
4149                                 if (parm_table[i].ptr) {
4150                                         parm_table[i].def.svalue = SMB_STRDUP((char *)parm_table[i].ptr);
4151                                 } else {
4152                                         parm_table[i].def.svalue = NULL;
4153                                 }
4154                                 break;
4155                         case P_BOOL:
4156                         case P_BOOLREV:
4157                                 parm_table[i].def.bvalue =
4158                                         *(BOOL *)parm_table[i].ptr;
4159                                 break;
4160                         case P_CHAR:
4161                                 parm_table[i].def.cvalue =
4162                                         *(char *)parm_table[i].ptr;
4163                                 break;
4164                         case P_INTEGER:
4165                         case P_OCTAL:
4166                         case P_ENUM:
4167                                 parm_table[i].def.ivalue =
4168                                         *(int *)parm_table[i].ptr;
4169                                 break;
4170                         case P_SEP:
4171                                 break;
4172                 }
4173         }
4174         defaults_saved = True;
4175 }
4176
4177 /*******************************************************************
4178  Set the server type we will announce as via nmbd.
4179 ********************************************************************/
4180
4181 static const struct srv_role_tab {
4182         uint32 role;
4183         const char *role_str;
4184 } srv_role_tab [] = {
4185         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4186         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4187         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4188         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4189         { 0, NULL }
4190 };
4191
4192 const char* server_role_str(uint32 role)
4193 {
4194         int i = 0;
4195         for (i=0; srv_role_tab[i].role_str; i++) {
4196                 if (role == srv_role_tab[i].role) {
4197                         return srv_role_tab[i].role_str;
4198                 }
4199         }
4200         return NULL;
4201 }
4202
4203 static void set_server_role(void)
4204 {
4205         server_role = ROLE_STANDALONE;
4206
4207         switch (lp_security()) {
4208                 case SEC_SHARE:
4209                         if (lp_domain_logons())
4210                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4211                         break;
4212                 case SEC_SERVER:
4213                         if (lp_domain_logons())
4214                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4215                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4216                         server_role = ROLE_STANDALONE;
4217                         break;
4218                 case SEC_DOMAIN:
4219                         if (lp_domain_logons()) {
4220                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4221                                 server_role = ROLE_DOMAIN_BDC;
4222                                 break;
4223                         }
4224                         server_role = ROLE_DOMAIN_MEMBER;
4225                         break;
4226                 case SEC_ADS:
4227                         if (lp_domain_logons()) {
4228                                 server_role = ROLE_DOMAIN_PDC;
4229                                 break;
4230                         }
4231                         server_role = ROLE_DOMAIN_MEMBER;
4232                         break;
4233                 case SEC_USER:
4234                         if (lp_domain_logons()) {
4235
4236                                 if (Globals.bDomainMaster) /* auto or yes */ 
4237                                         server_role = ROLE_DOMAIN_PDC;
4238                                 else
4239                                         server_role = ROLE_DOMAIN_BDC;
4240                         }
4241                         break;
4242                 default:
4243                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4244                         break;
4245         }
4246
4247         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4248 }
4249
4250 /***********************************************************
4251  If we should send plaintext/LANMAN passwords in the clinet
4252 ************************************************************/
4253
4254 static void set_allowed_client_auth(void)
4255 {
4256         if (Globals.bClientNTLMv2Auth) {
4257                 Globals.bClientLanManAuth = False;
4258         }
4259         if (!Globals.bClientLanManAuth) {
4260                 Globals.bClientPlaintextAuth = False;
4261         }
4262 }
4263
4264 /***************************************************************************
4265  JRA.
4266  The following code allows smbd to read a user defined share file.
4267  Yes, this is my intent. Yes, I'm comfortable with that...
4268
4269  THE FOLLOWING IS SECURITY CRITICAL CODE.
4270
4271  It washes your clothes, it cleans your house, it guards you while you sleep...
4272  Do not f%^k with it....
4273 ***************************************************************************/
4274
4275 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4276
4277 /***************************************************************************
4278  Check allowed stat state of a usershare file.
4279  Ensure we print out who is dicking with us so the admin can
4280  get their sorry ass fired.
4281 ***************************************************************************/
4282
4283 static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4284 {
4285         if (!S_ISREG(psbuf->st_mode)) {
4286                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4287                         "not a regular file\n",
4288                         fname, (unsigned int)psbuf->st_uid ));
4289                 return False;
4290         }
4291
4292         /* Ensure this doesn't have the other write bit set. */
4293         if (psbuf->st_mode & S_IWOTH) {
4294                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4295                         "public write. Refusing to allow as a usershare file.\n",
4296                         fname, (unsigned int)psbuf->st_uid ));
4297                 return False;
4298         }
4299
4300         /* Should be 10k or less. */
4301         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4302                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4303                         "too large (%u) to be a user share file.\n",
4304                         fname, (unsigned int)psbuf->st_uid,
4305                         (unsigned int)psbuf->st_size ));
4306                 return False;
4307         }
4308
4309         return True;
4310 }
4311
4312 /***************************************************************************
4313  Parse the contents of a usershare file.
4314 ***************************************************************************/
4315
4316 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, 
4317                         SMB_STRUCT_STAT *psbuf,
4318                         const char *servicename,
4319                         int snum,
4320                         char **lines,
4321                         int numlines,
4322                         pstring sharepath,
4323                         pstring comment,
4324                         SEC_DESC **ppsd,
4325                         BOOL *pallow_guest)
4326 {
4327         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4328         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4329         int us_vers;
4330         SMB_STRUCT_DIR *dp;
4331         SMB_STRUCT_STAT sbuf;
4332
4333         *pallow_guest = False;
4334
4335         if (numlines < 4) {
4336                 return USERSHARE_MALFORMED_FILE;
4337         }
4338
4339         if (strcmp(lines[0], "#VERSION 1") == 0) {
4340                 us_vers = 1;
4341         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
4342                 us_vers = 2;
4343                 if (numlines < 5) {
4344                         return USERSHARE_MALFORMED_FILE;
4345                 }
4346         } else {
4347                 return USERSHARE_BAD_VERSION;
4348         }
4349
4350         if (strncmp(lines[1], "path=", 5) != 0) {
4351                 return USERSHARE_MALFORMED_PATH;
4352         }
4353
4354         pstrcpy(sharepath, &lines[1][5]);
4355         trim_string(sharepath, " ", " ");
4356
4357         if (strncmp(lines[2], "comment=", 8) != 0) {
4358                 return USERSHARE_MALFORMED_COMMENT_DEF;
4359         }
4360
4361         pstrcpy(comment, &lines[2][8]);
4362         trim_string(comment, " ", " ");
4363         trim_char(comment, '"', '"');
4364
4365         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
4366                 return USERSHARE_MALFORMED_ACL_DEF;
4367         }
4368
4369         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
4370                 return USERSHARE_ACL_ERR;
4371         }
4372
4373         if (us_vers == 2) {
4374                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
4375                         return USERSHARE_MALFORMED_ACL_DEF;
4376                 }
4377                 if (lines[4][9] == 'y') {
4378                         *pallow_guest = True;
4379                 }
4380         }
4381
4382         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
4383                 /* Path didn't change, no checks needed. */
4384                 return USERSHARE_OK;
4385         }
4386
4387         /* The path *must* be absolute. */
4388         if (sharepath[0] != '/') {
4389                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4390                         servicename, sharepath));
4391                 return USERSHARE_PATH_NOT_ABSOLUTE;
4392         }
4393
4394         /* If there is a usershare prefix deny list ensure one of these paths
4395            doesn't match the start of the user given path. */
4396         if (prefixdenylist) {
4397                 int i;
4398                 for ( i=0; prefixdenylist[i]; i++ ) {
4399                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4400                                 servicename, i, prefixdenylist[i], sharepath ));
4401                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
4402                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4403                                         "usershare prefix deny list entries.\n",
4404                                         servicename, sharepath));
4405                                 return USERSHARE_PATH_IS_DENIED;
4406                         }
4407                 }
4408         }
4409
4410         /* If there is a usershare prefix allow list ensure one of these paths
4411            does match the start of the user given path. */
4412
4413         if (prefixallowlist) {
4414                 int i;
4415                 for ( i=0; prefixallowlist[i]; i++ ) {
4416                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4417                                 servicename, i, prefixallowlist[i], sharepath ));
4418                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
4419                                 break;
4420                         }
4421                 }
4422                 if (prefixallowlist[i] == NULL) {
4423                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4424                                 "usershare prefix allow list entries.\n",
4425                                 servicename, sharepath));
4426                         return USERSHARE_PATH_NOT_ALLOWED;
4427                 }
4428         }
4429
4430         /* Ensure this is pointing to a directory. */
4431         dp = sys_opendir(sharepath);
4432
4433         if (!dp) {
4434                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4435                         servicename, sharepath));
4436                 return USERSHARE_PATH_NOT_DIRECTORY;
4437         }
4438
4439         /* Ensure the owner of the usershare file has permission to share
4440            this directory. */
4441
4442         if (sys_stat(sharepath, &sbuf) == -1) {
4443                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4444                         servicename, sharepath, strerror(errno) ));
4445                 sys_closedir(dp);
4446                 return USERSHARE_POSIX_ERR;
4447         }
4448
4449         sys_closedir(dp);
4450
4451         if (!S_ISDIR(sbuf.st_mode)) {
4452                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4453                         servicename, sharepath ));
4454                 return USERSHARE_PATH_NOT_DIRECTORY;
4455         }
4456
4457         /* Check if sharing is restricted to owner-only. */
4458         /* psbuf is the stat of the usershare definition file,
4459            sbuf is the stat of the target directory to be shared. */
4460
4461         if (lp_usershare_owner_only()) {
4462                 /* root can share anything. */
4463                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
4464                         return USERSHARE_PATH_NOT_ALLOWED;
4465                 }
4466         }
4467
4468         return USERSHARE_OK;
4469 }
4470
4471 /***************************************************************************
4472  Deal with a usershare file.
4473  Returns:
4474         >= 0 - snum
4475         -1 - Bad name, invalid contents.
4476            - service name already existed and not a usershare, problem
4477             with permissions to share directory etc.
4478 ***************************************************************************/
4479
4480 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
4481 {
4482         SMB_STRUCT_STAT sbuf;
4483         SMB_STRUCT_STAT lsbuf;
4484         pstring fname;
4485         pstring sharepath;
4486         pstring comment;
4487         fstring service_name;
4488         char **lines = NULL;
4489         int numlines = 0;
4490         int fd = -1;
4491         int iService = -1;
4492         TALLOC_CTX *ctx = NULL;
4493         SEC_DESC *psd = NULL;
4494         BOOL guest_ok = False;
4495
4496         /* Ensure share name doesn't contain invalid characters. */
4497         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
4498                 DEBUG(0,("process_usershare_file: share name %s contains "
4499                         "invalid characters (any of %s)\n",
4500                         file_name, INVALID_SHARENAME_CHARS ));
4501                 return -1;
4502         }
4503
4504         fstrcpy(service_name, file_name);
4505
4506         pstrcpy(fname, dir_name);
4507         pstrcat(fname, "/");
4508         pstrcat(fname, file_name);
4509
4510         /* Minimize the race condition by doing an lstat before we
4511            open and fstat. Ensure this isn't a symlink link. */
4512
4513         if (sys_lstat(fname, &lsbuf) != 0) {
4514                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4515                         fname, strerror(errno) ));
4516                 return -1;
4517         }
4518
4519         /* This must be a regular file, not a symlink, directory or
4520            other strange filetype. */
4521         if (!check_usershare_stat(fname, &lsbuf)) {
4522                 return -1;
4523         }
4524
4525         /* See if there is already a servicenum for this name. */
4526         /* tdb_fetch_int32 returns -1 if not found. */
4527         iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
4528
4529         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
4530                 /* Nothing changed - Mark valid and return. */
4531                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4532                         service_name ));
4533                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
4534                 return iService;
4535         }
4536
4537         /* Try and open the file read only - no symlinks allowed. */
4538 #ifdef O_NOFOLLOW
4539         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
4540 #else
4541         fd = sys_open(fname, O_RDONLY, 0);
4542 #endif
4543
4544         if (fd == -1) {
4545                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4546                         fname, strerror(errno) ));
4547                 return -1;
4548         }
4549
4550         /* Now fstat to be *SURE* it's a regular file. */
4551         if (sys_fstat(fd, &sbuf) != 0) {
4552                 close(fd);
4553                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4554                         fname, strerror(errno) ));
4555                 return -1;
4556         }
4557
4558         /* Is it the same dev/inode as was lstated ? */
4559         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
4560                 close(fd);
4561                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4562                         "Symlink spoofing going on ?\n", fname ));
4563                 return -1;
4564         }
4565
4566         /* This must be a regular file, not a symlink, directory or
4567            other strange filetype. */
4568         if (!check_usershare_stat(fname, &sbuf)) {
4569                 return -1;
4570         }
4571
4572         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
4573
4574         close(fd);
4575         if (lines == NULL) {
4576                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4577                         fname, (unsigned int)sbuf.st_uid ));
4578                 return -1;
4579         }
4580
4581         /* Should we allow printers to be shared... ? */
4582         ctx = talloc_init("usershare_sd_xctx");
4583         if (!ctx) {
4584                 file_lines_free(lines);
4585                 return 1;
4586         }
4587
4588         if (parse_usershare_file(ctx, &sbuf, service_name,
4589                         iService, lines, numlines, sharepath,
4590                         comment, &psd, &guest_ok) != USERSHARE_OK) {
4591                 talloc_destroy(ctx);
4592                 file_lines_free(lines);
4593                 return -1;
4594         }
4595
4596         file_lines_free(lines);
4597
4598         /* Everything ok - add the service possibly using a template. */
4599         if (iService < 0) {
4600                 const service *sp = &sDefault;
4601                 if (snum_template != -1) {
4602                         sp = ServicePtrs[snum_template];
4603                 }
4604
4605                 if ((iService = add_a_service(sp, service_name)) < 0) {
4606                         DEBUG(0, ("process_usershare_file: Failed to add "
4607                                 "new service %s\n", service_name));
4608                         talloc_destroy(ctx);
4609                         return -1;
4610                 }
4611
4612                 /* Read only is controlled by usershare ACL below. */
4613                 ServicePtrs[iService]->bRead_only = False;
4614         }
4615
4616         /* Write the ACL of the new/modified share. */
4617         if (!set_share_security(service_name, psd)) {
4618                  DEBUG(0, ("process_usershare_file: Failed to set share "
4619                         "security for user share %s\n",
4620                         service_name ));
4621                 lp_remove_service(iService);
4622                 talloc_destroy(ctx);
4623                 return -1;
4624         }
4625
4626         talloc_destroy(ctx);
4627
4628         /* If from a template it may be marked invalid. */
4629         ServicePtrs[iService]->valid = True;
4630
4631         /* Set the service as a valid usershare. */
4632         ServicePtrs[iService]->usershare = USERSHARE_VALID;
4633
4634         /* Set guest access. */
4635         if (lp_usershare_allow_guests()) {
4636                 ServicePtrs[iService]->bGuest_ok = guest_ok;
4637         }
4638
4639         /* And note when it was loaded. */
4640         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
4641         string_set(&ServicePtrs[iService]->szPath, sharepath);
4642         string_set(&ServicePtrs[iService]->comment, comment);
4643
4644         return iService;
4645 }
4646
4647 /***************************************************************************
4648  Checks if a usershare entry has been modified since last load.
4649 ***************************************************************************/
4650
4651 static BOOL usershare_exists(int iService, time_t *last_mod)
4652 {
4653         SMB_STRUCT_STAT lsbuf;
4654         const char *usersharepath = Globals.szUsersharePath;
4655         pstring fname;
4656
4657         pstrcpy(fname, usersharepath);
4658         pstrcat(fname, "/");
4659         pstrcat(fname, ServicePtrs[iService]->szService);
4660
4661         if (sys_lstat(fname, &lsbuf) != 0) {
4662                 return False;
4663         }
4664
4665         if (!S_ISREG(lsbuf.st_mode)) {
4666                 return False;
4667         }
4668
4669         *last_mod = lsbuf.st_mtime;
4670         return True;
4671 }
4672
4673 /***************************************************************************
4674  Load a usershare service by name. Returns a valid servicenumber or -1.
4675 ***************************************************************************/
4676
4677 int load_usershare_service(const char *servicename)
4678 {
4679         SMB_STRUCT_STAT sbuf;
4680         const char *usersharepath = Globals.szUsersharePath;
4681         int max_user_shares = Globals.iUsershareMaxShares;
4682         int snum_template = -1;
4683
4684         if (*usersharepath == 0 ||  max_user_shares == 0) {
4685                 return -1;
4686         }
4687
4688         if (sys_stat(usersharepath, &sbuf) != 0) {
4689                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4690                         usersharepath, strerror(errno) ));
4691                 return -1;
4692         }
4693
4694         if (!S_ISDIR(sbuf.st_mode)) {
4695                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4696                         usersharepath ));
4697                 return -1;
4698         }
4699
4700         /*
4701          * This directory must be owned by root, and have the 't' bit set.
4702          * It also must not be writable by "other".
4703          */
4704
4705 #ifdef S_ISVTX
4706         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4707 #else
4708         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4709 #endif
4710                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4711                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4712                         usersharepath ));
4713                 return -1;
4714         }
4715
4716         /* Ensure the template share exists if it's set. */
4717         if (Globals.szUsershareTemplateShare[0]) {
4718                 /* We can't use lp_servicenumber here as we are recommending that
4719                    template shares have -valid=False set. */
4720                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4721                         if (ServicePtrs[snum_template]->szService &&
4722                                         strequal(ServicePtrs[snum_template]->szService,
4723                                                 Globals.szUsershareTemplateShare)) {
4724                                 break;
4725                         }
4726                 }
4727
4728                 if (snum_template == -1) {
4729                         DEBUG(0,("load_usershare_service: usershare template share %s "
4730                                 "does not exist.\n",
4731                                 Globals.szUsershareTemplateShare ));
4732                         return -1;
4733                 }
4734         }
4735
4736         return process_usershare_file(usersharepath, servicename, snum_template);
4737 }
4738
4739 /***************************************************************************
4740  Load all user defined shares from the user share directory.
4741  We only do this if we're enumerating the share list.
4742  This is the function that can delete usershares that have
4743  been removed.
4744 ***************************************************************************/
4745
4746 int load_usershare_shares(void)
4747 {
4748         SMB_STRUCT_DIR *dp;
4749         SMB_STRUCT_STAT sbuf;
4750         SMB_STRUCT_DIRENT *de;
4751         int num_usershares = 0;
4752         int max_user_shares = Globals.iUsershareMaxShares;
4753         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
4754         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
4755         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
4756         int iService;
4757         int snum_template = -1;
4758         const char *usersharepath = Globals.szUsersharePath;
4759         int ret = lp_numservices();
4760
4761         if (max_user_shares == 0 || *usersharepath == '\0') {
4762                 return lp_numservices();
4763         }
4764
4765         if (sys_stat(usersharepath, &sbuf) != 0) {
4766                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4767                         usersharepath, strerror(errno) ));
4768                 return ret;
4769         }
4770
4771         /*
4772          * This directory must be owned by root, and have the 't' bit set.
4773          * It also must not be writable by "other".
4774          */
4775
4776 #ifdef S_ISVTX
4777         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
4778 #else
4779         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
4780 #endif
4781                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4782                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
4783                         usersharepath ));
4784                 return ret;
4785         }
4786
4787         /* Ensure the template share exists if it's set. */
4788         if (Globals.szUsershareTemplateShare[0]) {
4789                 /* We can't use lp_servicenumber here as we are recommending that
4790                    template shares have -valid=False set. */
4791                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
4792                         if (ServicePtrs[snum_template]->szService &&
4793                                         strequal(ServicePtrs[snum_template]->szService,
4794                                                 Globals.szUsershareTemplateShare)) {
4795                                 break;
4796                         }
4797                 }
4798
4799                 if (snum_template == -1) {
4800                         DEBUG(0,("load_usershare_shares: usershare template share %s "
4801                                 "does not exist.\n",
4802                                 Globals.szUsershareTemplateShare ));
4803                         return ret;
4804                 }
4805         }
4806
4807         /* Mark all existing usershares as pending delete. */
4808         for (iService = iNumServices - 1; iService >= 0; iService--) {
4809                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
4810                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
4811                 }
4812         }
4813
4814         dp = sys_opendir(usersharepath);
4815         if (!dp) {
4816                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4817                         usersharepath, strerror(errno) ));
4818                 return ret;
4819         }
4820
4821         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
4822                         (de = sys_readdir(dp));
4823                         num_dir_entries++ ) {
4824                 int r;
4825                 const char *n = de->d_name;
4826
4827                 /* Ignore . and .. */
4828                 if (*n == '.') {
4829                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
4830                                 continue;
4831                         }
4832                 }
4833
4834                 if (n[0] == ':') {
4835                         /* Temporary file used when creating a share. */
4836                         num_tmp_dir_entries++;
4837                 }
4838
4839                 /* Allow 20% tmp entries. */
4840                 if (num_tmp_dir_entries > allowed_tmp_entries) {
4841                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4842                                 "in directory %s\n",
4843                                 num_tmp_dir_entries, usersharepath));
4844                         break;
4845                 }
4846
4847                 r = process_usershare_file(usersharepath, n, snum_template);
4848                 if (r == 0) {
4849                         /* Update the services count. */
4850                         num_usershares++;
4851                         if (num_usershares >= max_user_shares) {
4852                                 DEBUG(0,("load_usershare_shares: max user shares reached "
4853                                         "on file %s in directory %s\n",
4854                                         n, usersharepath ));
4855                                 break;
4856                         }
4857                 } else if (r == -1) {
4858                         num_bad_dir_entries++;
4859                 }
4860
4861                 /* Allow 20% bad entries. */
4862                 if (num_bad_dir_entries > allowed_bad_entries) {
4863                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4864                                 "in directory %s\n",
4865                                 num_bad_dir_entries, usersharepath));
4866                         break;
4867                 }
4868
4869                 /* Allow 20% bad entries. */
4870                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
4871                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4872                         "in directory %s\n",
4873                         num_dir_entries, usersharepath));
4874                         break;
4875                 }
4876         }
4877
4878         sys_closedir(dp);
4879
4880         /* Sweep through and delete any non-refreshed usershares that are
4881            not currently in use. */
4882         for (iService = iNumServices - 1; iService >= 0; iService--) {
4883                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
4884                         if (conn_snum_used(iService)) {
4885                                 continue;
4886                         }
4887                         /* Remove from the share ACL db. */
4888                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4889                                 lp_servicename(iService) ));
4890                         delete_share_security(snum2params_static(iService));
4891                         free_service_byindex(iService);
4892                 }
4893         }
4894
4895         return lp_numservices();
4896 }
4897
4898 /********************************************************
4899  Destroy global resources allocated in this file
4900 ********************************************************/
4901
4902 void gfree_loadparm(void)
4903 {
4904         struct file_lists *f;
4905         struct file_lists *next;
4906         int i;
4907
4908         lp_TALLOC_FREE();
4909
4910         /* Free the file lists */
4911
4912         f = file_lists;
4913         while( f ) {
4914                 next = f->next;
4915                 SAFE_FREE( f->name );
4916                 SAFE_FREE( f->subfname );
4917                 SAFE_FREE( f );
4918                 f = next;
4919         }
4920
4921         /* Free resources allocated to services */
4922
4923         for ( i = 0; i < iNumServices; i++ ) {
4924                 if ( VALID(i) ) {
4925                         free_service_byindex(i);
4926                 }
4927         }
4928
4929         SAFE_FREE( ServicePtrs );
4930         iNumServices = 0;
4931
4932         /* Now release all resources allocated to global
4933            parameters and the default service */
4934
4935         for (i = 0; parm_table[i].label; i++) 
4936         {
4937                 if ( parm_table[i].type == P_STRING 
4938                         || parm_table[i].type == P_USTRING ) 
4939                 {
4940                         string_free( (char**)parm_table[i].ptr );
4941                 }
4942                 else if (parm_table[i].type == P_LIST) {
4943                         str_list_free( (char***)parm_table[i].ptr );
4944                 }
4945         }
4946 }
4947
4948 /***************************************************************************
4949  Load the services array from the services file. Return True on success, 
4950  False on failure.
4951 ***************************************************************************/
4952
4953 BOOL lp_load(const char *pszFname,
4954              BOOL global_only,
4955              BOOL save_defaults,
4956              BOOL add_ipc,
4957              BOOL initialize_globals)
4958 {
4959         pstring n2;
4960         BOOL bRetval;
4961         param_opt_struct *data, *pdata;
4962
4963         pstrcpy(n2, pszFname);
4964         
4965         standard_sub_basic( get_current_username(), current_user_info.domain,
4966                             n2,sizeof(n2) );
4967
4968         add_to_file_list(pszFname, n2);
4969
4970         bRetval = False;
4971
4972         DEBUG(3, ("lp_load: refreshing parameters\n"));
4973         
4974         bInGlobalSection = True;
4975         bGlobalOnly = global_only;
4976
4977         init_globals(! initialize_globals);
4978         debug_init();
4979
4980         if (save_defaults) {
4981                 init_locals();
4982                 lp_save_defaults();
4983         }
4984
4985         if (Globals.param_opt != NULL) {
4986                 data = Globals.param_opt;
4987                 while (data) {
4988                         string_free(&data->key);
4989                         string_free(&data->value);
4990                         str_list_free(&data->list);
4991                         pdata = data->next;
4992                         SAFE_FREE(data);
4993                         data = pdata;
4994                 }
4995                 Globals.param_opt = NULL;
4996         }
4997         
4998         /* We get sections first, so have to start 'behind' to make up */
4999         iServiceIndex = -1;
5000         bRetval = pm_process(n2, do_section, do_parameter);
5001
5002         /* finish up the last section */
5003         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5004         if (bRetval)
5005                 if (iServiceIndex >= 0)
5006                         bRetval = service_ok(iServiceIndex);
5007
5008         lp_add_auto_services(lp_auto_services());
5009
5010         if (add_ipc) {
5011                 /* When 'restrict anonymous = 2' guest connections to ipc$
5012                    are denied */
5013                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5014                 if ( lp_enable_asu_support() )
5015                         lp_add_ipc("ADMIN$", False);
5016         }
5017
5018         set_server_role();
5019         set_default_server_announce_type();
5020         set_allowed_client_auth();
5021
5022         bLoaded = True;
5023
5024         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5025         /* if bWINSsupport is true and we are in the client            */
5026         if (in_client && Globals.bWINSsupport) {
5027                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5028         }
5029
5030         init_iconv();
5031
5032         return (bRetval);
5033 }
5034
5035 /***************************************************************************
5036  Reset the max number of services.
5037 ***************************************************************************/
5038
5039 void lp_resetnumservices(void)
5040 {
5041         iNumServices = 0;
5042 }
5043
5044 /***************************************************************************
5045  Return the max number of services.
5046 ***************************************************************************/
5047
5048 int lp_numservices(void)
5049 {
5050         return (iNumServices);
5051 }
5052
5053 /***************************************************************************
5054 Display the contents of the services array in human-readable form.
5055 ***************************************************************************/
5056
5057 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
5058 {
5059         int iService;
5060
5061         if (show_defaults)
5062                 defaults_saved = False;
5063
5064         dump_globals(f);
5065
5066         dump_a_service(&sDefault, f);
5067
5068         for (iService = 0; iService < maxtoprint; iService++) {
5069                 fprintf(f,"\n");
5070                 lp_dump_one(f, show_defaults, iService);
5071         }
5072 }
5073
5074 /***************************************************************************
5075 Display the contents of one service in human-readable form.
5076 ***************************************************************************/
5077
5078 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
5079 {
5080         if (VALID(snum)) {
5081                 if (ServicePtrs[snum]->szService[0] == '\0')
5082                         return;
5083                 dump_a_service(ServicePtrs[snum], f);
5084         }
5085 }
5086
5087 /***************************************************************************
5088 Return the number of the service with the given name, or -1 if it doesn't
5089 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5090 getservicebyname()! This works ONLY if all services have been loaded, and
5091 does not copy the found service.
5092 ***************************************************************************/
5093
5094 int lp_servicenumber(const char *pszServiceName)
5095 {
5096         int iService;
5097         fstring serviceName;
5098         
5099         if (!pszServiceName) {
5100                 return GLOBAL_SECTION_SNUM;
5101         }
5102         
5103         for (iService = iNumServices - 1; iService >= 0; iService--) {
5104                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5105                         /*
5106                          * The substitution here is used to support %U is
5107                          * service names
5108                          */
5109                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5110                         standard_sub_basic(get_current_username(),
5111                                            current_user_info.domain,
5112                                            serviceName,sizeof(serviceName));
5113                         if (strequal(serviceName, pszServiceName)) {
5114                                 break;
5115                         }
5116                 }
5117         }
5118
5119         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5120                 time_t last_mod;
5121
5122                 if (!usershare_exists(iService, &last_mod)) {
5123                         /* Remove the share security tdb entry for it. */
5124                         delete_share_security(snum2params_static(iService));
5125                         /* Remove it from the array. */
5126                         free_service_byindex(iService);
5127                         /* Doesn't exist anymore. */
5128                         return GLOBAL_SECTION_SNUM;
5129                 }
5130
5131                 /* Has it been modified ? If so delete and reload. */
5132                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5133                         /* Remove it from the array. */
5134                         free_service_byindex(iService);
5135                         /* and now reload it. */
5136                         iService = load_usershare_service(pszServiceName);
5137                 }
5138         }
5139
5140         if (iService < 0) {
5141                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5142                 return GLOBAL_SECTION_SNUM;
5143         }
5144
5145         return (iService);
5146 }
5147
5148 BOOL share_defined(const char *service_name)
5149 {
5150         return (lp_servicenumber(service_name) != -1);
5151 }
5152
5153 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5154                                       const char *sharename)
5155 {
5156         struct share_params *result;
5157         char *sname;
5158         int snum;
5159
5160         if (!(sname = SMB_STRDUP(sharename))) {
5161                 return NULL;
5162         }
5163
5164         snum = find_service(sname);
5165         SAFE_FREE(sname);
5166
5167         if (snum < 0) {
5168                 return NULL;
5169         }
5170
5171         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5172                 DEBUG(0, ("talloc failed\n"));
5173                 return NULL;
5174         }
5175
5176         result->service = snum;
5177         return result;
5178 }
5179
5180 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5181 {
5182         struct share_iterator *result;
5183
5184         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5185                 DEBUG(0, ("talloc failed\n"));
5186                 return NULL;
5187         }
5188
5189         result->next_id = 0;
5190         return result;
5191 }
5192
5193 struct share_params *next_share(struct share_iterator *list)
5194 {
5195         struct share_params *result;
5196
5197         while (!lp_snum_ok(list->next_id) &&
5198                (list->next_id < lp_numservices())) {
5199                 list->next_id += 1;
5200         }
5201
5202         if (list->next_id >= lp_numservices()) {
5203                 return NULL;
5204         }
5205
5206         if (!(result = TALLOC_P(list, struct share_params))) {
5207                 DEBUG(0, ("talloc failed\n"));
5208                 return NULL;
5209         }
5210
5211         result->service = list->next_id;
5212         list->next_id += 1;
5213         return result;
5214 }
5215
5216 struct share_params *next_printer(struct share_iterator *list)
5217 {
5218         struct share_params *result;
5219
5220         while ((result = next_share(list)) != NULL) {
5221                 if (lp_print_ok(result->service)) {
5222                         break;
5223                 }
5224         }
5225         return result;
5226 }
5227
5228 /*
5229  * This is a hack for a transition period until we transformed all code from
5230  * service numbers to struct share_params.
5231  */
5232
5233 struct share_params *snum2params_static(int snum)
5234 {
5235         static struct share_params result;
5236         result.service = snum;
5237         return &result;
5238 }
5239
5240 /*******************************************************************
5241  A useful volume label function. 
5242 ********************************************************************/
5243
5244 char *volume_label(int snum)
5245 {
5246         char *ret = lp_volume(snum);
5247         if (!*ret)
5248                 return lp_servicename(snum);
5249         return (ret);
5250 }
5251
5252
5253 /*******************************************************************
5254  Set the server type we will announce as via nmbd.
5255 ********************************************************************/
5256
5257 static void set_default_server_announce_type(void)
5258 {
5259         default_server_announce = 0;
5260         default_server_announce |= SV_TYPE_WORKSTATION;
5261         default_server_announce |= SV_TYPE_SERVER;
5262         default_server_announce |= SV_TYPE_SERVER_UNIX;
5263
5264         /* note that the flag should be set only if we have a 
5265            printer service but nmbd doesn't actually load the 
5266            services so we can't tell   --jerry */
5267
5268         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5269
5270         switch (lp_announce_as()) {
5271                 case ANNOUNCE_AS_NT_SERVER:
5272                         default_server_announce |= SV_TYPE_SERVER_NT;
5273                         /* fall through... */
5274                 case ANNOUNCE_AS_NT_WORKSTATION:
5275                         default_server_announce |= SV_TYPE_NT;
5276                         break;
5277                 case ANNOUNCE_AS_WIN95:
5278                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5279                         break;
5280                 case ANNOUNCE_AS_WFW:
5281                         default_server_announce |= SV_TYPE_WFW;
5282                         break;
5283                 default:
5284                         break;
5285         }
5286
5287         switch (lp_server_role()) {
5288                 case ROLE_DOMAIN_MEMBER:
5289                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5290                         break;
5291                 case ROLE_DOMAIN_PDC:
5292                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
5293                         break;
5294                 case ROLE_DOMAIN_BDC:
5295                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
5296                         break;
5297                 case ROLE_STANDALONE:
5298                 default:
5299                         break;
5300         }
5301         if (lp_time_server())
5302                 default_server_announce |= SV_TYPE_TIME_SOURCE;
5303
5304         if (lp_host_msdfs())
5305                 default_server_announce |= SV_TYPE_DFS_SERVER;
5306 }
5307
5308 /***********************************************************
5309  returns role of Samba server
5310 ************************************************************/
5311
5312 int lp_server_role(void)
5313 {
5314         return server_role;
5315 }
5316
5317 /***********************************************************
5318  If we are PDC then prefer us as DMB
5319 ************************************************************/
5320
5321 BOOL lp_domain_master(void)
5322 {
5323         if (Globals.bDomainMaster == Auto)
5324                 return (lp_server_role() == ROLE_DOMAIN_PDC);
5325
5326         return Globals.bDomainMaster;
5327 }
5328
5329 /***********************************************************
5330  If we are DMB then prefer us as LMB
5331 ************************************************************/
5332
5333 BOOL lp_preferred_master(void)
5334 {
5335         if (Globals.bPreferredMaster == Auto)
5336                 return (lp_local_master() && lp_domain_master());
5337
5338         return Globals.bPreferredMaster;
5339 }
5340
5341 /*******************************************************************
5342  Remove a service.
5343 ********************************************************************/
5344
5345 void lp_remove_service(int snum)
5346 {
5347         ServicePtrs[snum]->valid = False;
5348         invalid_services[num_invalid_services++] = snum;
5349 }
5350
5351 /*******************************************************************
5352  Copy a service.
5353 ********************************************************************/
5354
5355 void lp_copy_service(int snum, const char *new_name)
5356 {
5357         do_section(new_name);
5358         if (snum >= 0) {
5359                 snum = lp_servicenumber(new_name);
5360                 if (snum >= 0)
5361                         lp_do_parameter(snum, "copy", lp_servicename(snum));
5362         }
5363 }
5364
5365
5366 /*******************************************************************
5367  Get the default server type we will announce as via nmbd.
5368 ********************************************************************/
5369
5370 int lp_default_server_announce(void)
5371 {
5372         return default_server_announce;
5373 }
5374
5375 /*******************************************************************
5376  Split the announce version into major and minor numbers.
5377 ********************************************************************/
5378
5379 int lp_major_announce_version(void)
5380 {
5381         static BOOL got_major = False;
5382         static int major_version = DEFAULT_MAJOR_VERSION;
5383         char *vers;
5384         char *p;
5385
5386         if (got_major)
5387                 return major_version;
5388
5389         got_major = True;
5390         if ((vers = lp_announce_version()) == NULL)
5391                 return major_version;
5392
5393         if ((p = strchr_m(vers, '.')) == 0)
5394                 return major_version;
5395
5396         *p = '\0';
5397         major_version = atoi(vers);
5398         return major_version;
5399 }
5400
5401 int lp_minor_announce_version(void)
5402 {
5403         static BOOL got_minor = False;
5404         static int minor_version = DEFAULT_MINOR_VERSION;
5405         char *vers;
5406         char *p;
5407
5408         if (got_minor)
5409                 return minor_version;
5410
5411         got_minor = True;
5412         if ((vers = lp_announce_version()) == NULL)
5413                 return minor_version;
5414
5415         if ((p = strchr_m(vers, '.')) == 0)
5416                 return minor_version;
5417
5418         p++;
5419         minor_version = atoi(p);
5420         return minor_version;
5421 }
5422
5423 /***********************************************************
5424  Set the global name resolution order (used in smbclient).
5425 ************************************************************/
5426
5427 void lp_set_name_resolve_order(const char *new_order)
5428 {
5429         string_set(&Globals.szNameResolveOrder, new_order);
5430 }
5431
5432 const char *lp_printername(int snum)
5433 {
5434         const char *ret = _lp_printername(snum);
5435         if (ret == NULL || (ret != NULL && *ret == '\0'))
5436                 ret = lp_const_servicename(snum);
5437
5438         return ret;
5439 }
5440
5441
5442 /***********************************************************
5443  Allow daemons such as winbindd to fix their logfile name.
5444 ************************************************************/
5445
5446 void lp_set_logfile(const char *name)
5447 {
5448         string_set(&Globals.szLogFile, name);
5449         pstrcpy(debugf, name);
5450 }
5451
5452 /*******************************************************************
5453  Return the max print jobs per queue.
5454 ********************************************************************/
5455
5456 int lp_maxprintjobs(int snum)
5457 {
5458         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
5459         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
5460                 maxjobs = PRINT_MAX_JOBID - 1;
5461
5462         return maxjobs;
5463 }
5464
5465 const char *lp_printcapname(void)
5466 {
5467         if ((Globals.szPrintcapname != NULL) &&
5468             (Globals.szPrintcapname[0] != '\0'))
5469                 return Globals.szPrintcapname;
5470
5471         if (sDefault.iPrinting == PRINT_CUPS) {
5472 #ifdef HAVE_CUPS
5473                 return "cups";
5474 #else
5475                 return "lpstat";
5476 #endif
5477         }
5478
5479         if (sDefault.iPrinting == PRINT_BSD)
5480                 return "/etc/printcap";
5481
5482         return PRINTCAP_NAME;
5483 }
5484
5485 /*******************************************************************
5486  Ensure we don't use sendfile if server smb signing is active.
5487 ********************************************************************/
5488
5489 static uint32 spoolss_state;
5490
5491 BOOL lp_disable_spoolss( void )
5492 {
5493         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
5494                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5495
5496         return spoolss_state == SVCCTL_STOPPED ? True : False;
5497 }
5498
5499 void lp_set_spoolss_state( uint32 state )
5500 {
5501         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
5502
5503         spoolss_state = state;
5504 }
5505
5506 uint32 lp_get_spoolss_state( void )
5507 {
5508         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
5509 }
5510
5511 /*******************************************************************
5512  Ensure we don't use sendfile if server smb signing is active.
5513 ********************************************************************/
5514
5515 BOOL lp_use_sendfile(int snum)
5516 {
5517         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5518         if (Protocol < PROTOCOL_NT1) {
5519                 return False;
5520         }
5521         return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && !srv_is_signing_active());
5522 }
5523
5524 /*******************************************************************
5525  Turn off sendfile if we find the underlying OS doesn't support it.
5526 ********************************************************************/
5527
5528 void set_use_sendfile(int snum, BOOL val)
5529 {
5530         if (LP_SNUM_OK(snum))
5531                 ServicePtrs[snum]->bUseSendfile = val;
5532         else
5533                 sDefault.bUseSendfile = val;
5534 }
5535
5536 /*******************************************************************
5537  Turn off storing DOS attributes if this share doesn't support it.
5538 ********************************************************************/
5539
5540 void set_store_dos_attributes(int snum, BOOL val)
5541 {
5542         if (!LP_SNUM_OK(snum))
5543                 return;
5544         ServicePtrs[(snum)]->bStoreDosAttributes = val;
5545 }
5546
5547 void lp_set_mangling_method(const char *new_method)
5548 {
5549         string_set(&Globals.szManglingMethod, new_method);
5550 }
5551
5552 /*******************************************************************
5553  Global state for POSIX pathname processing.
5554 ********************************************************************/
5555
5556 static BOOL posix_pathnames;
5557
5558 BOOL lp_posix_pathnames(void)
5559 {
5560         return posix_pathnames;
5561 }
5562
5563 /*******************************************************************
5564  Change everything needed to ensure POSIX pathname processing (currently
5565  not much).
5566 ********************************************************************/
5567
5568 void lp_set_posix_pathnames(void)
5569 {
5570         posix_pathnames = True;
5571 }
5572
5573 /*******************************************************************
5574  Global state for POSIX lock processing - CIFS unix extensions.
5575 ********************************************************************/
5576
5577 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
5578
5579 enum brl_flavour lp_posix_cifsu_locktype(void)
5580 {
5581         return posix_cifsx_locktype;
5582 }
5583
5584 /*******************************************************************
5585 ********************************************************************/
5586
5587 void lp_set_posix_cifsx_locktype(enum brl_flavour val)
5588 {
5589         posix_cifsx_locktype = val;
5590 }