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