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