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