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