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