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