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