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