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