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