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