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