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