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