Save one extra strdup per lp_string. Use talloc_sub_basic()
[kai/samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
12    
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 3 of the License, or
16    (at your option) any later version.
17    
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22    
23    You should have received a copy of the GNU General Public License
24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 /*
28  *  Load parameters.
29  *
30  *  This module provides suitable callback functions for the params
31  *  module. It builds the internal table of service details which is
32  *  then used by the rest of the server.
33  *
34  * To add a parameter:
35  *
36  * 1) add it to the global or service structure definition
37  * 2) add it to the parm_table
38  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
39  * 4) If it's a global then initialise it in init_globals. If a local
40  *    (ie. service) parameter then initialise it in the sDefault structure
41  *  
42  *
43  * Notes:
44  *   The configuration file is processed sequentially for speed. It is NOT
45  *   accessed randomly as happens in 'real' Windows. For this reason, there
46  *   is a fair bit of sequence-dependent code here - ie., code which assumes
47  *   that certain things happen before others. In particular, the code which
48  *   happens at the boundary between sections is delicately poised, so be
49  *   careful!
50  *
51  */
52
53 #include "includes.h"
54
55 bool in_client = False;         /* Not in the client by default */
56 bool bLoaded = False;
57
58 extern 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 TDB_CONTEXT *ServiceHash;
631 static int *invalid_services = NULL;
632 static int num_invalid_services = 0;
633 static bool bInGlobalSection = True;
634 static bool bGlobalOnly = False;
635 static int server_role;
636 static int default_server_announce;
637
638 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
639
640 /* prototypes for the special type handlers */
641 static bool handle_include( int snum, const char *pszParmValue, char **ptr);
642 static bool handle_copy( int snum, const char *pszParmValue, char **ptr);
643 static bool handle_netbios_name( int snum, const char *pszParmValue, char **ptr);
644 static bool handle_idmap_uid( int snum, const char *pszParmValue, char **ptr);
645 static bool handle_idmap_gid( int snum, const char *pszParmValue, char **ptr);
646 static bool handle_debug_list( int snum, const char *pszParmValue, char **ptr );
647 static bool handle_workgroup( int snum, const char *pszParmValue, char **ptr );
648 static bool handle_netbios_aliases( int snum, const char *pszParmValue, char **ptr );
649 static bool handle_netbios_scope( int snum, const char *pszParmValue, char **ptr );
650 static bool handle_charset( int snum, const char *pszParmValue, char **ptr );
651 static bool handle_printing( int snum, const char *pszParmValue, char **ptr);
652
653 static void set_server_role(void);
654 static void set_default_server_announce_type(void);
655 static void set_allowed_client_auth(void);
656
657 static const struct enum_list enum_protocol[] = {
658         {PROTOCOL_NT1, "NT1"},
659         {PROTOCOL_LANMAN2, "LANMAN2"},
660         {PROTOCOL_LANMAN1, "LANMAN1"},
661         {PROTOCOL_CORE, "CORE"},
662         {PROTOCOL_COREPLUS, "COREPLUS"},
663         {PROTOCOL_COREPLUS, "CORE+"},
664         {-1, NULL}
665 };
666
667 static const struct enum_list enum_security[] = {
668         {SEC_SHARE, "SHARE"},
669         {SEC_USER, "USER"},
670         {SEC_SERVER, "SERVER"},
671         {SEC_DOMAIN, "DOMAIN"},
672 #ifdef HAVE_ADS
673         {SEC_ADS, "ADS"},
674 #endif
675         {-1, NULL}
676 };
677
678 static const struct enum_list enum_printing[] = {
679         {PRINT_SYSV, "sysv"},
680         {PRINT_AIX, "aix"},
681         {PRINT_HPUX, "hpux"},
682         {PRINT_BSD, "bsd"},
683         {PRINT_QNX, "qnx"},
684         {PRINT_PLP, "plp"},
685         {PRINT_LPRNG, "lprng"},
686         {PRINT_CUPS, "cups"},
687         {PRINT_IPRINT, "iprint"},
688         {PRINT_LPRNT, "nt"},
689         {PRINT_LPROS2, "os2"},
690 #ifdef DEVELOPER
691         {PRINT_TEST, "test"},
692         {PRINT_VLP, "vlp"},
693 #endif /* DEVELOPER */
694         {-1, NULL}
695 };
696
697 static const struct enum_list enum_ldap_sasl_wrapping[] = {
698         {0, "plain"},
699         {ADS_AUTH_SASL_SIGN, "sign"},
700         {ADS_AUTH_SASL_SEAL, "seal"},
701         {-1, NULL}
702 };
703
704 static const struct enum_list enum_ldap_ssl[] = {
705         {LDAP_SSL_OFF, "no"},
706         {LDAP_SSL_OFF, "No"},
707         {LDAP_SSL_OFF, "off"},
708         {LDAP_SSL_OFF, "Off"},
709         {LDAP_SSL_START_TLS, "start tls"},
710         {LDAP_SSL_START_TLS, "Start_tls"},
711         {-1, NULL}
712 };
713
714 static const struct enum_list enum_ldap_passwd_sync[] = {
715         {LDAP_PASSWD_SYNC_OFF, "no"},
716         {LDAP_PASSWD_SYNC_OFF, "No"},
717         {LDAP_PASSWD_SYNC_OFF, "off"},
718         {LDAP_PASSWD_SYNC_OFF, "Off"},
719         {LDAP_PASSWD_SYNC_ON, "Yes"},
720         {LDAP_PASSWD_SYNC_ON, "yes"},
721         {LDAP_PASSWD_SYNC_ON, "on"},
722         {LDAP_PASSWD_SYNC_ON, "On"},
723         {LDAP_PASSWD_SYNC_ONLY, "Only"},
724         {LDAP_PASSWD_SYNC_ONLY, "only"},
725         {-1, NULL}
726 };
727
728 /* Types of machine we can announce as. */
729 #define ANNOUNCE_AS_NT_SERVER 1
730 #define ANNOUNCE_AS_WIN95 2
731 #define ANNOUNCE_AS_WFW 3
732 #define ANNOUNCE_AS_NT_WORKSTATION 4
733
734 static const struct enum_list enum_announce_as[] = {
735         {ANNOUNCE_AS_NT_SERVER, "NT"},
736         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
737         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
738         {ANNOUNCE_AS_WIN95, "win95"},
739         {ANNOUNCE_AS_WFW, "WfW"},
740         {-1, NULL}
741 };
742
743 static const struct enum_list enum_map_readonly[] = {
744         {MAP_READONLY_NO, "no"},
745         {MAP_READONLY_NO, "false"},
746         {MAP_READONLY_NO, "0"},
747         {MAP_READONLY_YES, "yes"},
748         {MAP_READONLY_YES, "true"},
749         {MAP_READONLY_YES, "1"},
750         {MAP_READONLY_PERMISSIONS, "permissions"},
751         {MAP_READONLY_PERMISSIONS, "perms"},
752         {-1, NULL}
753 };
754
755 static const struct enum_list enum_case[] = {
756         {CASE_LOWER, "lower"},
757         {CASE_UPPER, "upper"},
758         {-1, NULL}
759 };
760
761 static const struct enum_list enum_bool_auto[] = {
762         {False, "No"},
763         {False, "False"},
764         {False, "0"},
765         {True, "Yes"},
766         {True, "True"},
767         {True, "1"},
768         {Auto, "Auto"},
769         {-1, NULL}
770 };
771
772 /* Client-side offline caching policy types */
773 #define CSC_POLICY_MANUAL 0
774 #define CSC_POLICY_DOCUMENTS 1
775 #define CSC_POLICY_PROGRAMS 2
776 #define CSC_POLICY_DISABLE 3
777
778 static const struct enum_list enum_csc_policy[] = {
779         {CSC_POLICY_MANUAL, "manual"},
780         {CSC_POLICY_DOCUMENTS, "documents"},
781         {CSC_POLICY_PROGRAMS, "programs"},
782         {CSC_POLICY_DISABLE, "disable"},
783         {-1, NULL}
784 };
785
786 /* SMB signing types. */
787 static const struct enum_list enum_smb_signing_vals[] = {
788         {False, "No"},
789         {False, "False"},
790         {False, "0"},
791         {False, "Off"},
792         {False, "disabled"},
793         {True, "Yes"},
794         {True, "True"},
795         {True, "1"},
796         {True, "On"},
797         {True, "enabled"},
798         {Auto, "auto"},
799         {Required, "required"},
800         {Required, "mandatory"},
801         {Required, "force"},
802         {Required, "forced"},
803         {Required, "enforced"},
804         {-1, NULL}
805 };
806
807 /* ACL compatibility options. */
808 static const struct enum_list enum_acl_compat_vals[] = {
809     { ACL_COMPAT_AUTO, "auto" },
810     { ACL_COMPAT_WINNT, "winnt" },
811     { ACL_COMPAT_WIN2K, "win2k" },
812     { -1, NULL}
813 };
814
815 /* 
816    Do you want session setups at user level security with a invalid
817    password to be rejected or allowed in as guest? WinNT rejects them
818    but it can be a pain as it means "net view" needs to use a password
819
820    You have 3 choices in the setting of map_to_guest:
821
822    "Never" means session setups with an invalid password
823    are rejected. This is the default.
824
825    "Bad User" means session setups with an invalid password
826    are rejected, unless the username does not exist, in which case it
827    is treated as a guest login
828
829    "Bad Password" means session setups with an invalid password
830    are treated as a guest login
831
832    Note that map_to_guest only has an effect in user or server
833    level security.
834 */
835
836 static const struct enum_list enum_map_to_guest[] = {
837         {NEVER_MAP_TO_GUEST, "Never"},
838         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
839         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
840         {MAP_TO_GUEST_ON_BAD_UID, "Bad Uid"},
841         {-1, NULL}
842 };
843
844 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
845  *
846  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
847  * screen in SWAT. This is used to exclude parameters as well as to squash all
848  * parameters that have been duplicated by pseudonyms.
849  *
850  * NOTE: To display a parameter in BASIC view set FLAG_BASIC
851  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
852  *       Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
853  *        respective views.
854  *
855  * NOTE2: Handling of duplicated (synonym) paramters:
856  *      Only the first occurance of a parameter should be enabled by FLAG_BASIC
857  *      and/or FLAG_ADVANCED. All duplicates following the first mention should be
858  *      set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
859  *      name first, and all synonyms must follow it with the FLAG_HIDE attribute.
860  */
861
862 static struct parm_struct parm_table[] = {
863         {N_("Base Options"), P_SEP, P_SEPARATOR}, 
864
865         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, 
866         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, 
867         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, 
868         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
869         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
870         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, 
871         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
872 #ifdef WITH_ADS
873         {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
874 #endif
875         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
876         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases,  NULL, FLAG_ADVANCED}, 
877         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope,  NULL, FLAG_ADVANCED}, 
878         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED }, 
879         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
880         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
881
882         {N_("Security Options"), P_SEP, P_SEPARATOR}, 
883
884         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
885         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_ADVANCED}, 
886         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, 
887         {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_ADVANCED}, 
888         {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
889         {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, 
890         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, 
891         {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
892         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
893         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
894         {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
895         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
896         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
897         {"passdb backend", P_STRING, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
898         {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
899         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
900         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
901         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, 
902         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, 
903         {"enable privileges", P_BOOL, P_GLOBAL, &Globals.bEnablePrivileges, NULL, NULL, FLAG_ADVANCED}, 
904
905         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED}, 
906         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED}, 
907         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED}, 
908         {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED}, 
909         {"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED}, 
910         {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED}, 
911         {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED}, 
912         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED}, 
913         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED}, 
914         {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED}, 
915         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED}, 
916         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED}, 
917         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED}, 
918         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED}, 
919         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED}, 
920         {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED}, 
921
922         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
923         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
924         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE}, 
925
926         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
927         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
928         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
929         {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
930         {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
931         {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT | FLAG_DEPRECATED }, 
932         {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
933         {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
934         {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, 
935
936         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE}, 
937         {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
938         {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
939         {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE}, 
940
941         {"acl check permissions", P_BOOL, P_LOCAL, &sDefault.bAclCheckPermissions, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
942         {"acl group control", P_BOOL, P_LOCAL, &sDefault.bAclGroupControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE | FLAG_DEPRECATED },
943         {"acl map full control", P_BOOL, P_LOCAL, &sDefault.bAclMapFullControl, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
944         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
945         {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, 
946         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
947         {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
948         {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
949         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
950         {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
951         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
952         {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
953         {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
954         {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE},
955         {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
956         {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
957         {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
958         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
959         {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, 
960
961         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
962         {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, 
963
964         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED}, 
965         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
966         {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE}, 
967         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
968         {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, 
969         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
970         {"use kerberos keytab", P_BOOL, P_GLOBAL, &Globals.bUseKerberosKeytab, NULL, NULL, FLAG_ADVANCED}, 
971
972         {N_("Logging Options"), P_SEP, P_SEPARATOR}, 
973
974         {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED}, 
975         {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE}, 
976         {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED}, 
977         {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED}, 
978         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED}, 
979
980         {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, 
981         {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
982         {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
983         {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED}, 
984         {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, 
985         {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, 
986         {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, 
987         {"debug class", P_BOOL, P_GLOBAL, &Globals.bDebugClass, NULL, NULL, FLAG_ADVANCED},
988         {"enable core files", P_BOOL, P_GLOBAL, &Globals.bEnableCoreFiles, NULL, NULL, FLAG_ADVANCED},
989
990         {N_("Protocol Options"), P_SEP, P_SEPARATOR}, 
991
992         {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED}, 
993         {"aio read size", P_INTEGER, P_LOCAL, &sDefault.iAioReadSize, NULL, NULL, FLAG_ADVANCED}, 
994         {"aio write size", P_INTEGER, P_LOCAL, &sDefault.iAioWriteSize, NULL, NULL, FLAG_ADVANCED}, 
995         {"aio write behind", P_STRING, P_LOCAL, &sDefault.szAioWriteBehind, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, 
996         {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, 
997         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, 
998         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
999         {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1000         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED}, 
1001         {"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, dyn_SMB_PASSWD_FILE);
1460         string_set(&Globals.szPrivateDir, 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, dyn_PIDDIR);
1495         string_set(&Globals.szLockDir, 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", 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( ServicePtrs[idx]->szService );
2518                 
2519                 tdb_delete_bystring(ServiceHash, canon_name );
2520         }
2521
2522         free_service(ServicePtrs[idx]);
2523 }
2524
2525 /***************************************************************************
2526  Add a new service to the services array initialising it with the given 
2527  service. 
2528 ***************************************************************************/
2529
2530 static int add_a_service(const service *pservice, const char *name)
2531 {
2532         int i;
2533         service tservice;
2534         int num_to_alloc = iNumServices + 1;
2535         param_opt_struct *data, *pdata;
2536
2537         tservice = *pservice;
2538
2539         /* it might already exist */
2540         if (name) {
2541                 i = getservicebyname(name, NULL);
2542                 if (i >= 0) {
2543                         /* Clean all parametric options for service */
2544                         /* They will be added during parsing again */
2545                         data = ServicePtrs[i]->param_opt;
2546                         while (data) {
2547                                 string_free(&data->key);
2548                                 string_free(&data->value);
2549                                 str_list_free(&data->list);
2550                                 pdata = data->next;
2551                                 SAFE_FREE(data);
2552                                 data = pdata;
2553                         }
2554                         ServicePtrs[i]->param_opt = NULL;
2555                         return (i);
2556                 }
2557         }
2558
2559         /* find an invalid one */
2560         i = iNumServices;
2561         if (num_invalid_services > 0) {
2562                 i = invalid_services[--num_invalid_services];
2563         }
2564
2565         /* if not, then create one */
2566         if (i == iNumServices) {
2567                 service **tsp;
2568                 int *tinvalid;
2569                 
2570                 tsp = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs, service *, num_to_alloc);
2571                 if (tsp == NULL) {
2572                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2573                         return (-1);
2574                 }
2575                 ServicePtrs = tsp;
2576                 ServicePtrs[iNumServices] = SMB_MALLOC_P(service);
2577                 if (!ServicePtrs[iNumServices]) {
2578                         DEBUG(0,("add_a_service: out of memory!\n"));
2579                         return (-1);
2580                 }
2581                 iNumServices++;
2582
2583                 /* enlarge invalid_services here for now... */
2584                 tinvalid = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services, int,
2585                                              num_to_alloc);
2586                 if (tinvalid == NULL) {
2587                         DEBUG(0,("add_a_service: failed to enlarge "
2588                                  "invalid_services!\n"));
2589                         return (-1);
2590                 }
2591                 invalid_services = tinvalid;
2592         } else {
2593                 free_service_byindex(i);
2594         }
2595
2596         ServicePtrs[i]->valid = True;
2597
2598         init_service(ServicePtrs[i]);
2599         copy_service(ServicePtrs[i], &tservice, NULL);
2600         if (name)
2601                 string_set(&ServicePtrs[i]->szService, name);
2602                 
2603         DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
2604                 i, ServicePtrs[i]->szService));
2605
2606         if (!hash_a_service(ServicePtrs[i]->szService, i)) {
2607                 return (-1);
2608         }
2609                 
2610         return (i);
2611 }
2612
2613 /***************************************************************************
2614   Convert a string to uppercase and remove whitespaces.
2615 ***************************************************************************/
2616
2617 static char *canonicalize_servicename(const char *src)
2618 {
2619         static fstring canon; /* is fstring large enough? */
2620
2621         if ( !src ) {
2622                 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
2623                 return NULL;
2624         }
2625
2626         fstrcpy( canon, src );
2627         strlower_m( canon );
2628
2629         return canon;
2630 }
2631
2632 /***************************************************************************
2633   Add a name/index pair for the services array to the hash table.
2634 ***************************************************************************/
2635
2636 static bool hash_a_service(const char *name, int idx)
2637 {
2638         char *canon_name;
2639
2640         if ( !ServiceHash ) {
2641                 DEBUG(10,("hash_a_service: creating tdb servicehash\n"));
2642                 ServiceHash = tdb_open("servicehash", 1031, TDB_INTERNAL, 
2643                                         (O_RDWR|O_CREAT), 0600);
2644                 if ( !ServiceHash ) {
2645                         DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
2646                         return False;
2647                 }
2648         }
2649
2650         DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
2651                 idx, name));
2652
2653         if ( !(canon_name = canonicalize_servicename( name )) )
2654                 return False;
2655
2656         tdb_store_int32(ServiceHash, canon_name, idx);
2657
2658         return True;
2659 }
2660
2661 /***************************************************************************
2662  Add a new home service, with the specified home directory, defaults coming
2663  from service ifrom.
2664 ***************************************************************************/
2665
2666 bool lp_add_home(const char *pszHomename, int iDefaultService,
2667                  const char *user, const char *pszHomedir)
2668 {
2669         int i;
2670
2671         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2672
2673         if (i < 0)
2674                 return (False);
2675
2676         if (!(*(ServicePtrs[iDefaultService]->szPath))
2677             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) {
2678                 string_set(&ServicePtrs[i]->szPath, pszHomedir);
2679         }
2680
2681         if (!(*(ServicePtrs[i]->comment))) {
2682                 char *comment = NULL;
2683                 if (asprintf(&comment, "Home directory of %s", user) < 0) {
2684                         return false;
2685                 }
2686                 string_set(&ServicePtrs[i]->comment, comment);
2687                 SAFE_FREE(comment);
2688         }
2689
2690         /* set the browseable flag from the global default */
2691
2692         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2693
2694         ServicePtrs[i]->autoloaded = True;
2695
2696         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2697                user, ServicePtrs[i]->szPath ));
2698
2699         return (True);
2700 }
2701
2702 /***************************************************************************
2703  Add a new service, based on an old one.
2704 ***************************************************************************/
2705
2706 int lp_add_service(const char *pszService, int iDefaultService)
2707 {
2708         if (iDefaultService < 0) {
2709                 return add_a_service(&sDefault, pszService);
2710         }
2711
2712         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2713 }
2714
2715 /***************************************************************************
2716  Add the IPC service.
2717 ***************************************************************************/
2718
2719 static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
2720 {
2721         char *comment = NULL;
2722         int i = add_a_service(&sDefault, ipc_name);
2723
2724         if (i < 0)
2725                 return (False);
2726
2727         if (asprintf(&comment, "IPC Service (%s)",
2728                                 Globals.szServerString) < 0) {
2729                 return (False);
2730         }
2731
2732         string_set(&ServicePtrs[i]->szPath, tmpdir());
2733         string_set(&ServicePtrs[i]->szUsername, "");
2734         string_set(&ServicePtrs[i]->comment, comment);
2735         string_set(&ServicePtrs[i]->fstype, "IPC");
2736         ServicePtrs[i]->iMaxConnections = 0;
2737         ServicePtrs[i]->bAvailable = True;
2738         ServicePtrs[i]->bRead_only = True;
2739         ServicePtrs[i]->bGuest_only = False;
2740         ServicePtrs[i]->bGuest_ok = guest_ok;
2741         ServicePtrs[i]->bPrint_ok = False;
2742         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2743
2744         DEBUG(3, ("adding IPC service\n"));
2745
2746         SAFE_FREE(comment);
2747         return (True);
2748 }
2749
2750 /***************************************************************************
2751  Add a new printer service, with defaults coming from service iFrom.
2752 ***************************************************************************/
2753
2754 bool lp_add_printer(const char *pszPrintername, int iDefaultService)
2755 {
2756         const char *comment = "From Printcap";
2757         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2758
2759         if (i < 0)
2760                 return (False);
2761
2762         /* note that we do NOT default the availability flag to True - */
2763         /* we take it from the default service passed. This allows all */
2764         /* dynamic printers to be disabled by disabling the [printers] */
2765         /* entry (if/when the 'available' keyword is implemented!).    */
2766
2767         /* the printer name is set to the service name. */
2768         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2769         string_set(&ServicePtrs[i]->comment, comment);
2770
2771         /* set the browseable flag from the gloabl default */
2772         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2773
2774         /* Printers cannot be read_only. */
2775         ServicePtrs[i]->bRead_only = False;
2776         /* No share modes on printer services. */
2777         ServicePtrs[i]->bShareModes = False;
2778         /* No oplocks on printer services. */
2779         ServicePtrs[i]->bOpLocks = False;
2780         /* Printer services must be printable. */
2781         ServicePtrs[i]->bPrint_ok = True;
2782         
2783         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2784
2785         return (True);
2786 }
2787
2788
2789 /***************************************************************************
2790  Check whether the given parameter name is valid.
2791  Parametric options (names containing a colon) are considered valid.
2792 ***************************************************************************/
2793
2794 bool lp_parameter_is_valid(const char *pszParmName)
2795 {
2796         return ((map_parameter(pszParmName) != -1) ||
2797                 (strchr(pszParmName, ':') != NULL));
2798 }
2799
2800 /***************************************************************************
2801  Check whether the given name is the name of a global parameter.
2802  Returns True for strings belonging to parameters of class
2803  P_GLOBAL, False for all other strings, also for parametric options
2804  and strings not belonging to any option.
2805 ***************************************************************************/
2806
2807 bool lp_parameter_is_global(const char *pszParmName)
2808 {
2809         int num = map_parameter(pszParmName);
2810
2811         if (num >= 0) {
2812                 return (parm_table[num].p_class == P_GLOBAL);
2813         }
2814
2815         return False;
2816 }
2817
2818 /**************************************************************************
2819  Check whether the given name is the canonical name of a parameter.
2820  Returns False if it is not a valid parameter Name.
2821  For parametric options, True is returned.
2822 **************************************************************************/
2823
2824 bool lp_parameter_is_canonical(const char *parm_name)
2825 {
2826         if (!lp_parameter_is_valid(parm_name)) {
2827                 return False;
2828         }
2829
2830         return (map_parameter(parm_name) ==
2831                 map_parameter_canonical(parm_name, NULL));
2832 }
2833
2834 /**************************************************************************
2835  Determine the canonical name for a parameter.
2836  Indicate when it is an inverse (boolean) synonym instead of a
2837  "usual" synonym.
2838 **************************************************************************/
2839
2840 bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
2841                                bool *inverse)
2842 {
2843         int num;
2844
2845         if (!lp_parameter_is_valid(parm_name)) {
2846                 *canon_parm = NULL;
2847                 return False;
2848         }
2849
2850         num = map_parameter_canonical(parm_name, inverse);
2851         if (num < 0) {
2852                 /* parametric option */
2853                 *canon_parm = parm_name;
2854         } else {
2855                 *canon_parm = parm_table[num].label;
2856         }
2857
2858         return True;
2859
2860 }
2861
2862 /**************************************************************************
2863  Determine the canonical name for a parameter.
2864  Turn the value given into the inverse boolean expression when
2865  the synonym is an invers boolean synonym.
2866
2867  Return True if parm_name is a valid parameter name and
2868  in case it is an invers boolean synonym, if the val string could
2869  successfully be converted to the reverse bool.
2870  Return false in all other cases.
2871 **************************************************************************/
2872
2873 bool lp_canonicalize_parameter_with_value(const char *parm_name,
2874                                           const char *val,
2875                                           const char **canon_parm,
2876                                           const char **canon_val)
2877 {
2878         int num;
2879         bool inverse;
2880
2881         if (!lp_parameter_is_valid(parm_name)) {
2882                 *canon_parm = NULL;
2883                 *canon_val = NULL;
2884                 return False;
2885         }
2886
2887         num = map_parameter_canonical(parm_name, &inverse);
2888         if (num < 0) {
2889                 /* parametric option */
2890                 *canon_parm = parm_name;
2891                 *canon_val = val;
2892         } else {
2893                 *canon_parm = parm_table[num].label;
2894                 if (inverse) {
2895                         if (!lp_invert_boolean(val, canon_val)) {
2896                                 *canon_val = NULL;
2897                                 return False;
2898                         }
2899                 } else {
2900                         *canon_val = val;
2901                 }
2902         }
2903
2904         return True;
2905 }
2906
2907 /***************************************************************************
2908  Map a parameter's string representation to something we can use. 
2909  Returns False if the parameter string is not recognised, else TRUE.
2910 ***************************************************************************/
2911
2912 static int map_parameter(const char *pszParmName)
2913 {
2914         int iIndex;
2915
2916         if (*pszParmName == '-')
2917                 return (-1);
2918
2919         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2920                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2921                         return (iIndex);
2922
2923         /* Warn only if it isn't parametric option */
2924         if (strchr(pszParmName, ':') == NULL)
2925                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2926         /* We do return 'fail' for parametric options as well because they are
2927            stored in different storage
2928          */
2929         return (-1);
2930 }
2931
2932 /***************************************************************************
2933  Map a parameter's string representation to the index of the canonical
2934  form of the parameter (it might be a synonym).
2935  Returns -1 if the parameter string is not recognised.
2936 ***************************************************************************/
2937
2938 static int map_parameter_canonical(const char *pszParmName, bool *inverse)
2939 {
2940         int parm_num, canon_num;
2941         bool loc_inverse = False;
2942
2943         parm_num = map_parameter(pszParmName);
2944         if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
2945                 /* invalid, parametric or no canidate for synonyms ... */
2946                 goto done;
2947         }
2948
2949         for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
2950                 if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
2951                         parm_num = canon_num;
2952                         goto done;
2953                 }
2954         }
2955
2956 done:
2957         if (inverse != NULL) {
2958                 *inverse = loc_inverse;
2959         }
2960         return parm_num;
2961 }
2962
2963 /***************************************************************************
2964  return true if parameter number parm1 is a synonym of parameter
2965  number parm2 (parm2 being the principal name).
2966  set inverse to True if parm1 is P_BOOLREV and parm2 is P_BOOL,
2967  False otherwise.
2968 ***************************************************************************/
2969
2970 static bool is_synonym_of(int parm1, int parm2, bool *inverse)
2971 {
2972         if ((parm_table[parm1].ptr == parm_table[parm2].ptr) &&
2973             (parm_table[parm1].flags & FLAG_HIDE) &&
2974             !(parm_table[parm2].flags & FLAG_HIDE))
2975         {
2976                 if (inverse != NULL) {
2977                         if ((parm_table[parm1].type == P_BOOLREV) &&
2978                             (parm_table[parm2].type == P_BOOL))
2979                         {
2980                                 *inverse = True;
2981                         } else {
2982                                 *inverse = False;
2983                         }
2984                 }
2985                 return True;
2986         }
2987         return False;
2988 }
2989
2990 /***************************************************************************
2991  Show one parameter's name, type, [values,] and flags.
2992  (helper functions for show_parameter_list)
2993 ***************************************************************************/
2994
2995 static void show_parameter(int parmIndex)
2996 {
2997         int enumIndex, flagIndex;
2998         int parmIndex2;
2999         bool hadFlag;
3000         bool hadSyn;
3001         bool inverse;
3002         const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
3003                 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING", "P_GSTRING",
3004                 "P_UGSTRING", "P_ENUM", "P_SEP"};
3005         unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
3006                 FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
3007                 FLAG_HIDE, FLAG_DOS_STRING};
3008         const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
3009                 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
3010                 "FLAG_DEPRECATED", "FLAG_HIDE", "FLAG_DOS_STRING", NULL};
3011
3012         printf("%s=%s", parm_table[parmIndex].label,
3013                type[parm_table[parmIndex].type]);
3014         if (parm_table[parmIndex].type == P_ENUM) {
3015                 printf(",");
3016                 for (enumIndex=0;
3017                      parm_table[parmIndex].enum_list[enumIndex].name;
3018                      enumIndex++)
3019                 {
3020                         printf("%s%s",
3021                                enumIndex ? "|" : "",
3022                                parm_table[parmIndex].enum_list[enumIndex].name);
3023                 }
3024         }
3025         printf(",");
3026         hadFlag = False;
3027         for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
3028                 if (parm_table[parmIndex].flags & flags[flagIndex]) {
3029                         printf("%s%s",
3030                                 hadFlag ? "|" : "",
3031                                 flag_names[flagIndex]);
3032                         hadFlag = True;
3033                 }
3034         }
3035
3036         /* output synonyms */
3037         hadSyn = False;
3038         for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
3039                 if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
3040                         printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
3041                                parm_table[parmIndex2].label);
3042                 } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
3043                         if (!hadSyn) {
3044                                 printf(" (synonyms: ");
3045                                 hadSyn = True;
3046                         } else {
3047                                 printf(", ");
3048                         }
3049                         printf("%s%s", parm_table[parmIndex2].label,
3050                                inverse ? "[i]" : "");
3051                 }
3052         }
3053         if (hadSyn) {
3054                 printf(")");
3055         }
3056
3057         printf("\n");
3058 }
3059
3060 /***************************************************************************
3061  Show all parameter's name, type, [values,] and flags.
3062 ***************************************************************************/
3063
3064 void show_parameter_list(void)
3065 {
3066         int classIndex, parmIndex;
3067         const char *section_names[] = { "local", "global", NULL};
3068
3069         for (classIndex=0; section_names[classIndex]; classIndex++) {
3070                 printf("[%s]\n", section_names[classIndex]);
3071                 for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
3072                         if (parm_table[parmIndex].p_class == classIndex) {
3073                                 show_parameter(parmIndex);
3074                         }
3075                 }
3076         }
3077 }
3078
3079 /***************************************************************************
3080  Set a boolean variable from the text value stored in the passed string.
3081  Returns True in success, False if the passed string does not correctly 
3082  represent a boolean.
3083 ***************************************************************************/
3084
3085 static bool set_boolean(bool *pb, const char *pszParmValue)
3086 {
3087         bool bRetval;
3088         bool value;
3089
3090         bRetval = True;
3091         value = False;
3092         if (strwicmp(pszParmValue, "yes") == 0 ||
3093             strwicmp(pszParmValue, "true") == 0 ||
3094             strwicmp(pszParmValue, "1") == 0)
3095                 value = True;
3096         else if (strwicmp(pszParmValue, "no") == 0 ||
3097                     strwicmp(pszParmValue, "False") == 0 ||
3098                     strwicmp(pszParmValue, "0") == 0)
3099                 value = False;
3100         else {
3101                 DEBUG(2,
3102                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
3103                        pszParmValue));
3104                 bRetval = False;
3105         }
3106
3107         if ((pb != NULL) && (bRetval != False)) {
3108                 *pb = value;
3109         }
3110
3111         return (bRetval);
3112 }
3113
3114
3115 /***************************************************************************
3116  Check if a given string correctly represents a boolean value.
3117 ***************************************************************************/
3118
3119 bool lp_string_is_valid_boolean(const char *parm_value)
3120 {
3121         return set_boolean(NULL, parm_value);
3122 }
3123
3124 /***************************************************************************
3125  Get the standard string representation of a boolean value ("yes" or "no")
3126 ***************************************************************************/
3127
3128 static const char *get_boolean(bool bool_value)
3129 {
3130         static const char *yes_str = "yes";
3131         static const char *no_str = "no";
3132
3133         return (bool_value ? yes_str : no_str);
3134 }
3135
3136 /***************************************************************************
3137  Provide the string of the negated boolean value associated to the boolean
3138  given as a string. Returns False if the passed string does not correctly
3139  represent a boolean.
3140 ***************************************************************************/
3141
3142 bool lp_invert_boolean(const char *str, const char **inverse_str)
3143 {
3144         bool val;
3145
3146         if (!set_boolean(&val, str)) {
3147                 return False;
3148         }
3149
3150         *inverse_str = get_boolean(!val);
3151         return True;
3152 }
3153
3154 /***************************************************************************
3155  Provide the canonical string representation of a boolean value given
3156  as a string. Return True on success, False if the string given does
3157  not correctly represent a boolean.
3158 ***************************************************************************/
3159
3160 bool lp_canonicalize_boolean(const char *str, const char**canon_str)
3161 {
3162         bool val;
3163
3164         if (!set_boolean(&val, str)) {
3165                 return False;
3166         }
3167
3168         *canon_str = get_boolean(val);
3169         return True;
3170 }
3171
3172 /***************************************************************************
3173 Find a service by name. Otherwise works like get_service.
3174 ***************************************************************************/
3175
3176 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
3177 {
3178         int iService = -1;
3179         char *canon_name;
3180
3181         if (ServiceHash != NULL) {
3182                 if ( !(canon_name = canonicalize_servicename( pszServiceName )) )
3183                         return -1;
3184
3185                 iService = tdb_fetch_int32(ServiceHash, canon_name );
3186
3187                 if (LP_SNUM_OK(iService)) {
3188                         if (pserviceDest != NULL) {
3189                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
3190                         }
3191                 } else {
3192                         iService = -1;
3193                 }
3194         }
3195
3196         return (iService);
3197 }
3198
3199 /***************************************************************************
3200  Copy a service structure to another.
3201  If pcopymapDest is NULL then copy all fields
3202 ***************************************************************************/
3203
3204 static void copy_service(service * pserviceDest, service * pserviceSource,
3205                          struct bitmap *pcopymapDest)
3206 {
3207         int i;
3208         bool bcopyall = (pcopymapDest == NULL);
3209         param_opt_struct *data, *pdata, *paramo;
3210         bool not_added;
3211
3212         for (i = 0; parm_table[i].label; i++)
3213                 if (parm_table[i].ptr && parm_table[i].p_class == P_LOCAL &&
3214                     (bcopyall || bitmap_query(pcopymapDest,i))) {
3215                         void *def_ptr = parm_table[i].ptr;
3216                         void *src_ptr =
3217                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
3218                                                                     &sDefault);
3219                         void *dest_ptr =
3220                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
3221                                                                   &sDefault);
3222
3223                         switch (parm_table[i].type) {
3224                                 case P_BOOL:
3225                                 case P_BOOLREV:
3226                                         *(bool *)dest_ptr = *(bool *)src_ptr;
3227                                         break;
3228
3229                                 case P_INTEGER:
3230                                 case P_ENUM:
3231                                 case P_OCTAL:
3232                                         *(int *)dest_ptr = *(int *)src_ptr;
3233                                         break;
3234
3235                                 case P_CHAR:
3236                                         *(char *)dest_ptr = *(char *)src_ptr;
3237                                         break;
3238
3239                                 case P_STRING:
3240                                         string_set((char **)dest_ptr,
3241                                                    *(char **)src_ptr);
3242                                         break;
3243
3244                                 case P_USTRING:
3245                                         string_set((char **)dest_ptr,
3246                                                    *(char **)src_ptr);
3247                                         strupper_m(*(char **)dest_ptr);
3248                                         break;
3249                                 case P_LIST:
3250                                         str_list_free((char ***)dest_ptr);
3251                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
3252                                         break;
3253                                 default:
3254                                         break;
3255                         }
3256                 }
3257
3258         if (bcopyall) {
3259                 init_copymap(pserviceDest);
3260                 if (pserviceSource->copymap)
3261                         bitmap_copy(pserviceDest->copymap,
3262                                     pserviceSource->copymap);
3263         }
3264         
3265         data = pserviceSource->param_opt;
3266         while (data) {
3267                 not_added = True;
3268                 pdata = pserviceDest->param_opt;
3269                 /* Traverse destination */
3270                 while (pdata) {
3271                         /* If we already have same option, override it */
3272                         if (strcmp(pdata->key, data->key) == 0) {
3273                                 string_free(&pdata->value);
3274                                 str_list_free(&data->list);
3275                                 pdata->value = SMB_STRDUP(data->value);
3276                                 not_added = False;
3277                                 break;
3278                         }
3279                         pdata = pdata->next;
3280                 }
3281                 if (not_added) {
3282                     paramo = SMB_XMALLOC_P(param_opt_struct);
3283                     paramo->key = SMB_STRDUP(data->key);
3284                     paramo->value = SMB_STRDUP(data->value);
3285                     paramo->list = NULL;
3286                     DLIST_ADD(pserviceDest->param_opt, paramo);
3287                 }
3288                 data = data->next;
3289         }
3290 }
3291
3292 /***************************************************************************
3293 Check a service for consistency. Return False if the service is in any way
3294 incomplete or faulty, else True.
3295 ***************************************************************************/
3296
3297 bool service_ok(int iService)
3298 {
3299         bool bRetval;
3300
3301         bRetval = True;
3302         if (ServicePtrs[iService]->szService[0] == '\0') {
3303                 DEBUG(0, ("The following message indicates an internal error:\n"));
3304                 DEBUG(0, ("No service name in service entry.\n"));
3305                 bRetval = False;
3306         }
3307
3308         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
3309         /* I can't see why you'd want a non-printable printer service...        */
3310         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
3311                 if (!ServicePtrs[iService]->bPrint_ok) {
3312                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
3313                                ServicePtrs[iService]->szService));
3314                         ServicePtrs[iService]->bPrint_ok = True;
3315                 }
3316                 /* [printers] service must also be non-browsable. */
3317                 if (ServicePtrs[iService]->bBrowseable)
3318                         ServicePtrs[iService]->bBrowseable = False;
3319         }
3320
3321         if (ServicePtrs[iService]->szPath[0] == '\0' &&
3322             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
3323             ServicePtrs[iService]->szMSDfsProxy[0] == '\0'
3324             ) {
3325                 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
3326                         ServicePtrs[iService]->szService));
3327                 ServicePtrs[iService]->bAvailable = False;
3328         }
3329
3330         /* If a service is flagged unavailable, log the fact at level 1. */
3331         if (!ServicePtrs[iService]->bAvailable)
3332                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
3333                           ServicePtrs[iService]->szService));
3334
3335         return (bRetval);
3336 }
3337
3338 /*
3339  * lp_regdb_open - regdb helper function 
3340  *
3341  * this should be considered an interim solution that becomes
3342  * superfluous once the registry code has been rewritten
3343  * do allow use of the tdb portion of the registry alone.
3344  *
3345  * in the meanwhile this provides a lean access
3346  * to the registry globals.
3347  */
3348
3349 static struct tdb_wrap *lp_regdb_open(void)
3350 {
3351         struct tdb_wrap *reg_tdb = NULL;
3352         const char *vstring = "INFO/version";
3353         uint32 vers_id;
3354
3355         become_root();
3356         reg_tdb = tdb_wrap_open(NULL, state_path("registry.tdb"), 0, 
3357                                 REG_TDB_FLAGS, O_RDWR, 0600);
3358         unbecome_root();
3359         if (!reg_tdb) {
3360                 DEBUG(1, ("lp_regdb_open: failed to open %s: %s\n",
3361                          state_path("registry.tdb"), strerror(errno)));
3362                 goto done;
3363         }
3364         else {
3365                 DEBUG(10, ("lp_regdb_open: reg tdb opened.\n"));
3366         }
3367
3368         vers_id = tdb_fetch_int32(reg_tdb->tdb, vstring);
3369         if (vers_id != REGVER_V1) {
3370                 DEBUG(10, ("lp_regdb_open: INFO: registry tdb %s has wrong "
3371                           "INFO/version (got %d, expected %d)\n",
3372                           state_path("registry.tdb"), vers_id, REGVER_V1));
3373                 /* this is apparently not implemented in the tdb */
3374         }
3375
3376 done:
3377         return reg_tdb;
3378 }
3379
3380 /*
3381  * process_registry_globals
3382  *
3383  * this is the interim version of process_registry globals
3384  *
3385  * until we can do it as we would like using the api and only
3386  * using the tdb portion of the registry (see below),
3387  * this just provides the needed functionality of regdb_fetch_values
3388  * and regdb_unpack_values, circumventing any fancy stuff, to
3389  * give us access to the registry globals.
3390  */
3391 static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
3392 {
3393         bool ret = False;
3394         struct tdb_wrap *reg_tdb = NULL;
3395         WERROR err;
3396         char *keystr;
3397         TDB_DATA data;
3398         /* vars for the tdb unpack loop */
3399         int len = 0;
3400         int i;
3401         int buflen;
3402         uint8 *buf;
3403         uint32 type;
3404         uint32 size;
3405         uint32 num_values = 0;
3406         uint8 *data_p;
3407         char * valstr;
3408         struct registry_value *value = NULL;
3409
3410         include_registry_globals = True;
3411
3412         ZERO_STRUCT(data);
3413
3414         reg_tdb = lp_regdb_open();
3415         if (!reg_tdb) {
3416                 DEBUG(1, ("Error opening the registry!\n"));
3417                 goto done;
3418         }
3419
3420         /* reg_tdb is from now on used as talloc ctx.
3421          * freeing it closes the tdb (if refcount is 0) */
3422
3423         keystr = talloc_asprintf(reg_tdb,"%s/%s/%s", REG_VALUE_PREFIX,
3424                                  KEY_SMBCONF, GLOBAL_NAME);
3425         normalize_dbkey(keystr);
3426
3427         DEBUG(10, ("process_registry_globals: fetching key '%s'\n",
3428                    keystr));
3429
3430         data = tdb_fetch_bystring(reg_tdb->tdb, keystr);
3431         if (!data.dptr) {
3432                 ret = True;
3433                 goto done;
3434         }
3435
3436         buf = data.dptr;
3437         buflen = data.dsize;
3438
3439         /* unpack number of values */
3440         len = tdb_unpack(buf, buflen, "d", &num_values);
3441         DEBUG(10, ("process_registry_globals: got %d values from tdb\n",
3442                    num_values));
3443
3444         /* unpack the values */
3445         for (i=0; i < num_values; i++) {
3446                 fstring valname;
3447                 type = REG_NONE;
3448                 size = 0;
3449                 data_p = NULL;
3450                 len += tdb_unpack(buf+len, buflen-len, "fdB",
3451                                   valname,
3452                                   &type,
3453                                   &size,
3454                                   &data_p);
3455                 if (registry_smbconf_valname_forbidden(valname)) {
3456                         DEBUG(10, ("process_registry_globals: Ignoring "
3457                                    "parameter '%s' in registry.\n", valname));
3458                         continue;
3459                 }
3460                 DEBUG(10, ("process_registry_globals: got value '%s'\n",
3461                            valname));
3462                 if (size && data_p) {
3463                         err = registry_pull_value(reg_tdb,
3464                                                   &value,
3465                                                   type,
3466                                                   data_p,
3467                                                   size,
3468                                                   size);
3469                         SAFE_FREE(data_p);
3470                         if (!W_ERROR_IS_OK(err)) {
3471                                 goto done;
3472                         }
3473                         switch(type) {
3474                         case REG_DWORD:
3475                                 valstr = talloc_asprintf(reg_tdb, "%d",
3476                                                          value->v.dword);
3477                                 pfunc(valname, valstr);
3478                                 break;
3479                         case REG_SZ:
3480                                 pfunc(valname, value->v.sz.str);
3481                                 break;
3482                         default:
3483                                 /* ignore other types */
3484                                 break;
3485                         }
3486                 }
3487         }
3488
3489         ret = pfunc("registry shares", "yes");
3490         regdb_last_seqnum = tdb_get_seqnum(reg_tdb->tdb);
3491
3492 done:
3493         TALLOC_FREE(reg_tdb);
3494         SAFE_FREE(data.dptr);
3495         return ret;
3496 }
3497
3498 #if 0
3499 /*
3500  * this is process_registry_globals as it _should_ be (roughly)
3501  * using the reg_api functions...
3502  * 
3503  */
3504 static bool process_registry_globals(bool (*pfunc)(const char *, const char *))
3505 {
3506         bool ret = False;
3507         TALLOC_CTX *ctx = NULL;
3508         char *regpath = NULL;
3509         WERROR werr = WERR_OK;
3510         struct registry_key *key = NULL;
3511         struct registry_value *value = NULL;
3512         char *valname = NULL;
3513         char *valstr = NULL;
3514         uint32 idx = 0;
3515         NT_USER_TOKEN *token;
3516
3517         ctx = talloc_init("process_registry_globals");
3518         if (!ctx) {
3519                 smb_panic("Failed to create talloc context!");
3520         }
3521
3522         include_registry_globals = True;
3523
3524         if (!registry_init_regdb()) {
3525                 DEBUG(1, ("Error initializing the registry.\n"));
3526                 goto done;
3527         }
3528
3529         if (!(token = registry_create_admin_token(ctx))) {
3530                 DEBUG(1, ("Error creating admin token\n"));
3531                 goto done;
3532         }
3533
3534         regpath = talloc_asprintf(ctx,"%s\\%s", KEY_SMBCONF, GLOBAL_NAME);
3535         werr = reg_open_path(ctx, regpath, REG_KEY_READ, token, &key);
3536         if (!W_ERROR_IS_OK(werr)) {
3537                 DEBUG(1, ("Registry smbconf global section does not exist.\n"));
3538                 DEBUGADD(1, ("Error opening registry path '%s\\%s: %s\n",
3539                              KEY_SMBCONF, GLOBAL_NAME, dos_errstr(werr)));
3540                 goto done;
3541         }
3542
3543         for (idx = 0;
3544              W_ERROR_IS_OK(werr = reg_enumvalue(ctx, key, idx, &valname,
3545                                                 &value));
3546              idx++)
3547         {
3548                 DEBUG(5, ("got global registry parameter '%s'\n", valname));
3549                 switch(value->type) {
3550                 case REG_DWORD:
3551                         valstr = talloc_asprintf(ctx, "%d", value->v.dword);
3552                         pfunc(valname, valstr);
3553                         TALLOC_FREE(valstr);
3554                         break;
3555                 case REG_SZ:
3556                         pfunc(valname, value->v.sz.str);
3557                         break;
3558                 default:
3559                         /* ignore other types */
3560                         break;
3561                 }
3562                 TALLOC_FREE(value);
3563                 TALLOC_FREE(valstr);
3564         }
3565
3566         ret = pfunc("registry shares", "yes");
3567
3568         regdb_last_seqnum = regdb_get_seqnum();
3569
3570 done:
3571         talloc_destroy(ctx);
3572         return ret;
3573 }
3574 #endif /* if 0 */
3575
3576 static struct file_lists {
3577         struct file_lists *next;
3578         char *name;
3579         char *subfname;
3580         time_t modtime;
3581 } *file_lists = NULL;
3582
3583 /*******************************************************************
3584  Keep a linked list of all config files so we know when one has changed 
3585  it's date and needs to be reloaded.
3586 ********************************************************************/
3587
3588 static void add_to_file_list(const char *fname, const char *subfname)
3589 {
3590         struct file_lists *f = file_lists;
3591
3592         while (f) {
3593                 if (f->name && !strcmp(f->name, fname))
3594                         break;
3595                 f = f->next;
3596         }
3597
3598         if (!f) {
3599                 f = SMB_MALLOC_P(struct file_lists);
3600                 if (!f)
3601                         return;
3602                 f->next = file_lists;
3603                 f->name = SMB_STRDUP(fname);
3604                 if (!f->name) {
3605                         SAFE_FREE(f);
3606                         return;
3607                 }
3608                 f->subfname = SMB_STRDUP(subfname);
3609                 if (!f->subfname) {
3610                         SAFE_FREE(f);
3611                         return;
3612                 }
3613                 file_lists = f;
3614                 f->modtime = file_modtime(subfname);
3615         } else {
3616                 time_t t = file_modtime(subfname);
3617                 if (t)
3618                         f->modtime = t;
3619         }
3620 }
3621
3622 /*******************************************************************
3623  Check if a config file has changed date.
3624 ********************************************************************/
3625
3626 bool lp_file_list_changed(void)
3627 {
3628         struct file_lists *f = file_lists;
3629         struct tdb_wrap *reg_tdb = NULL;
3630
3631         DEBUG(6, ("lp_file_list_changed()\n"));
3632
3633         if (include_registry_globals) {
3634                 reg_tdb = lp_regdb_open();
3635                 if (reg_tdb && (regdb_last_seqnum != tdb_get_seqnum(reg_tdb->tdb)))
3636                 {
3637                         DEBUGADD(6, ("regdb seqnum changed: old = %d, new = %d\n",
3638                                     regdb_last_seqnum, tdb_get_seqnum(reg_tdb->tdb)));
3639                         TALLOC_FREE(reg_tdb);
3640                         return true;
3641                 }
3642         }
3643
3644         while (f) {
3645                 char *n2 = NULL;
3646                 time_t mod_time;
3647
3648                 n2 = alloc_sub_basic(get_current_username(),
3649                                     current_user_info.domain,
3650                                     f->name);
3651                 if (!n2) {
3652                         return false;
3653                 }
3654                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
3655                              f->name, n2, ctime(&f->modtime)));
3656
3657                 mod_time = file_modtime(n2);
3658
3659                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
3660                         DEBUGADD(6,
3661                                  ("file %s modified: %s\n", n2,
3662                                   ctime(&mod_time)));
3663                         f->modtime = mod_time;
3664                         SAFE_FREE(f->subfname);
3665                         f->subfname = n2; /* Passing ownership of
3666                                              return from alloc_sub_basic
3667                                              above. */
3668                         return true;
3669                 }
3670                 SAFE_FREE(n2);
3671                 f = f->next;
3672         }
3673         return (False);
3674 }
3675
3676 /***************************************************************************
3677  Run standard_sub_basic on netbios name... needed because global_myname
3678  is not accessed through any lp_ macro.
3679  Note: We must *NOT* use string_set() here as ptr points to global_myname.
3680 ***************************************************************************/
3681
3682 static bool handle_netbios_name(int snum, const char *pszParmValue, char **ptr)
3683 {
3684         bool ret;
3685         char *netbios_name = alloc_sub_basic(get_current_username(),
3686                                         current_user_info.domain,
3687                                         pszParmValue);
3688
3689         ret = set_global_myname(netbios_name);
3690         SAFE_FREE(netbios_name);
3691         string_set(&Globals.szNetbiosName,global_myname());
3692
3693         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
3694                global_myname()));
3695
3696         return ret;
3697 }
3698
3699 static bool handle_charset(int snum, const char *pszParmValue, char **ptr)
3700 {
3701         if (strcmp(*ptr, pszParmValue) != 0) {
3702                 string_set(ptr, pszParmValue);
3703                 init_iconv();
3704         }
3705         return True;
3706 }
3707
3708
3709
3710 static bool handle_workgroup(int snum, const char *pszParmValue, char **ptr)
3711 {
3712         bool ret;
3713         
3714         ret = set_global_myworkgroup(pszParmValue);
3715         string_set(&Globals.szWorkgroup,lp_workgroup());
3716         
3717         return ret;
3718 }
3719
3720 static bool handle_netbios_scope(int snum, const char *pszParmValue, char **ptr)
3721 {
3722         bool ret;
3723         
3724         ret = set_global_scope(pszParmValue);
3725         string_set(&Globals.szNetbiosScope,global_scope());
3726
3727         return ret;
3728 }
3729
3730 static bool handle_netbios_aliases(int snum, const char *pszParmValue, char **ptr)
3731 {
3732         str_list_free(&Globals.szNetbiosAliases);
3733         Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
3734         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
3735 }
3736
3737 /***************************************************************************
3738  Handle the include operation.
3739 ***************************************************************************/
3740
3741 static bool handle_include(int snum, const char *pszParmValue, char **ptr)
3742 {
3743         char *fname;
3744
3745         if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
3746                 if (bInGlobalSection) {
3747                         return process_registry_globals(do_parameter);
3748                 }
3749                 else {
3750                         DEBUG(1, ("\"include = registry\" only effective "
3751                                   "in %s section\n", GLOBAL_NAME));
3752                         return false;
3753                 }
3754         }
3755
3756         fname = alloc_sub_basic(get_current_username(),
3757                                 current_user_info.domain,
3758                                 pszParmValue);
3759
3760         add_to_file_list(pszParmValue, fname);
3761
3762         string_set(ptr, fname);
3763
3764         if (file_exist(fname, NULL)) {
3765                 bool ret = pm_process(fname, do_section, do_parameter);
3766                 SAFE_FREE(fname);
3767                 return ret;
3768         }
3769
3770         DEBUG(2, ("Can't find include file %s\n", fname));
3771         SAFE_FREE(fname);
3772         return false;
3773 }
3774
3775 /***************************************************************************
3776  Handle the interpretation of the copy parameter.
3777 ***************************************************************************/
3778
3779 static bool handle_copy(int snum, const char *pszParmValue, char **ptr)
3780 {
3781         bool bRetval;
3782         int iTemp;
3783         service serviceTemp;
3784
3785         string_set(ptr, pszParmValue);
3786
3787         init_service(&serviceTemp);
3788
3789         bRetval = False;
3790
3791         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
3792
3793         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
3794                 if (iTemp == iServiceIndex) {
3795                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
3796                 } else {
3797                         copy_service(ServicePtrs[iServiceIndex],
3798                                      &serviceTemp,
3799                                      ServicePtrs[iServiceIndex]->copymap);
3800                         bRetval = True;
3801                 }
3802         } else {
3803                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
3804                 bRetval = False;
3805         }
3806
3807         free_service(&serviceTemp);
3808         return (bRetval);
3809 }
3810
3811 /***************************************************************************
3812  Handle idmap/non unix account uid and gid allocation parameters.  The format of these
3813  parameters is:
3814
3815  [global]
3816
3817         idmap uid = 1000-1999
3818         idmap gid = 700-899
3819
3820  We only do simple parsing checks here.  The strings are parsed into useful
3821  structures in the idmap daemon code.
3822
3823 ***************************************************************************/
3824
3825 /* Some lp_ routines to return idmap [ug]id information */
3826
3827 static uid_t idmap_uid_low, idmap_uid_high;
3828 static gid_t idmap_gid_low, idmap_gid_high;
3829
3830 bool lp_idmap_uid(uid_t *low, uid_t *high)
3831 {
3832         if (idmap_uid_low == 0 || idmap_uid_high == 0)
3833                 return False;
3834
3835         if (low)
3836                 *low = idmap_uid_low;
3837
3838         if (high)
3839                 *high = idmap_uid_high;
3840
3841         return True;
3842 }
3843
3844 bool lp_idmap_gid(gid_t *low, gid_t *high)
3845 {
3846         if (idmap_gid_low == 0 || idmap_gid_high == 0)
3847                 return False;
3848
3849         if (low)
3850                 *low = idmap_gid_low;
3851
3852         if (high)
3853                 *high = idmap_gid_high;
3854
3855         return True;
3856 }
3857
3858 /* Do some simple checks on "idmap [ug]id" parameter values */
3859
3860 static bool handle_idmap_uid(int snum, const char *pszParmValue, char **ptr)
3861 {
3862         uint32 low, high;
3863
3864         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3865                 return False;
3866
3867         /* Parse OK */
3868
3869         string_set(ptr, pszParmValue);
3870
3871         idmap_uid_low = low;
3872         idmap_uid_high = high;
3873
3874         return True;
3875 }
3876
3877 static bool handle_idmap_gid(int snum, const char *pszParmValue, char **ptr)
3878 {
3879         uint32 low, high;
3880
3881         if (sscanf(pszParmValue, "%u - %u", &low, &high) != 2 || high < low)
3882                 return False;
3883
3884         /* Parse OK */
3885
3886         string_set(ptr, pszParmValue);
3887
3888         idmap_gid_low = low;
3889         idmap_gid_high = high;
3890
3891         return True;
3892 }
3893
3894 /***************************************************************************
3895  Handle the DEBUG level list.
3896 ***************************************************************************/
3897
3898 static bool handle_debug_list( int snum, const char *pszParmValueIn, char **ptr )
3899 {
3900         string_set(ptr, pszParmValueIn);
3901         return debug_parse_levels(pszParmValueIn);
3902 }
3903
3904 /***************************************************************************
3905  Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
3906 ***************************************************************************/
3907
3908 static const char *append_ldap_suffix( const char *str )
3909 {
3910         const char *suffix_string;
3911
3912
3913         suffix_string = talloc_asprintf(talloc_tos(), "%s,%s", str,
3914                                         Globals.szLdapSuffix );
3915         if ( !suffix_string ) {
3916                 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
3917                 return "";
3918         }
3919
3920         return suffix_string;
3921 }
3922
3923 const char *lp_ldap_machine_suffix(void)
3924 {
3925         if (Globals.szLdapMachineSuffix[0])
3926                 return append_ldap_suffix(Globals.szLdapMachineSuffix);
3927
3928         return lp_string(Globals.szLdapSuffix);
3929 }
3930
3931 const char *lp_ldap_user_suffix(void)
3932 {
3933         if (Globals.szLdapUserSuffix[0])
3934                 return append_ldap_suffix(Globals.szLdapUserSuffix);
3935
3936         return lp_string(Globals.szLdapSuffix);
3937 }
3938
3939 const char *lp_ldap_group_suffix(void)
3940 {
3941         if (Globals.szLdapGroupSuffix[0])
3942                 return append_ldap_suffix(Globals.szLdapGroupSuffix);
3943
3944         return lp_string(Globals.szLdapSuffix);
3945 }
3946
3947 const char *lp_ldap_idmap_suffix(void)
3948 {
3949         if (Globals.szLdapIdmapSuffix[0])
3950                 return append_ldap_suffix(Globals.szLdapIdmapSuffix);
3951
3952         return lp_string(Globals.szLdapSuffix);
3953 }
3954
3955 /****************************************************************************
3956  set the value for a P_ENUM
3957  ***************************************************************************/
3958
3959 static void lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
3960                               int *ptr )
3961 {
3962         int i;
3963
3964         for (i = 0; parm->enum_list[i].name; i++) {
3965                 if ( strequal(pszParmValue, parm->enum_list[i].name)) {
3966                         *ptr = parm->enum_list[i].value;
3967                         break;
3968                 }
3969         }
3970 }
3971
3972 /***************************************************************************
3973 ***************************************************************************/
3974
3975 static bool handle_printing(int snum, const char *pszParmValue, char **ptr)
3976 {
3977         static int parm_num = -1;
3978         service *s;
3979
3980         if ( parm_num == -1 )
3981                 parm_num = map_parameter( "printing" );
3982
3983         lp_set_enum_parm( &parm_table[parm_num], pszParmValue, (int*)ptr );
3984
3985         if ( snum < 0 )
3986                 s = &sDefault;
3987         else
3988                 s = ServicePtrs[snum];
3989
3990         init_printer_values( s );
3991
3992         return True;
3993 }
3994
3995
3996 /***************************************************************************
3997  Initialise a copymap.
3998 ***************************************************************************/
3999
4000 static void init_copymap(service * pservice)
4001 {
4002         int i;
4003         if (pservice->copymap) {
4004                 bitmap_free(pservice->copymap);
4005         }
4006         pservice->copymap = bitmap_allocate(NUMPARAMETERS);
4007         if (!pservice->copymap)
4008                 DEBUG(0,
4009                       ("Couldn't allocate copymap!! (size %d)\n",
4010                        (int)NUMPARAMETERS));
4011         else
4012                 for (i = 0; i < NUMPARAMETERS; i++)
4013                         bitmap_set(pservice->copymap, i);
4014 }
4015
4016 /***************************************************************************
4017  Return the local pointer to a parameter given the service number and the 
4018  pointer into the default structure.
4019 ***************************************************************************/
4020
4021 void *lp_local_ptr(int snum, void *ptr)
4022 {
4023         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
4024 }
4025
4026 /***************************************************************************
4027  Process a parameter for a particular service number. If snum < 0
4028  then assume we are in the globals.
4029 ***************************************************************************/
4030
4031 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
4032 {
4033         int parmnum, i, slen;
4034         void *parm_ptr = NULL;  /* where we are going to store the result */
4035         void *def_ptr = NULL;
4036         char *param_key = NULL;
4037         char *sep;
4038         param_opt_struct *paramo, *data;
4039         bool not_added;
4040
4041         parmnum = map_parameter(pszParmName);
4042
4043         if (parmnum < 0) {
4044                 if ((sep=strchr(pszParmName, ':')) != NULL) {
4045                         TALLOC_CTX *frame = talloc_stackframe();
4046
4047                         *sep = '\0';
4048                         param_key = talloc_asprintf(frame, "%s:", pszParmName);
4049                         if (!param_key) {
4050                                 TALLOC_FREE(frame);
4051                                 return false;
4052                         }
4053                         slen = strlen(param_key);
4054                         param_key = talloc_asprintf_append(param_key, sep+1);
4055                         if (!param_key) {
4056                                 TALLOC_FREE(frame);
4057                                 return false;
4058                         }
4059                         trim_char(param_key+slen, ' ', ' ');
4060                         not_added = True;
4061                         data = (snum < 0) ? Globals.param_opt :
4062                                 ServicePtrs[snum]->param_opt;
4063                         /* Traverse destination */
4064                         while (data) {
4065                                 /* If we already have same option, override it */
4066                                 if (strcmp(data->key, param_key) == 0) {
4067                                         string_free(&data->value);
4068                                         str_list_free(&data->list);
4069                                         data->value = SMB_STRDUP(pszParmValue);
4070                                         not_added = False;
4071                                         break;
4072                                 }
4073                                 data = data->next;
4074                         }
4075                         if (not_added) {
4076                                 paramo = SMB_XMALLOC_P(param_opt_struct);
4077                                 paramo->key = SMB_STRDUP(param_key);
4078                                 paramo->value = SMB_STRDUP(pszParmValue);
4079                                 paramo->list = NULL;
4080                                 if (snum < 0) {
4081                                         DLIST_ADD(Globals.param_opt, paramo);
4082                                 } else {
4083                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
4084                                 }
4085                         }
4086
4087                         *sep = ':';
4088                         TALLOC_FREE(frame);
4089                         return (True);
4090                 }
4091                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
4092                 return (True);
4093         }
4094
4095         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
4096                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
4097                           pszParmName));
4098         }
4099
4100         def_ptr = parm_table[parmnum].ptr;
4101
4102         /* we might point at a service, the default service or a global */
4103         if (snum < 0) {
4104                 parm_ptr = def_ptr;
4105         } else {
4106                 if (parm_table[parmnum].p_class == P_GLOBAL) {
4107                         DEBUG(0,
4108                               ("Global parameter %s found in service section!\n",
4109                                pszParmName));
4110                         return (True);
4111                 }
4112                 parm_ptr =
4113                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
4114                                                             &sDefault);
4115         }
4116
4117         if (snum >= 0) {
4118                 if (!ServicePtrs[snum]->copymap)
4119                         init_copymap(ServicePtrs[snum]);
4120
4121                 /* this handles the aliases - set the copymap for other entries with
4122                    the same data pointer */
4123                 for (i = 0; parm_table[i].label; i++)
4124                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
4125                                 bitmap_clear(ServicePtrs[snum]->copymap, i);
4126         }
4127
4128         /* if it is a special case then go ahead */
4129         if (parm_table[parmnum].special) {
4130                 parm_table[parmnum].special(snum, pszParmValue, (char **)parm_ptr);
4131                 return (True);
4132         }
4133
4134         /* now switch on the type of variable it is */
4135         switch (parm_table[parmnum].type)
4136         {
4137                 case P_BOOL:
4138                         *(bool *)parm_ptr = lp_bool(pszParmValue);
4139                         break;
4140
4141                 case P_BOOLREV:
4142                         *(bool *)parm_ptr = !lp_bool(pszParmValue);
4143                         break;
4144
4145                 case P_INTEGER:
4146                         *(int *)parm_ptr = lp_int(pszParmValue);
4147                         break;
4148
4149                 case P_CHAR:
4150                         *(char *)parm_ptr = *pszParmValue;
4151                         break;
4152
4153                 case P_OCTAL:
4154                         i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
4155                         if ( i != 1 ) {
4156                             DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
4157                         }
4158                         break;
4159
4160                 case P_LIST:
4161                         str_list_free((char ***)parm_ptr);
4162                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
4163                         break;
4164
4165                 case P_STRING:
4166                         string_set((char **)parm_ptr, pszParmValue);
4167                         break;
4168
4169                 case P_USTRING:
4170                         string_set((char **)parm_ptr, pszParmValue);
4171                         strupper_m(*(char **)parm_ptr);
4172                         break;
4173
4174                 case P_GSTRING:
4175                         pstrcpy((char *)parm_ptr, pszParmValue);
4176                         break;
4177
4178                 case P_UGSTRING:
4179                         pstrcpy((char *)parm_ptr, pszParmValue);
4180                         strupper_m((char *)parm_ptr);
4181                         break;
4182
4183                 case P_ENUM:
4184                         lp_set_enum_parm( &parm_table[parmnum], pszParmValue, (int*)parm_ptr );
4185                         break;
4186                 case P_SEP:
4187                         break;
4188         }
4189
4190         return (True);
4191 }
4192
4193 /***************************************************************************
4194  Process a parameter.
4195 ***************************************************************************/
4196
4197 static bool do_parameter(const char *pszParmName, const char *pszParmValue)
4198 {
4199         if (!bInGlobalSection && bGlobalOnly)
4200                 return (True);
4201
4202         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
4203
4204         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
4205                                 pszParmName, pszParmValue));
4206 }
4207
4208 /***************************************************************************
4209  Print a parameter of the specified type.
4210 ***************************************************************************/
4211
4212 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
4213 {
4214         int i;
4215         switch (p->type)
4216         {
4217                 case P_ENUM:
4218                         for (i = 0; p->enum_list[i].name; i++) {
4219                                 if (*(int *)ptr == p->enum_list[i].value) {
4220                                         fprintf(f, "%s",
4221                                                 p->enum_list[i].name);
4222                                         break;
4223                                 }
4224                         }
4225                         break;
4226
4227                 case P_BOOL:
4228                         fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
4229                         break;
4230
4231                 case P_BOOLREV:
4232                         fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
4233                         break;
4234
4235                 case P_INTEGER:
4236                         fprintf(f, "%d", *(int *)ptr);
4237                         break;
4238
4239                 case P_CHAR:
4240                         fprintf(f, "%c", *(char *)ptr);
4241                         break;
4242
4243                 case P_OCTAL:
4244                         fprintf(f, "%s", octal_string(*(int *)ptr));
4245                         break;
4246
4247                 case P_LIST:
4248                         if ((char ***)ptr && *(char ***)ptr) {
4249                                 char **list = *(char ***)ptr;
4250                                 
4251                                 for (; *list; list++) {
4252                                         /* surround strings with whitespace in double quotes */
4253                                         if ( strchr_m( *list, ' ' ) )
4254                                                 fprintf(f, "\"%s\"%s", *list, ((*(list+1))?", ":""));
4255                                         else
4256                                                 fprintf(f, "%s%s", *list, ((*(list+1))?", ":""));
4257                                 }
4258                         }
4259                         break;
4260
4261                 case P_GSTRING:
4262                 case P_UGSTRING:
4263                         if ((char *)ptr) {
4264                                 fprintf(f, "%s", (char *)ptr);
4265                         }
4266                         break;
4267
4268                 case P_STRING:
4269                 case P_USTRING:
4270                         if (*(char **)ptr) {
4271                                 fprintf(f, "%s", *(char **)ptr);
4272                         }
4273                         break;
4274                 case P_SEP:
4275                         break;
4276         }
4277 }
4278
4279 /***************************************************************************
4280  Check if two parameters are equal.
4281 ***************************************************************************/
4282
4283 static bool equal_parameter(parm_type type, void *ptr1, void *ptr2)
4284 {
4285         switch (type) {
4286                 case P_BOOL:
4287                 case P_BOOLREV:
4288                         return (*((bool *)ptr1) == *((bool *)ptr2));
4289
4290                 case P_INTEGER:
4291                 case P_ENUM:
4292                 case P_OCTAL:
4293                         return (*((int *)ptr1) == *((int *)ptr2));
4294
4295                 case P_CHAR:
4296                         return (*((char *)ptr1) == *((char *)ptr2));
4297                 
4298                 case P_LIST:
4299                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
4300
4301                 case P_GSTRING:
4302                 case P_UGSTRING:
4303                 {
4304                         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
4305                         if (p1 && !*p1)
4306                                 p1 = NULL;
4307                         if (p2 && !*p2)
4308                                 p2 = NULL;
4309                         return (p1 == p2 || strequal(p1, p2));
4310                 }
4311                 case P_STRING:
4312                 case P_USTRING:
4313                 {
4314                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
4315                         if (p1 && !*p1)
4316                                 p1 = NULL;
4317                         if (p2 && !*p2)
4318                                 p2 = NULL;
4319                         return (p1 == p2 || strequal(p1, p2));
4320                 }
4321                 case P_SEP:
4322                         break;
4323         }
4324         return (False);
4325 }
4326
4327 /***************************************************************************
4328  Initialize any local varients in the sDefault table.
4329 ***************************************************************************/
4330
4331 void init_locals(void)
4332 {
4333         /* None as yet. */
4334 }
4335
4336 /***************************************************************************
4337  Process a new section (service). At this stage all sections are services.
4338  Later we'll have special sections that permit server parameters to be set.
4339  Returns True on success, False on failure. 
4340 ***************************************************************************/
4341
4342 static bool do_section(const char *pszSectionName)
4343 {
4344         bool bRetval;
4345         bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
4346                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
4347         bRetval = False;
4348
4349         /* if we were in a global section then do the local inits */
4350         if (bInGlobalSection && !isglobal)
4351                 init_locals();
4352
4353         /* if we've just struck a global section, note the fact. */
4354         bInGlobalSection = isglobal;
4355
4356         /* check for multiple global sections */
4357         if (bInGlobalSection) {
4358                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
4359                 return (True);
4360         }
4361
4362         if (!bInGlobalSection && bGlobalOnly)
4363                 return (True);
4364
4365         /* if we have a current service, tidy it up before moving on */
4366         bRetval = True;
4367
4368         if (iServiceIndex >= 0)
4369                 bRetval = service_ok(iServiceIndex);
4370
4371         /* if all is still well, move to the next record in the services array */
4372         if (bRetval) {
4373                 /* We put this here to avoid an odd message order if messages are */
4374                 /* issued by the post-processing of a previous section. */
4375                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
4376
4377                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
4378                     < 0) {
4379                         DEBUG(0, ("Failed to add a new service\n"));
4380                         return (False);
4381                 }
4382         }
4383
4384         return (bRetval);
4385 }
4386
4387
4388 /***************************************************************************
4389  Determine if a partcular base parameter is currentl set to the default value.
4390 ***************************************************************************/
4391
4392 static bool is_default(int i)
4393 {
4394         if (!defaults_saved)
4395                 return False;
4396         switch (parm_table[i].type) {
4397                 case P_LIST:
4398                         return str_list_compare (parm_table[i].def.lvalue, 
4399                                                 *(char ***)parm_table[i].ptr);
4400                 case P_STRING:
4401                 case P_USTRING:
4402                         return strequal(parm_table[i].def.svalue,
4403                                         *(char **)parm_table[i].ptr);
4404                 case P_GSTRING:
4405                 case P_UGSTRING:
4406                         return strequal(parm_table[i].def.svalue,
4407                                         (char *)parm_table[i].ptr);
4408                 case P_BOOL:
4409                 case P_BOOLREV:
4410                         return parm_table[i].def.bvalue ==
4411                                 *(bool *)parm_table[i].ptr;
4412                 case P_CHAR:
4413                         return parm_table[i].def.cvalue ==
4414                                 *(char *)parm_table[i].ptr;
4415                 case P_INTEGER:
4416                 case P_OCTAL:
4417                 case P_ENUM:
4418                         return parm_table[i].def.ivalue ==
4419                                 *(int *)parm_table[i].ptr;
4420                 case P_SEP:
4421                         break;
4422         }
4423         return False;
4424 }
4425
4426 /***************************************************************************
4427 Display the contents of the global structure.
4428 ***************************************************************************/
4429
4430 static void dump_globals(FILE *f)
4431 {
4432         int i;
4433         param_opt_struct *data;
4434         
4435         fprintf(f, "[global]\n");
4436
4437         for (i = 0; parm_table[i].label; i++)
4438                 if (parm_table[i].p_class == P_GLOBAL &&
4439                     parm_table[i].ptr &&
4440                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
4441                         if (defaults_saved && is_default(i))
4442                                 continue;
4443                         fprintf(f, "\t%s = ", parm_table[i].label);
4444                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
4445                         fprintf(f, "\n");
4446         }
4447         if (Globals.param_opt != NULL) {
4448                 data = Globals.param_opt;
4449                 while(data) {
4450                         fprintf(f, "\t%s = %s\n", data->key, data->value);
4451                         data = data->next;
4452                 }
4453         }
4454
4455 }
4456
4457 /***************************************************************************
4458  Return True if a local parameter is currently set to the global default.
4459 ***************************************************************************/
4460
4461 bool lp_is_default(int snum, struct parm_struct *parm)
4462 {
4463         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
4464
4465         return equal_parameter(parm->type,
4466                                ((char *)ServicePtrs[snum]) + pdiff,
4467                                ((char *)&sDefault) + pdiff);
4468 }
4469
4470 /***************************************************************************
4471  Display the contents of a single services record.
4472 ***************************************************************************/
4473
4474 static void dump_a_service(service * pService, FILE * f)
4475 {
4476         int i;
4477         param_opt_struct *data;
4478         
4479         if (pService != &sDefault)
4480                 fprintf(f, "[%s]\n", pService->szService);
4481
4482         for (i = 0; parm_table[i].label; i++) {
4483
4484                 if (parm_table[i].p_class == P_LOCAL &&
4485                     parm_table[i].ptr &&
4486                     (*parm_table[i].label != '-') &&
4487                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4488                 {
4489                 
4490                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
4491
4492                         if (pService == &sDefault) {
4493                                 if (defaults_saved && is_default(i))
4494                                         continue;
4495                         } else {
4496                                 if (equal_parameter(parm_table[i].type,
4497                                                     ((char *)pService) +
4498                                                     pdiff,
4499                                                     ((char *)&sDefault) +
4500                                                     pdiff))
4501                                         continue;
4502                         }
4503
4504                         fprintf(f, "\t%s = ", parm_table[i].label);
4505                         print_parameter(&parm_table[i],
4506                                         ((char *)pService) + pdiff, f);
4507                         fprintf(f, "\n");
4508                 }
4509         }
4510
4511                 if (pService->param_opt != NULL) {
4512                         data = pService->param_opt;
4513                         while(data) {
4514                                 fprintf(f, "\t%s = %s\n", data->key, data->value);
4515                                 data = data->next;
4516                         }
4517                 }
4518 }
4519
4520 /***************************************************************************
4521  Display the contents of a parameter of a single services record.
4522 ***************************************************************************/
4523
4524 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
4525 {
4526         int i;
4527         bool result = False;
4528         parm_class p_class;
4529         unsigned flag = 0;
4530         fstring local_parm_name;
4531         char *parm_opt;
4532         const char *parm_opt_value;
4533
4534         /* check for parametrical option */
4535         fstrcpy( local_parm_name, parm_name);
4536         parm_opt = strchr( local_parm_name, ':');
4537
4538         if (parm_opt) {
4539                 *parm_opt = '\0';
4540                 parm_opt++;
4541                 if (strlen(parm_opt)) {
4542                         parm_opt_value = lp_parm_const_string( snum,
4543                                 local_parm_name, parm_opt, NULL);
4544                         if (parm_opt_value) {
4545                                 printf( "%s\n", parm_opt_value);
4546                                 result = True;
4547                         }
4548                 }
4549                 return result;
4550         }
4551
4552         /* check for a key and print the value */
4553         if (isGlobal) {
4554                 p_class = P_GLOBAL;
4555                 flag = FLAG_GLOBAL;
4556         } else
4557                 p_class = P_LOCAL;
4558
4559         for (i = 0; parm_table[i].label; i++) {
4560                 if (strwicmp(parm_table[i].label, parm_name) == 0 &&
4561                     (parm_table[i].p_class == p_class || parm_table[i].flags & flag) &&
4562                     parm_table[i].ptr &&
4563                     (*parm_table[i].label != '-') &&
4564                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) 
4565                 {
4566                         void *ptr;
4567
4568                         if (isGlobal) {
4569                                 ptr = parm_table[i].ptr;
4570                         } else {
4571                                 service * pService = ServicePtrs[snum];
4572                                 ptr = ((char *)pService) +
4573                                         PTR_DIFF(parm_table[i].ptr, &sDefault);
4574                         }
4575
4576                         print_parameter(&parm_table[i],
4577                                         ptr, f);
4578                         fprintf(f, "\n");
4579                         result = True;
4580                         break;
4581                 }
4582         }
4583
4584         return result;
4585 }
4586
4587 /***************************************************************************
4588  Return info about the requested parameter (given as a string).
4589  Return NULL when the string is not a valid parameter name.
4590 ***************************************************************************/
4591
4592 struct parm_struct *lp_get_parameter(const char *param_name)
4593 {
4594         int num = map_parameter(param_name);
4595
4596         if (num < 0) {
4597                 return NULL;
4598         }
4599
4600         return &parm_table[num];
4601 }
4602
4603 /***************************************************************************
4604  Return info about the next parameter in a service.
4605  snum==GLOBAL_SECTION_SNUM gives the globals.
4606  Return NULL when out of parameters.
4607 ***************************************************************************/
4608
4609 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
4610 {
4611         if (snum < 0) {
4612                 /* do the globals */
4613                 for (; parm_table[*i].label; (*i)++) {
4614                         if (parm_table[*i].p_class == P_SEPARATOR)
4615                                 return &parm_table[(*i)++];
4616
4617                         if (!parm_table[*i].ptr
4618                             || (*parm_table[*i].label == '-'))
4619                                 continue;
4620
4621                         if ((*i) > 0
4622                             && (parm_table[*i].ptr ==
4623                                 parm_table[(*i) - 1].ptr))
4624                                 continue;
4625                         
4626                         if (is_default(*i) && !allparameters)
4627                                 continue;
4628
4629                         return &parm_table[(*i)++];
4630                 }
4631         } else {
4632                 service *pService = ServicePtrs[snum];
4633
4634                 for (; parm_table[*i].label; (*i)++) {
4635                         if (parm_table[*i].p_class == P_SEPARATOR)
4636                                 return &parm_table[(*i)++];
4637
4638                         if (parm_table[*i].p_class == P_LOCAL &&
4639                             parm_table[*i].ptr &&
4640                             (*parm_table[*i].label != '-') &&
4641                             ((*i) == 0 ||
4642                              (parm_table[*i].ptr !=
4643                               parm_table[(*i) - 1].ptr)))
4644                         {
4645                                 int pdiff =
4646                                         PTR_DIFF(parm_table[*i].ptr,
4647                                                  &sDefault);
4648
4649                                 if (allparameters ||
4650                                     !equal_parameter(parm_table[*i].type,
4651                                                      ((char *)pService) +
4652                                                      pdiff,
4653                                                      ((char *)&sDefault) +
4654                                                      pdiff))
4655                                 {
4656                                         return &parm_table[(*i)++];
4657                                 }
4658                         }
4659                 }
4660         }
4661
4662         return NULL;
4663 }
4664
4665
4666 #if 0
4667 /***************************************************************************
4668  Display the contents of a single copy structure.
4669 ***************************************************************************/
4670 static void dump_copy_map(bool *pcopymap)
4671 {
4672         int i;
4673         if (!pcopymap)
4674                 return;
4675
4676         printf("\n\tNon-Copied parameters:\n");
4677
4678         for (i = 0; parm_table[i].label; i++)
4679                 if (parm_table[i].p_class == P_LOCAL &&
4680                     parm_table[i].ptr && !pcopymap[i] &&
4681                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
4682                 {
4683                         printf("\t\t%s\n", parm_table[i].label);
4684                 }
4685 }
4686 #endif
4687
4688 /***************************************************************************
4689  Return TRUE if the passed service number is within range.
4690 ***************************************************************************/
4691
4692 bool lp_snum_ok(int iService)
4693 {
4694         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
4695 }
4696
4697 /***************************************************************************
4698  Auto-load some home services.
4699 ***************************************************************************/
4700
4701 static void lp_add_auto_services(char *str)
4702 {
4703         char *s;
4704         char *p;
4705         int homes;
4706
4707         if (!str)
4708                 return;
4709
4710         s = SMB_STRDUP(str);
4711         if (!s)
4712                 return;
4713
4714         homes = lp_servicenumber(HOMES_NAME);
4715
4716         for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
4717                 char *home = get_user_home_dir(p);
4718
4719                 if (lp_servicenumber(p) >= 0)
4720                         continue;
4721
4722                 if (home && homes >= 0)
4723                         lp_add_home(p, homes, p, home);
4724         }
4725         SAFE_FREE(s);
4726 }
4727
4728 /***************************************************************************
4729  Auto-load one printer.
4730 ***************************************************************************/
4731
4732 void lp_add_one_printer(char *name, char *comment)
4733 {
4734         int printers = lp_servicenumber(PRINTERS_NAME);
4735         int i;
4736
4737         if (lp_servicenumber(name) < 0) {
4738                 lp_add_printer(name, printers);
4739                 if ((i = lp_servicenumber(name)) >= 0) {
4740                         string_set(&ServicePtrs[i]->comment, comment);
4741                         ServicePtrs[i]->autoloaded = True;
4742                 }
4743         }
4744 }
4745
4746 /***************************************************************************
4747  Have we loaded a services file yet?
4748 ***************************************************************************/
4749
4750 bool lp_loaded(void)
4751 {
4752         return (bLoaded);
4753 }
4754
4755 /***************************************************************************
4756  Unload unused services.
4757 ***************************************************************************/
4758
4759 void lp_killunused(bool (*snumused) (int))
4760 {
4761         int i;
4762         for (i = 0; i < iNumServices; i++) {
4763                 if (!VALID(i))
4764                         continue;
4765
4766                 /* don't kill autoloaded or usershare services */
4767                 if ( ServicePtrs[i]->autoloaded ||
4768                                 ServicePtrs[i]->usershare == USERSHARE_VALID) {
4769                         continue;
4770                 }
4771
4772                 if (!snumused || !snumused(i)) {
4773                         free_service_byindex(i);
4774                 }
4775         }
4776 }
4777
4778 /***************************************************************************
4779  Unload a service.
4780 ***************************************************************************/
4781
4782 void lp_killservice(int iServiceIn)
4783 {
4784         if (VALID(iServiceIn)) {
4785                 free_service_byindex(iServiceIn);
4786         }
4787 }
4788
4789 /***************************************************************************
4790  Save the curent values of all global and sDefault parameters into the 
4791  defaults union. This allows swat and testparm to show only the
4792  changed (ie. non-default) parameters.
4793 ***************************************************************************/
4794
4795 static void lp_save_defaults(void)
4796 {
4797         int i;
4798         for (i = 0; parm_table[i].label; i++) {
4799                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
4800                         continue;
4801                 switch (parm_table[i].type) {
4802                         case P_LIST:
4803                                 str_list_copy(&(parm_table[i].def.lvalue),
4804                                             *(const char ***)parm_table[i].ptr);
4805                                 break;
4806                         case P_STRING:
4807                         case P_USTRING:
4808                                 if (parm_table[i].ptr) {
4809                                         parm_table[i].def.svalue = SMB_STRDUP(*(char **)parm_table[i].ptr);
4810                                 } else {
4811                                         parm_table[i].def.svalue = NULL;
4812                                 }
4813                                 break;
4814                         case P_GSTRING:
4815                         case P_UGSTRING:
4816                                 if (parm_table[i].ptr) {
4817                                         parm_table[i].def.svalue = SMB_STRDUP((char *)parm_table[i].ptr);
4818                                 } else {
4819                                         parm_table[i].def.svalue = NULL;
4820                                 }
4821                                 break;
4822                         case P_BOOL:
4823                         case P_BOOLREV:
4824                                 parm_table[i].def.bvalue =
4825                                         *(bool *)parm_table[i].ptr;
4826                                 break;
4827                         case P_CHAR:
4828                                 parm_table[i].def.cvalue =
4829                                         *(char *)parm_table[i].ptr;
4830                                 break;
4831                         case P_INTEGER:
4832                         case P_OCTAL:
4833                         case P_ENUM:
4834                                 parm_table[i].def.ivalue =
4835                                         *(int *)parm_table[i].ptr;
4836                                 break;
4837                         case P_SEP:
4838                                 break;
4839                 }
4840         }
4841         defaults_saved = True;
4842 }
4843
4844 /*******************************************************************
4845  Set the server type we will announce as via nmbd.
4846 ********************************************************************/
4847
4848 static const struct srv_role_tab {
4849         uint32 role;
4850         const char *role_str;
4851 } srv_role_tab [] = {
4852         { ROLE_STANDALONE, "ROLE_STANDALONE" },
4853         { ROLE_DOMAIN_MEMBER, "ROLE_DOMAIN_MEMBER" },
4854         { ROLE_DOMAIN_BDC, "ROLE_DOMAIN_BDC" },
4855         { ROLE_DOMAIN_PDC, "ROLE_DOMAIN_PDC" },
4856         { 0, NULL }
4857 };
4858
4859 const char* server_role_str(uint32 role)
4860 {
4861         int i = 0;
4862         for (i=0; srv_role_tab[i].role_str; i++) {
4863                 if (role == srv_role_tab[i].role) {
4864                         return srv_role_tab[i].role_str;
4865                 }
4866         }
4867         return NULL;
4868 }
4869
4870 static void set_server_role(void)
4871 {
4872         server_role = ROLE_STANDALONE;
4873
4874         switch (lp_security()) {
4875                 case SEC_SHARE:
4876                         if (lp_domain_logons())
4877                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
4878                         break;
4879                 case SEC_SERVER:
4880                         if (lp_domain_logons())
4881                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
4882                         /* this used to be considered ROLE_DOMAIN_MEMBER but that's just wrong */
4883                         server_role = ROLE_STANDALONE;
4884                         break;
4885                 case SEC_DOMAIN:
4886                         if (lp_domain_logons()) {
4887                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
4888                                 server_role = ROLE_DOMAIN_BDC;
4889                                 break;
4890                         }
4891                         server_role = ROLE_DOMAIN_MEMBER;
4892                         break;
4893                 case SEC_ADS:
4894                         if (lp_domain_logons()) {
4895                                 server_role = ROLE_DOMAIN_PDC;
4896                                 break;
4897                         }
4898                         server_role = ROLE_DOMAIN_MEMBER;
4899                         break;
4900                 case SEC_USER:
4901                         if (lp_domain_logons()) {
4902
4903                                 if (Globals.iDomainMaster) /* auto or yes */ 
4904                                         server_role = ROLE_DOMAIN_PDC;
4905                                 else
4906                                         server_role = ROLE_DOMAIN_BDC;
4907                         }
4908                         break;
4909                 default:
4910                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
4911                         break;
4912         }
4913
4914         DEBUG(10, ("set_server_role: role = %s\n", server_role_str(server_role)));
4915 }
4916
4917 /***********************************************************
4918  If we should send plaintext/LANMAN passwords in the clinet
4919 ************************************************************/
4920
4921 static void set_allowed_client_auth(void)
4922 {
4923         if (Globals.bClientNTLMv2Auth) {
4924                 Globals.bClientLanManAuth = False;
4925         }
4926         if (!Globals.bClientLanManAuth) {
4927                 Globals.bClientPlaintextAuth = False;
4928         }
4929 }
4930
4931 /***************************************************************************
4932  JRA.
4933  The following code allows smbd to read a user defined share file.
4934  Yes, this is my intent. Yes, I'm comfortable with that...
4935
4936  THE FOLLOWING IS SECURITY CRITICAL CODE.
4937
4938  It washes your clothes, it cleans your house, it guards you while you sleep...
4939  Do not f%^k with it....
4940 ***************************************************************************/
4941
4942 #define MAX_USERSHARE_FILE_SIZE (10*1024)
4943
4944 /***************************************************************************
4945  Check allowed stat state of a usershare file.
4946  Ensure we print out who is dicking with us so the admin can
4947  get their sorry ass fired.
4948 ***************************************************************************/
4949
4950 static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
4951 {
4952         if (!S_ISREG(psbuf->st_mode)) {
4953                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4954                         "not a regular file\n",
4955                         fname, (unsigned int)psbuf->st_uid ));
4956                 return False;
4957         }
4958
4959         /* Ensure this doesn't have the other write bit set. */
4960         if (psbuf->st_mode & S_IWOTH) {
4961                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4962                         "public write. Refusing to allow as a usershare file.\n",
4963                         fname, (unsigned int)psbuf->st_uid ));
4964                 return False;
4965         }
4966
4967         /* Should be 10k or less. */
4968         if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
4969                 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4970                         "too large (%u) to be a user share file.\n",
4971                         fname, (unsigned int)psbuf->st_uid,
4972                         (unsigned int)psbuf->st_size ));
4973                 return False;
4974         }
4975
4976         return True;
4977 }
4978
4979 /***************************************************************************
4980  Parse the contents of a usershare file.
4981 ***************************************************************************/
4982
4983 enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
4984                         SMB_STRUCT_STAT *psbuf,
4985                         const char *servicename,
4986                         int snum,
4987                         char **lines,
4988                         int numlines,
4989                         char **pp_sharepath,
4990                         char **pp_comment,
4991                         SEC_DESC **ppsd,
4992                         bool *pallow_guest)
4993 {
4994         const char **prefixallowlist = lp_usershare_prefix_allow_list();
4995         const char **prefixdenylist = lp_usershare_prefix_deny_list();
4996         int us_vers;
4997         SMB_STRUCT_DIR *dp;
4998         SMB_STRUCT_STAT sbuf;
4999         char *sharepath = NULL;
5000         char *comment = NULL;
5001
5002         *pp_sharepath = NULL;
5003         *pp_comment = NULL;
5004
5005         *pallow_guest = False;
5006
5007         if (numlines < 4) {
5008                 return USERSHARE_MALFORMED_FILE;
5009         }
5010
5011         if (strcmp(lines[0], "#VERSION 1") == 0) {
5012                 us_vers = 1;
5013         } else if (strcmp(lines[0], "#VERSION 2") == 0) {
5014                 us_vers = 2;
5015                 if (numlines < 5) {
5016                         return USERSHARE_MALFORMED_FILE;
5017                 }
5018         } else {
5019                 return USERSHARE_BAD_VERSION;
5020         }
5021
5022         if (strncmp(lines[1], "path=", 5) != 0) {
5023                 return USERSHARE_MALFORMED_PATH;
5024         }
5025
5026         sharepath = talloc_strdup(ctx, &lines[1][5]);
5027         if (!sharepath) {
5028                 return USERSHARE_POSIX_ERR;
5029         }
5030         trim_string(sharepath, " ", " ");
5031
5032         if (strncmp(lines[2], "comment=", 8) != 0) {
5033                 return USERSHARE_MALFORMED_COMMENT_DEF;
5034         }
5035
5036         comment = talloc_strdup(ctx, &lines[2][8]);
5037         if (!comment) {
5038                 return USERSHARE_POSIX_ERR;
5039         }
5040         trim_string(comment, " ", " ");
5041         trim_char(comment, '"', '"');
5042
5043         if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
5044                 return USERSHARE_MALFORMED_ACL_DEF;
5045         }
5046
5047         if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
5048                 return USERSHARE_ACL_ERR;
5049         }
5050
5051         if (us_vers == 2) {
5052                 if (strncmp(lines[4], "guest_ok=", 9) != 0) {
5053                         return USERSHARE_MALFORMED_ACL_DEF;
5054                 }
5055                 if (lines[4][9] == 'y') {
5056                         *pallow_guest = True;
5057                 }
5058         }
5059
5060         if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->szPath) == 0)) {
5061                 /* Path didn't change, no checks needed. */
5062                 *pp_sharepath = sharepath;
5063                 *pp_comment = comment;
5064                 return USERSHARE_OK;
5065         }
5066
5067         /* The path *must* be absolute. */
5068         if (sharepath[0] != '/') {
5069                 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
5070                         servicename, sharepath));
5071                 return USERSHARE_PATH_NOT_ABSOLUTE;
5072         }
5073
5074         /* If there is a usershare prefix deny list ensure one of these paths
5075            doesn't match the start of the user given path. */
5076         if (prefixdenylist) {
5077                 int i;
5078                 for ( i=0; prefixdenylist[i]; i++ ) {
5079                         DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
5080                                 servicename, i, prefixdenylist[i], sharepath ));
5081                         if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
5082                                 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
5083                                         "usershare prefix deny list entries.\n",
5084                                         servicename, sharepath));
5085                                 return USERSHARE_PATH_IS_DENIED;
5086                         }
5087                 }
5088         }
5089
5090         /* If there is a usershare prefix allow list ensure one of these paths
5091            does match the start of the user given path. */
5092
5093         if (prefixallowlist) {
5094                 int i;
5095                 for ( i=0; prefixallowlist[i]; i++ ) {
5096                         DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
5097                                 servicename, i, prefixallowlist[i], sharepath ));
5098                         if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
5099                                 break;
5100                         }
5101                 }
5102                 if (prefixallowlist[i] == NULL) {
5103                         DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
5104                                 "usershare prefix allow list entries.\n",
5105                                 servicename, sharepath));
5106                         return USERSHARE_PATH_NOT_ALLOWED;
5107                 }
5108         }
5109
5110         /* Ensure this is pointing to a directory. */
5111         dp = sys_opendir(sharepath);
5112
5113         if (!dp) {
5114                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
5115                         servicename, sharepath));
5116                 return USERSHARE_PATH_NOT_DIRECTORY;
5117         }
5118
5119         /* Ensure the owner of the usershare file has permission to share
5120            this directory. */
5121
5122         if (sys_stat(sharepath, &sbuf) == -1) {
5123                 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
5124                         servicename, sharepath, strerror(errno) ));
5125                 sys_closedir(dp);
5126                 return USERSHARE_POSIX_ERR;
5127         }
5128
5129         sys_closedir(dp);
5130
5131         if (!S_ISDIR(sbuf.st_mode)) {
5132                 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
5133                         servicename, sharepath ));
5134                 return USERSHARE_PATH_NOT_DIRECTORY;
5135         }
5136
5137         /* Check if sharing is restricted to owner-only. */
5138         /* psbuf is the stat of the usershare definition file,
5139            sbuf is the stat of the target directory to be shared. */
5140
5141         if (lp_usershare_owner_only()) {
5142                 /* root can share anything. */
5143                 if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
5144                         return USERSHARE_PATH_NOT_ALLOWED;
5145                 }
5146         }
5147
5148         *pp_sharepath = sharepath;
5149         *pp_comment = comment;
5150         return USERSHARE_OK;
5151 }
5152
5153 /***************************************************************************
5154  Deal with a usershare file.
5155  Returns:
5156         >= 0 - snum
5157         -1 - Bad name, invalid contents.
5158            - service name already existed and not a usershare, problem
5159             with permissions to share directory etc.
5160 ***************************************************************************/
5161
5162 static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
5163 {
5164         SMB_STRUCT_STAT sbuf;
5165         SMB_STRUCT_STAT lsbuf;
5166         char *fname = NULL;
5167         char *sharepath = NULL;
5168         char *comment = NULL;
5169         fstring service_name;
5170         char **lines = NULL;
5171         int numlines = 0;
5172         int fd = -1;
5173         int iService = -1;
5174         TALLOC_CTX *ctx = NULL;
5175         SEC_DESC *psd = NULL;
5176         bool guest_ok = False;
5177
5178         /* Ensure share name doesn't contain invalid characters. */
5179         if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
5180                 DEBUG(0,("process_usershare_file: share name %s contains "
5181                         "invalid characters (any of %s)\n",
5182                         file_name, INVALID_SHARENAME_CHARS ));
5183                 return -1;
5184         }
5185
5186         fstrcpy(service_name, file_name);
5187
5188         if (asprintf(&fname, "%s/%s", dir_name, file_name) < 0) {
5189         }
5190
5191         /* Minimize the race condition by doing an lstat before we
5192            open and fstat. Ensure this isn't a symlink link. */
5193
5194         if (sys_lstat(fname, &lsbuf) != 0) {
5195                 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
5196                         fname, strerror(errno) ));
5197                 SAFE_FREE(fname);
5198                 return -1;
5199         }
5200
5201         /* This must be a regular file, not a symlink, directory or
5202            other strange filetype. */
5203         if (!check_usershare_stat(fname, &lsbuf)) {
5204                 SAFE_FREE(fname);
5205                 return -1;
5206         }
5207
5208         /* See if there is already a servicenum for this name. */
5209         /* tdb_fetch_int32 returns -1 if not found. */
5210         iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
5211
5212         if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
5213                 /* Nothing changed - Mark valid and return. */
5214                 DEBUG(10,("process_usershare_file: service %s not changed.\n",
5215                         service_name ));
5216                 ServicePtrs[iService]->usershare = USERSHARE_VALID;
5217                 SAFE_FREE(fname);
5218                 return iService;
5219         }
5220
5221         /* Try and open the file read only - no symlinks allowed. */
5222 #ifdef O_NOFOLLOW
5223         fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
5224 #else
5225         fd = sys_open(fname, O_RDONLY, 0);
5226 #endif
5227
5228         if (fd == -1) {
5229                 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
5230                         fname, strerror(errno) ));
5231                 SAFE_FREE(fname);
5232                 return -1;
5233         }
5234
5235         /* Now fstat to be *SURE* it's a regular file. */
5236         if (sys_fstat(fd, &sbuf) != 0) {
5237                 close(fd);
5238                 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
5239                         fname, strerror(errno) ));
5240                 SAFE_FREE(fname);
5241                 return -1;
5242         }
5243
5244         /* Is it the same dev/inode as was lstated ? */
5245         if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
5246                 close(fd);
5247                 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
5248                         "Symlink spoofing going on ?\n", fname ));
5249                 SAFE_FREE(fname);
5250                 return -1;
5251         }
5252
5253         /* This must be a regular file, not a symlink, directory or
5254            other strange filetype. */
5255         if (!check_usershare_stat(fname, &sbuf)) {
5256                 SAFE_FREE(fname);
5257                 return -1;
5258         }
5259
5260         lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
5261
5262         close(fd);
5263         if (lines == NULL) {
5264                 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
5265                         fname, (unsigned int)sbuf.st_uid ));
5266                 SAFE_FREE(fname);
5267                 return -1;
5268         }
5269
5270         SAFE_FREE(fname);
5271
5272         /* Should we allow printers to be shared... ? */
5273         ctx = talloc_init("usershare_sd_xctx");
5274         if (!ctx) {
5275                 file_lines_free(lines);
5276                 return 1;
5277         }
5278
5279         if (parse_usershare_file(ctx, &sbuf, service_name,
5280                         iService, lines, numlines, &sharepath,
5281                         &comment, &psd, &guest_ok) != USERSHARE_OK) {
5282                 talloc_destroy(ctx);
5283                 file_lines_free(lines);
5284                 return -1;
5285         }
5286
5287         file_lines_free(lines);
5288
5289         /* Everything ok - add the service possibly using a template. */
5290         if (iService < 0) {
5291                 const service *sp = &sDefault;
5292                 if (snum_template != -1) {
5293                         sp = ServicePtrs[snum_template];
5294                 }
5295
5296                 if ((iService = add_a_service(sp, service_name)) < 0) {
5297                         DEBUG(0, ("process_usershare_file: Failed to add "
5298                                 "new service %s\n", service_name));
5299                         talloc_destroy(ctx);
5300                         return -1;
5301                 }
5302
5303                 /* Read only is controlled by usershare ACL below. */
5304                 ServicePtrs[iService]->bRead_only = False;
5305         }
5306
5307         /* Write the ACL of the new/modified share. */
5308         if (!set_share_security(service_name, psd)) {
5309                  DEBUG(0, ("process_usershare_file: Failed to set share "
5310                         "security for user share %s\n",
5311                         service_name ));
5312                 lp_remove_service(iService);
5313                 talloc_destroy(ctx);
5314                 return -1;
5315         }
5316
5317         /* If from a template it may be marked invalid. */
5318         ServicePtrs[iService]->valid = True;
5319
5320         /* Set the service as a valid usershare. */
5321         ServicePtrs[iService]->usershare = USERSHARE_VALID;
5322
5323         /* Set guest access. */
5324         if (lp_usershare_allow_guests()) {
5325                 ServicePtrs[iService]->bGuest_ok = guest_ok;
5326         }
5327
5328         /* And note when it was loaded. */
5329         ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
5330         string_set(&ServicePtrs[iService]->szPath, sharepath);
5331         string_set(&ServicePtrs[iService]->comment, comment);
5332
5333         talloc_destroy(ctx);
5334
5335         return iService;
5336 }
5337
5338 /***************************************************************************
5339  Checks if a usershare entry has been modified since last load.
5340 ***************************************************************************/
5341
5342 static bool usershare_exists(int iService, time_t *last_mod)
5343 {
5344         SMB_STRUCT_STAT lsbuf;
5345         const char *usersharepath = Globals.szUsersharePath;
5346         char *fname;
5347
5348         if (asprintf(&fname, "%s/%s",
5349                                 usersharepath,
5350                                 ServicePtrs[iService]->szService) < 0) {
5351                 return false;
5352         }
5353
5354         if (sys_lstat(fname, &lsbuf) != 0) {
5355                 SAFE_FREE(fname);
5356                 return false;
5357         }
5358
5359         if (!S_ISREG(lsbuf.st_mode)) {
5360                 SAFE_FREE(fname);
5361                 return false;
5362         }
5363
5364         SAFE_FREE(fname);
5365         *last_mod = lsbuf.st_mtime;
5366         return true;
5367 }
5368
5369 /***************************************************************************
5370  Load a usershare service by name. Returns a valid servicenumber or -1.
5371 ***************************************************************************/
5372
5373 int load_usershare_service(const char *servicename)
5374 {
5375         SMB_STRUCT_STAT sbuf;
5376         const char *usersharepath = Globals.szUsersharePath;
5377         int max_user_shares = Globals.iUsershareMaxShares;
5378         int snum_template = -1;
5379
5380         if (*usersharepath == 0 ||  max_user_shares == 0) {
5381                 return -1;
5382         }
5383
5384         if (sys_stat(usersharepath, &sbuf) != 0) {
5385                 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
5386                         usersharepath, strerror(errno) ));
5387                 return -1;
5388         }
5389
5390         if (!S_ISDIR(sbuf.st_mode)) {
5391                 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
5392                         usersharepath ));
5393                 return -1;
5394         }
5395
5396         /*
5397          * This directory must be owned by root, and have the 't' bit set.
5398          * It also must not be writable by "other".
5399          */
5400
5401 #ifdef S_ISVTX
5402         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5403 #else
5404         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5405 #endif
5406                 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
5407                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5408                         usersharepath ));
5409                 return -1;
5410         }
5411
5412         /* Ensure the template share exists if it's set. */
5413         if (Globals.szUsershareTemplateShare[0]) {
5414                 /* We can't use lp_servicenumber here as we are recommending that
5415                    template shares have -valid=False set. */
5416                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5417                         if (ServicePtrs[snum_template]->szService &&
5418                                         strequal(ServicePtrs[snum_template]->szService,
5419                                                 Globals.szUsershareTemplateShare)) {
5420                                 break;
5421                         }
5422                 }
5423
5424                 if (snum_template == -1) {
5425                         DEBUG(0,("load_usershare_service: usershare template share %s "
5426                                 "does not exist.\n",
5427                                 Globals.szUsershareTemplateShare ));
5428                         return -1;
5429                 }
5430         }
5431
5432         return process_usershare_file(usersharepath, servicename, snum_template);
5433 }
5434
5435 /***************************************************************************
5436  Load all user defined shares from the user share directory.
5437  We only do this if we're enumerating the share list.
5438  This is the function that can delete usershares that have
5439  been removed.
5440 ***************************************************************************/
5441
5442 int load_usershare_shares(void)
5443 {
5444         SMB_STRUCT_DIR *dp;
5445         SMB_STRUCT_STAT sbuf;
5446         SMB_STRUCT_DIRENT *de;
5447         int num_usershares = 0;
5448         int max_user_shares = Globals.iUsershareMaxShares;
5449         unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
5450         unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
5451         unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
5452         int iService;
5453         int snum_template = -1;
5454         const char *usersharepath = Globals.szUsersharePath;
5455         int ret = lp_numservices();
5456
5457         if (max_user_shares == 0 || *usersharepath == '\0') {
5458                 return lp_numservices();
5459         }
5460
5461         if (sys_stat(usersharepath, &sbuf) != 0) {
5462                 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
5463                         usersharepath, strerror(errno) ));
5464                 return ret;
5465         }
5466
5467         /*
5468          * This directory must be owned by root, and have the 't' bit set.
5469          * It also must not be writable by "other".
5470          */
5471
5472 #ifdef S_ISVTX
5473         if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
5474 #else
5475         if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
5476 #endif
5477                 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
5478                         "or does not have the sticky bit 't' set or is writable by anyone.\n",
5479                         usersharepath ));
5480                 return ret;
5481         }
5482
5483         /* Ensure the template share exists if it's set. */
5484         if (Globals.szUsershareTemplateShare[0]) {
5485                 /* We can't use lp_servicenumber here as we are recommending that
5486                    template shares have -valid=False set. */
5487                 for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
5488                         if (ServicePtrs[snum_template]->szService &&
5489                                         strequal(ServicePtrs[snum_template]->szService,
5490                                                 Globals.szUsershareTemplateShare)) {
5491                                 break;
5492                         }
5493                 }
5494
5495                 if (snum_template == -1) {
5496                         DEBUG(0,("load_usershare_shares: usershare template share %s "
5497                                 "does not exist.\n",
5498                                 Globals.szUsershareTemplateShare ));
5499                         return ret;
5500                 }
5501         }
5502
5503         /* Mark all existing usershares as pending delete. */
5504         for (iService = iNumServices - 1; iService >= 0; iService--) {
5505                 if (VALID(iService) && ServicePtrs[iService]->usershare) {
5506                         ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
5507                 }
5508         }
5509
5510         dp = sys_opendir(usersharepath);
5511         if (!dp) {
5512                 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
5513                         usersharepath, strerror(errno) ));
5514                 return ret;
5515         }
5516
5517         for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
5518                         (de = sys_readdir(dp));
5519                         num_dir_entries++ ) {
5520                 int r;
5521                 const char *n = de->d_name;
5522
5523                 /* Ignore . and .. */
5524                 if (*n == '.') {
5525                         if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
5526                                 continue;
5527                         }
5528                 }
5529
5530                 if (n[0] == ':') {
5531                         /* Temporary file used when creating a share. */
5532                         num_tmp_dir_entries++;
5533                 }
5534
5535                 /* Allow 20% tmp entries. */
5536                 if (num_tmp_dir_entries > allowed_tmp_entries) {
5537                         DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
5538                                 "in directory %s\n",
5539                                 num_tmp_dir_entries, usersharepath));
5540                         break;
5541                 }
5542
5543                 r = process_usershare_file(usersharepath, n, snum_template);
5544                 if (r == 0) {
5545                         /* Update the services count. */
5546                         num_usershares++;
5547                         if (num_usershares >= max_user_shares) {
5548                                 DEBUG(0,("load_usershare_shares: max user shares reached "
5549                                         "on file %s in directory %s\n",
5550                                         n, usersharepath ));
5551                                 break;
5552                         }
5553                 } else if (r == -1) {
5554                         num_bad_dir_entries++;
5555                 }
5556
5557                 /* Allow 20% bad entries. */
5558                 if (num_bad_dir_entries > allowed_bad_entries) {
5559                         DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
5560                                 "in directory %s\n",
5561                                 num_bad_dir_entries, usersharepath));
5562                         break;
5563                 }
5564
5565                 /* Allow 20% bad entries. */
5566                 if (num_dir_entries > max_user_shares + allowed_bad_entries) {
5567                         DEBUG(0,("load_usershare_shares: too many total entries (%u) "
5568                         "in directory %s\n",
5569                         num_dir_entries, usersharepath));
5570                         break;
5571                 }
5572         }
5573
5574         sys_closedir(dp);
5575
5576         /* Sweep through and delete any non-refreshed usershares that are
5577            not currently in use. */
5578         for (iService = iNumServices - 1; iService >= 0; iService--) {
5579                 if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
5580                         if (conn_snum_used(iService)) {
5581                                 continue;
5582                         }
5583                         /* Remove from the share ACL db. */
5584                         DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
5585                                 lp_servicename(iService) ));
5586                         delete_share_security(lp_servicename(iService));
5587                         free_service_byindex(iService);
5588                 }
5589         }
5590
5591         return lp_numservices();
5592 }
5593
5594 /********************************************************
5595  Destroy global resources allocated in this file
5596 ********************************************************/
5597
5598 void gfree_loadparm(void)
5599 {
5600         struct file_lists *f;
5601         struct file_lists *next;
5602         int i;
5603
5604         /* Free the file lists */
5605
5606         f = file_lists;
5607         while( f ) {
5608                 next = f->next;
5609                 SAFE_FREE( f->name );
5610                 SAFE_FREE( f->subfname );
5611                 SAFE_FREE( f );
5612                 f = next;
5613         }
5614
5615         /* Free resources allocated to services */
5616
5617         for ( i = 0; i < iNumServices; i++ ) {
5618                 if ( VALID(i) ) {
5619                         free_service_byindex(i);
5620                 }
5621         }
5622
5623         SAFE_FREE( ServicePtrs );
5624         iNumServices = 0;
5625
5626         /* Now release all resources allocated to global
5627            parameters and the default service */
5628
5629         for (i = 0; parm_table[i].label; i++) 
5630         {
5631                 if ( parm_table[i].type == P_STRING 
5632                         || parm_table[i].type == P_USTRING ) 
5633                 {
5634                         string_free( (char**)parm_table[i].ptr );
5635                 }
5636                 else if (parm_table[i].type == P_LIST) {
5637                         str_list_free( (char***)parm_table[i].ptr );
5638                 }
5639         }
5640 }
5641
5642 /***************************************************************************
5643  Load the services array from the services file. Return True on success, 
5644  False on failure.
5645 ***************************************************************************/
5646
5647 bool lp_load(const char *pszFname,
5648              bool global_only,
5649              bool save_defaults,
5650              bool add_ipc,
5651              bool initialize_globals)
5652 {
5653         char *n2 = NULL;
5654         bool bRetval;
5655         param_opt_struct *data, *pdata;
5656
5657         n2 = alloc_sub_basic(get_current_username(),
5658                                 current_user_info.domain,
5659                                 pszFname);
5660         if (!n2) {
5661                 smb_panic("lp_load: out of memory");
5662         }
5663
5664         add_to_file_list(pszFname, n2);
5665
5666         bRetval = False;
5667
5668         DEBUG(3, ("lp_load: refreshing parameters\n"));
5669
5670         bInGlobalSection = True;
5671         bGlobalOnly = global_only;
5672
5673         init_globals(! initialize_globals);
5674         debug_init();
5675
5676         if (save_defaults) {
5677                 init_locals();
5678                 lp_save_defaults();
5679         }
5680
5681         if (Globals.param_opt != NULL) {
5682                 data = Globals.param_opt;
5683                 while (data) {
5684                         string_free(&data->key);
5685                         string_free(&data->value);
5686                         str_list_free(&data->list);
5687                         pdata = data->next;
5688                         SAFE_FREE(data);
5689                         data = pdata;
5690                 }
5691                 Globals.param_opt = NULL;
5692         }
5693
5694         /* We get sections first, so have to start 'behind' to make up */
5695         iServiceIndex = -1;
5696         bRetval = pm_process(n2, do_section, do_parameter);
5697         SAFE_FREE(n2);
5698
5699         /* finish up the last section */
5700         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
5701         if (bRetval) {
5702                 if (iServiceIndex >= 0) {
5703                         bRetval = service_ok(iServiceIndex);
5704                 }
5705         }
5706
5707         lp_add_auto_services(lp_auto_services());
5708
5709         if (add_ipc) {
5710                 /* When 'restrict anonymous = 2' guest connections to ipc$
5711                    are denied */
5712                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
5713                 if ( lp_enable_asu_support() ) {
5714                         lp_add_ipc("ADMIN$", false);
5715                 }
5716         }
5717
5718         set_server_role();
5719         set_default_server_announce_type();
5720         set_allowed_client_auth();
5721
5722         bLoaded = True;
5723
5724         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
5725         /* if bWINSsupport is true and we are in the client            */
5726         if (in_client && Globals.bWINSsupport) {
5727                 lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
5728         }
5729
5730         init_iconv();
5731
5732         return (bRetval);
5733 }
5734
5735 /***************************************************************************
5736  Reset the max number of services.
5737 ***************************************************************************/
5738
5739 void lp_resetnumservices(void)
5740 {
5741         iNumServices = 0;
5742 }
5743
5744 /***************************************************************************
5745  Return the max number of services.
5746 ***************************************************************************/
5747
5748 int lp_numservices(void)
5749 {
5750         return (iNumServices);
5751 }
5752
5753 /***************************************************************************
5754 Display the contents of the services array in human-readable form.
5755 ***************************************************************************/
5756
5757 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
5758 {
5759         int iService;
5760
5761         if (show_defaults)
5762                 defaults_saved = False;
5763
5764         dump_globals(f);
5765
5766         dump_a_service(&sDefault, f);
5767
5768         for (iService = 0; iService < maxtoprint; iService++) {
5769                 fprintf(f,"\n");
5770                 lp_dump_one(f, show_defaults, iService);
5771         }
5772 }
5773
5774 /***************************************************************************
5775 Display the contents of one service in human-readable form.
5776 ***************************************************************************/
5777
5778 void lp_dump_one(FILE * f, bool show_defaults, int snum)
5779 {
5780         if (VALID(snum)) {
5781                 if (ServicePtrs[snum]->szService[0] == '\0')
5782                         return;
5783                 dump_a_service(ServicePtrs[snum], f);
5784         }
5785 }
5786
5787 /***************************************************************************
5788 Return the number of the service with the given name, or -1 if it doesn't
5789 exist. Note that this is a DIFFERENT ANIMAL from the internal function
5790 getservicebyname()! This works ONLY if all services have been loaded, and
5791 does not copy the found service.
5792 ***************************************************************************/
5793
5794 int lp_servicenumber(const char *pszServiceName)
5795 {
5796         int iService;
5797         fstring serviceName;
5798         
5799         if (!pszServiceName) {
5800                 return GLOBAL_SECTION_SNUM;
5801         }
5802         
5803         for (iService = iNumServices - 1; iService >= 0; iService--) {
5804                 if (VALID(iService) && ServicePtrs[iService]->szService) {
5805                         /*
5806                          * The substitution here is used to support %U is
5807                          * service names
5808                          */
5809                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
5810                         standard_sub_basic(get_current_username(),
5811                                            current_user_info.domain,
5812                                            serviceName,sizeof(serviceName));
5813                         if (strequal(serviceName, pszServiceName)) {
5814                                 break;
5815                         }
5816                 }
5817         }
5818
5819         if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
5820                 time_t last_mod;
5821
5822                 if (!usershare_exists(iService, &last_mod)) {
5823                         /* Remove the share security tdb entry for it. */
5824                         delete_share_security(lp_servicename(iService));
5825                         /* Remove it from the array. */
5826                         free_service_byindex(iService);
5827                         /* Doesn't exist anymore. */
5828                         return GLOBAL_SECTION_SNUM;
5829                 }
5830
5831                 /* Has it been modified ? If so delete and reload. */
5832                 if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
5833                         /* Remove it from the array. */
5834                         free_service_byindex(iService);
5835                         /* and now reload it. */
5836                         iService = load_usershare_service(pszServiceName);
5837                 }
5838         }
5839
5840         if (iService < 0) {
5841                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
5842                 return GLOBAL_SECTION_SNUM;
5843         }
5844
5845         return (iService);
5846 }
5847
5848 bool share_defined(const char *service_name)
5849 {
5850         return (lp_servicenumber(service_name) != -1);
5851 }
5852
5853 struct share_params *get_share_params(TALLOC_CTX *mem_ctx,
5854                                       const char *sharename)
5855 {
5856         struct share_params *result;
5857         char *sname;
5858         int snum;
5859
5860         if (!(sname = SMB_STRDUP(sharename))) {
5861                 return NULL;
5862         }
5863
5864         snum = find_service(sname);
5865         SAFE_FREE(sname);
5866
5867         if (snum < 0) {
5868                 return NULL;
5869         }
5870
5871         if (!(result = TALLOC_P(mem_ctx, struct share_params))) {
5872                 DEBUG(0, ("talloc failed\n"));
5873                 return NULL;
5874         }
5875
5876         result->service = snum;
5877         return result;
5878 }
5879
5880 struct share_iterator *share_list_all(TALLOC_CTX *mem_ctx)
5881 {
5882         struct share_iterator *result;
5883
5884         if (!(result = TALLOC_P(mem_ctx, struct share_iterator))) {
5885                 DEBUG(0, ("talloc failed\n"));
5886                 return NULL;
5887         }
5888
5889         result->next_id = 0;
5890         return result;
5891 }
5892
5893 struct share_params *next_share(struct share_iterator *list)
5894 {
5895         struct share_params *result;
5896
5897         while (!lp_snum_ok(list->next_id) &&
5898                (list->next_id < lp_numservices())) {
5899                 list->next_id += 1;
5900         }
5901
5902         if (list->next_id >= lp_numservices()) {
5903                 return NULL;
5904         }
5905
5906         if (!(result = TALLOC_P(list, struct share_params))) {
5907                 DEBUG(0, ("talloc failed\n"));
5908                 return NULL;
5909         }
5910
5911         result->service = list->next_id;
5912         list->next_id += 1;
5913         return result;
5914 }
5915
5916 struct share_params *next_printer(struct share_iterator *list)
5917 {
5918         struct share_params *result;
5919
5920         while ((result = next_share(list)) != NULL) {
5921                 if (lp_print_ok(result->service)) {
5922                         break;
5923                 }
5924         }
5925         return result;
5926 }
5927
5928 /*
5929  * This is a hack for a transition period until we transformed all code from
5930  * service numbers to struct share_params.
5931  */
5932
5933 struct share_params *snum2params_static(int snum)
5934 {
5935         static struct share_params result;
5936         result.service = snum;
5937         return &result;
5938 }
5939
5940 /*******************************************************************
5941  A useful volume label function. 
5942 ********************************************************************/
5943
5944 const char *volume_label(int snum)
5945 {
5946         char *ret;
5947         const char *label = lp_volume(snum);
5948         if (!*label) {
5949                 label = lp_servicename(snum);
5950         }
5951                 
5952         /* This returns a 33 byte guarenteed null terminated string. */
5953         ret = talloc_strndup(talloc_tos(), label, 32);
5954         if (!ret) {
5955                 return "";
5956         }               
5957         return ret;
5958 }
5959
5960 /*******************************************************************
5961  Set the server type we will announce as via nmbd.
5962 ********************************************************************/
5963
5964 static void set_default_server_announce_type(void)
5965 {
5966         default_server_announce = 0;
5967         default_server_announce |= SV_TYPE_WORKSTATION;
5968         default_server_announce |= SV_TYPE_SERVER;
5969         default_server_announce |= SV_TYPE_SERVER_UNIX;
5970
5971         /* note that the flag should be set only if we have a 
5972            printer service but nmbd doesn't actually load the 
5973            services so we can't tell   --jerry */
5974
5975         default_server_announce |= SV_TYPE_PRINTQ_SERVER;
5976
5977         switch (lp_announce_as()) {
5978                 case ANNOUNCE_AS_NT_SERVER:
5979                         default_server_announce |= SV_TYPE_SERVER_NT;
5980                         /* fall through... */
5981                 case ANNOUNCE_AS_NT_WORKSTATION:
5982                         default_server_announce |= SV_TYPE_NT;
5983                         break;
5984                 case ANNOUNCE_AS_WIN95:
5985                         default_server_announce |= SV_TYPE_WIN95_PLUS;
5986                         break;
5987                 case ANNOUNCE_AS_WFW:
5988                         default_server_announce |= SV_TYPE_WFW;
5989                         break;
5990                 default:
5991                         break;
5992         }
5993
5994         switch (lp_server_role()) {
5995                 case ROLE_DOMAIN_MEMBER:
5996                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
5997                         break;
5998                 case ROLE_DOMAIN_PDC:
5999                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
6000                         break;
6001                 case ROLE_DOMAIN_BDC:
6002                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
6003                         break;
6004                 case ROLE_STANDALONE:
6005                 default:
6006                         break;
6007         }
6008         if (lp_time_server())
6009                 default_server_announce |= SV_TYPE_TIME_SOURCE;
6010
6011         if (lp_host_msdfs())
6012                 default_server_announce |= SV_TYPE_DFS_SERVER;
6013 }
6014
6015 /***********************************************************
6016  returns role of Samba server
6017 ************************************************************/
6018
6019 int lp_server_role(void)
6020 {
6021         return server_role;
6022 }
6023
6024 /***********************************************************
6025  If we are PDC then prefer us as DMB
6026 ************************************************************/
6027
6028 bool lp_domain_master(void)
6029 {
6030         if (Globals.iDomainMaster == Auto)
6031                 return (lp_server_role() == ROLE_DOMAIN_PDC);
6032
6033         return (bool)Globals.iDomainMaster;
6034 }
6035
6036 /***********************************************************
6037  If we are DMB then prefer us as LMB
6038 ************************************************************/
6039
6040 bool lp_preferred_master(void)
6041 {
6042         if (Globals.iPreferredMaster == Auto)
6043                 return (lp_local_master() && lp_domain_master());
6044
6045         return (bool)Globals.iPreferredMaster;
6046 }
6047
6048 /*******************************************************************
6049  Remove a service.
6050 ********************************************************************/
6051
6052 void lp_remove_service(int snum)
6053 {
6054         ServicePtrs[snum]->valid = False;
6055         invalid_services[num_invalid_services++] = snum;
6056 }
6057
6058 /*******************************************************************
6059  Copy a service.
6060 ********************************************************************/
6061
6062 void lp_copy_service(int snum, const char *new_name)
6063 {
6064         do_section(new_name);
6065         if (snum >= 0) {
6066                 snum = lp_servicenumber(new_name);
6067                 if (snum >= 0)
6068                         lp_do_parameter(snum, "copy", lp_servicename(snum));
6069         }
6070 }
6071
6072
6073 /*******************************************************************
6074  Get the default server type we will announce as via nmbd.
6075 ********************************************************************/
6076
6077 int lp_default_server_announce(void)
6078 {
6079         return default_server_announce;
6080 }
6081
6082 /*******************************************************************
6083  Split the announce version into major and minor numbers.
6084 ********************************************************************/
6085
6086 int lp_major_announce_version(void)
6087 {
6088         static bool got_major = False;
6089         static int major_version = DEFAULT_MAJOR_VERSION;
6090         char *vers;
6091         char *p;
6092
6093         if (got_major)
6094                 return major_version;
6095
6096         got_major = True;
6097         if ((vers = lp_announce_version()) == NULL)
6098                 return major_version;
6099
6100         if ((p = strchr_m(vers, '.')) == 0)
6101                 return major_version;
6102
6103         *p = '\0';
6104         major_version = atoi(vers);
6105         return major_version;
6106 }
6107
6108 int lp_minor_announce_version(void)
6109 {
6110         static bool got_minor = False;
6111         static int minor_version = DEFAULT_MINOR_VERSION;
6112         char *vers;
6113         char *p;
6114
6115         if (got_minor)
6116                 return minor_version;
6117
6118         got_minor = True;
6119         if ((vers = lp_announce_version()) == NULL)
6120                 return minor_version;
6121
6122         if ((p = strchr_m(vers, '.')) == 0)
6123                 return minor_version;
6124
6125         p++;
6126         minor_version = atoi(p);
6127         return minor_version;
6128 }
6129
6130 /***********************************************************
6131  Set the global name resolution order (used in smbclient).
6132 ************************************************************/
6133
6134 void lp_set_name_resolve_order(const char *new_order)
6135 {
6136         string_set(&Globals.szNameResolveOrder, new_order);
6137 }
6138
6139 const char *lp_printername(int snum)
6140 {
6141         const char *ret = _lp_printername(snum);
6142         if (ret == NULL || (ret != NULL && *ret == '\0'))
6143                 ret = lp_const_servicename(snum);
6144
6145         return ret;
6146 }
6147
6148
6149 /***********************************************************
6150  Allow daemons such as winbindd to fix their logfile name.
6151 ************************************************************/
6152
6153 void lp_set_logfile(const char *name)
6154 {
6155         string_set(&Globals.szLogFile, name);
6156         debug_set_logfile(name);
6157 }
6158
6159 /*******************************************************************
6160  Return the max print jobs per queue.
6161 ********************************************************************/
6162
6163 int lp_maxprintjobs(int snum)
6164 {
6165         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
6166         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
6167                 maxjobs = PRINT_MAX_JOBID - 1;
6168
6169         return maxjobs;
6170 }
6171
6172 const char *lp_printcapname(void)
6173 {
6174         if ((Globals.szPrintcapname != NULL) &&
6175             (Globals.szPrintcapname[0] != '\0'))
6176                 return Globals.szPrintcapname;
6177
6178         if (sDefault.iPrinting == PRINT_CUPS) {
6179 #ifdef HAVE_CUPS
6180                 return "cups";
6181 #else
6182                 return "lpstat";
6183 #endif
6184         }
6185
6186         if (sDefault.iPrinting == PRINT_BSD)
6187                 return "/etc/printcap";
6188
6189         return PRINTCAP_NAME;
6190 }
6191
6192 /*******************************************************************
6193  Ensure we don't use sendfile if server smb signing is active.
6194 ********************************************************************/
6195
6196 static uint32 spoolss_state;
6197
6198 bool lp_disable_spoolss( void )
6199 {
6200         if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
6201                 spoolss_state = _lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6202
6203         return spoolss_state == SVCCTL_STOPPED ? True : False;
6204 }
6205
6206 void lp_set_spoolss_state( uint32 state )
6207 {
6208         SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
6209
6210         spoolss_state = state;
6211 }
6212
6213 uint32 lp_get_spoolss_state( void )
6214 {
6215         return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
6216 }
6217
6218 /*******************************************************************
6219  Ensure we don't use sendfile if server smb signing is active.
6220 ********************************************************************/
6221
6222 bool lp_use_sendfile(int snum)
6223 {
6224         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
6225         if (Protocol < PROTOCOL_NT1) {
6226                 return False;
6227         }
6228         return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && !srv_is_signing_active());
6229 }
6230
6231 /*******************************************************************
6232  Turn off sendfile if we find the underlying OS doesn't support it.
6233 ********************************************************************/
6234
6235 void set_use_sendfile(int snum, bool val)
6236 {
6237         if (LP_SNUM_OK(snum))
6238                 ServicePtrs[snum]->bUseSendfile = val;
6239         else
6240                 sDefault.bUseSendfile = val;
6241 }
6242
6243 /*******************************************************************
6244  Turn off storing DOS attributes if this share doesn't support it.
6245 ********************************************************************/
6246
6247 void set_store_dos_attributes(int snum, bool val)
6248 {
6249         if (!LP_SNUM_OK(snum))
6250                 return;
6251         ServicePtrs[(snum)]->bStoreDosAttributes = val;
6252 }
6253
6254 void lp_set_mangling_method(const char *new_method)
6255 {
6256         string_set(&Globals.szManglingMethod, new_method);
6257 }
6258
6259 /*******************************************************************
6260  Global state for POSIX pathname processing.
6261 ********************************************************************/
6262
6263 static bool posix_pathnames;
6264
6265 bool lp_posix_pathnames(void)
6266 {
6267         return posix_pathnames;
6268 }
6269
6270 /*******************************************************************
6271  Change everything needed to ensure POSIX pathname processing (currently
6272  not much).
6273 ********************************************************************/
6274
6275 void lp_set_posix_pathnames(void)
6276 {
6277         posix_pathnames = True;
6278 }
6279
6280 /*******************************************************************
6281  Global state for POSIX lock processing - CIFS unix extensions.
6282 ********************************************************************/
6283
6284 bool posix_default_lock_was_set;
6285 static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
6286
6287 enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
6288 {
6289         if (posix_default_lock_was_set) {
6290                 return posix_cifsx_locktype;
6291         } else {
6292                 return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
6293         }
6294 }
6295
6296 /*******************************************************************
6297 ********************************************************************/
6298
6299 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
6300 {
6301         posix_default_lock_was_set = True;
6302         posix_cifsx_locktype = val;
6303 }
6304
6305 int lp_min_receive_file_size(void)
6306 {
6307         if (Globals.iminreceivefile < 0) {
6308                 return 0;
6309         }
6310         return MIN(Globals.iminreceivefile, BUFFER_SIZE);
6311 }