Move -V to -C to prevent conflict with -V for version
[kai/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) Anthony Liguori 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 2 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, write to the Free Software
25    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28 /*
29  *  Load parameters.
30  *
31  *  This module provides suitable callback functions for the params
32  *  module. It builds the internal table of service details which is
33  *  then used by the rest of the server.
34  *
35  * To add a parameter:
36  *
37  * 1) add it to the global or service structure definition
38  * 2) add it to the parm_table
39  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
40  * 4) If it's a global then initialise it in init_globals. If a local
41  *    (ie. service) parameter then initialise it in the sDefault structure
42  *  
43  *
44  * Notes:
45  *   The configuration file is processed sequentially for speed. It is NOT
46  *   accessed randomly as happens in 'real' Windows. For this reason, there
47  *   is a fair bit of sequence-dependent code here - ie., code which assumes
48  *   that certain things happen before others. In particular, the code which
49  *   happens at the boundary between sections is delicately poised, so be
50  *   careful!
51  *
52  */
53
54 #include "includes.h"
55
56 BOOL in_client = False;         /* Not in the client by default */
57 BOOL bLoaded = False;
58
59 extern userdom_struct current_user_info;
60 extern pstring user_socket_options;
61
62 #ifndef GLOBAL_NAME
63 #define GLOBAL_NAME "global"
64 #endif
65
66 #ifndef PRINTERS_NAME
67 #define PRINTERS_NAME "printers"
68 #endif
69
70 #ifndef HOMES_NAME
71 #define HOMES_NAME "homes"
72 #endif
73
74 /* some helpful bits */
75 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid)
76 #define VALID(i) ServicePtrs[i]->valid
77
78 int keepalive = DEFAULT_KEEPALIVE;
79 BOOL use_getwd_cache = True;
80
81 extern int extra_time_offset;
82
83 static BOOL defaults_saved = False;
84
85 typedef struct _param_opt_struct param_opt_struct;
86 struct _param_opt_struct {
87         param_opt_struct *prev, *next;
88         char *key;
89         char *value;
90 };
91
92 /* 
93  * This structure describes global (ie., server-wide) parameters.
94  */
95 typedef struct
96 {
97         char *smb_ports;
98         char *dos_charset;
99         char *unix_charset;
100         char *display_charset;
101         char *szPrintcapname;
102         char *szEnumPortsCommand;
103         char *szAddPrinterCommand;
104         char *szDeletePrinterCommand;
105         char *szOs2DriverMap;
106         char *szLockDir;
107         char *szPidDir;
108         char *szRootdir;
109         char *szDefaultService;
110         char *szDfree;
111         char *szMsgCommand;
112         char *szHostsEquiv;
113         char *szServerString;
114         char *szAutoServices;
115         char *szPasswdProgram;
116         char *szPasswdChat;
117         char *szLogFile;
118         char *szConfigFile;
119         char *szSMBPasswdFile;
120         char *szPrivateDir;
121         char **szPassdbBackend;
122         char **szSamBackend;
123         char **szPreloadModules;
124         char *szPasswordServer;
125         char *szSocketOptions;
126         char *szRealm;
127         char *szADSserver;
128         char *szUsernameMap;
129         char *szLogonScript;
130         char *szLogonPath;
131         char *szLogonDrive;
132         char *szLogonHome;
133         char **szWINSservers;
134         char **szInterfaces;
135         char *szRemoteAnnounce;
136         char *szRemoteBrowseSync;
137         char *szSocketAddress;
138         char *szNISHomeMapName;
139         char *szAnnounceVersion;        /* This is initialised in init_globals */
140         char *szWorkgroup;
141         char *szNetbiosName;
142         char **szNetbiosAliases;
143         char *szNetbiosScope;
144         char *szDomainOtherSIDs;
145         char *szNameResolveOrder;
146         char *szPanicAction;
147         char *szAddUserScript;
148         char *szDelUserScript;
149         char *szAddGroupScript;
150         char *szDelGroupScript;
151         char *szAddUserToGroupScript;
152         char *szDelUserFromGroupScript;
153         char *szSetPrimaryGroupScript;
154         char *szAddMachineScript;
155         char *szShutdownScript;
156         char *szAbortShutdownScript;
157         char *szWINSHook;
158         char *szWINSPartners;
159 #ifdef WITH_UTMP
160         char *szUtmpDir;
161         char *szWtmpDir;
162         BOOL bUtmp;
163 #endif
164         char *szSourceEnv;
165         char *szWinbindUID;
166         char *szWinbindGID;
167         char *szNonUnixAccountRange;
168         int AlgorithmicRidBase;
169         char *szTemplateHomedir;
170         char *szTemplateShell;
171         char *szWinbindSeparator;
172         BOOL bWinbindEnumUsers;
173         BOOL bWinbindEnumGroups;
174         BOOL bWinbindUseDefaultDomain;
175         char *szIDMapBackend;
176         char *szAddShareCommand;
177         char *szChangeShareCommand;
178         char *szDeleteShareCommand;
179         char *szGuestaccount;
180         char *szManglingMethod;
181         int mangle_prefix;
182         int max_log_size;
183         char *szLogLevel;
184         int mangled_stack;
185         int max_xmit;
186         int max_mux;
187         int max_open_files;
188         int pwordlevel;
189         int unamelevel;
190         int deadtime;
191         int maxprotocol;
192         int minprotocol;
193         int security;
194         char **AuthMethods;
195         BOOL paranoid_server_security;
196         int maxdisksize;
197         int lpqcachetime;
198         int iMaxSmbdProcesses;
199         BOOL bDisableSpoolss;
200         int iTotalPrintJobs;
201         int syslog;
202         int os_level;
203         int enhanced_browsing;
204         int max_ttl;
205         int max_wins_ttl;
206         int min_wins_ttl;
207         int ReadSize;
208         int lm_announce;
209         int lm_interval;
210         int announce_as;        /* This is initialised in init_globals */
211         int machine_password_timeout;
212         int change_notify_timeout;
213         int stat_cache_size;
214         int map_to_guest;
215         int min_passwd_length;
216         int oplock_break_wait_time;
217         int winbind_cache_time;
218         int iLockSpinCount;
219         int iLockSpinTime;
220         char *szLdapMachineSuffix;
221         char *szLdapUserSuffix;
222 #ifdef WITH_LDAP_SAMCONFIG
223         int ldap_port;
224         char *szLdapServer;
225 #endif
226         int ldap_ssl;
227         char *szLdapSuffix;
228         char *szLdapFilter;
229         char *szLdapAdminDn;
230         BOOL ldap_trust_ids;
231         char *szAclCompat;
232         int ldap_passwd_sync; 
233         BOOL ldap_del_only_sam;
234         BOOL bMsAddPrinterWizard;
235         BOOL bDNSproxy;
236         BOOL bWINSsupport;
237         BOOL bWINSproxy;
238         BOOL bLocalMaster;
239         BOOL bPreferredMaster;
240         BOOL bDomainMaster;
241         BOOL bDomainLogons;
242         BOOL bEncryptPasswords;
243         BOOL bUpdateEncrypt;
244         BOOL bStripDot;
245         BOOL bNullPasswords;
246         BOOL bObeyPamRestrictions;
247         BOOL bLoadPrinters;
248         BOOL bLargeReadwrite;
249         BOOL bReadRaw;
250         BOOL bWriteRaw;
251         BOOL bReadPrediction;
252         BOOL bReadbmpx;
253         BOOL bSyslogOnly;
254         BOOL bBrowseList;
255         BOOL bNISHomeMap;
256         BOOL bTimeServer;
257         BOOL bBindInterfacesOnly;
258         BOOL bPamPasswordChange;
259         BOOL bUnixPasswdSync;
260         BOOL bPasswdChatDebug;
261         BOOL bTimestampLogs;
262         BOOL bNTSmbSupport;
263         BOOL bNTPipeSupport;
264         BOOL bNTStatusSupport;
265         BOOL bStatCache;
266         BOOL bKernelOplocks;
267         BOOL bAllowTrustedDomains;
268         BOOL bLanmanAuth;
269         BOOL bNTLMAuth;
270         BOOL bUseSpnego;
271         BOOL bClientLanManAuth;
272         BOOL bClientNTLMv2Auth;
273         BOOL bClientUseSpnego;
274         BOOL bDebugHiresTimestamp;
275         BOOL bDebugPid;
276         BOOL bDebugUid;
277         BOOL bHostMSDfs;
278         BOOL bHideLocalUsers;
279         BOOL bUnicode;
280         BOOL bUseMmap;
281         BOOL bHostnameLookups;
282         BOOL bUnixExtensions;
283         BOOL bDisableNetbios;
284         BOOL bKernelChangeNotify;
285         int restrict_anonymous;
286         int name_cache_timeout;
287         BOOL client_signing;
288         param_opt_struct *param_opt;
289 }
290 global;
291
292 static global Globals;
293
294 /* 
295  * This structure describes a single service. 
296  */
297 typedef struct
298 {
299         BOOL valid;
300         BOOL autoloaded;
301         char *szService;
302         char *szPath;
303         char *szUsername;
304         char **szInvalidUsers;
305         char **szValidUsers;
306         char **szAdminUsers;
307         char *szCopy;
308         char *szInclude;
309         char *szPreExec;
310         char *szPostExec;
311         char *szRootPreExec;
312         char *szRootPostExec;
313         char *szPrintcommand;
314         char *szLpqcommand;
315         char *szLprmcommand;
316         char *szLppausecommand;
317         char *szLpresumecommand;
318         char *szQueuepausecommand;
319         char *szQueueresumecommand;
320         char *szPrintername;
321         char *szDontdescend;
322         char **szHostsallow;
323         char **szHostsdeny;
324         char *szMagicScript;
325         char *szMagicOutput;
326         char *szMangledMap;
327         char *szVetoFiles;
328         char *szHideFiles;
329         char *szVetoOplockFiles;
330         char *comment;
331         char *force_user;
332         char *force_group;
333         char **readlist;
334         char **writelist;
335         char **printer_admin;
336         char *volume;
337         char *fstype;
338         char *szVfsObjectFile;
339         char *szVfsOptions;
340         char *szVfsPath;
341         char *szMSDfsProxy;
342         int iMinPrintSpace;
343         int iMaxPrintJobs;
344         int iMaxReportedPrintJobs;
345         int iWriteCacheSize;
346         int iCreate_mask;
347         int iCreate_force_mode;
348         int iSecurity_mask;
349         int iSecurity_force_mode;
350         int iDir_mask;
351         int iDir_force_mode;
352         int iDir_Security_mask;
353         int iDir_Security_force_mode;
354         int iMaxConnections;
355         int iDefaultCase;
356         int iPrinting;
357         int iOplockContentionLimit;
358         int iCSCPolicy;
359         int iBlock_size;
360         BOOL bPreexecClose;
361         BOOL bRootpreexecClose;
362         BOOL bCaseSensitive;
363         BOOL bCasePreserve;
364         BOOL bShortCasePreserve;
365         BOOL bCaseMangle;
366         BOOL bHideDotFiles;
367         BOOL bHideSpecialFiles;
368         BOOL bHideUnReadable;
369         BOOL bHideUnWriteableFiles;
370         BOOL bBrowseable;
371         BOOL bAvailable;
372         BOOL bRead_only;
373         BOOL bNo_set_dir;
374         BOOL bGuest_only;
375         BOOL bGuest_ok;
376         BOOL bPrint_ok;
377         BOOL bMap_system;
378         BOOL bMap_hidden;
379         BOOL bMap_archive;
380         BOOL bLocking;
381         BOOL bStrictLocking;
382         BOOL bPosixLocking;
383         BOOL bShareModes;
384         BOOL bOpLocks;
385         BOOL bLevel2OpLocks;
386         BOOL bOnlyUser;
387         BOOL bMangledNames;
388         BOOL bWidelinks;
389         BOOL bSymlinks;
390         BOOL bSyncAlways;
391         BOOL bStrictAllocate;
392         BOOL bStrictSync;
393         char magic_char;
394         BOOL *copymap;
395         BOOL bDeleteReadonly;
396         BOOL bFakeOplocks;
397         BOOL bDeleteVetoFiles;
398         BOOL bDosFilemode;
399         BOOL bDosFiletimes;
400         BOOL bDosFiletimeResolution;
401         BOOL bFakeDirCreateTimes;
402         BOOL bBlockingLocks;
403         BOOL bInheritPerms;
404         BOOL bInheritACLS;
405         BOOL bMSDfsRoot;
406         BOOL bUseClientDriver;
407         BOOL bDefaultDevmode;
408         BOOL bNTAclSupport;
409         BOOL bUseSendfile;
410         BOOL bProfileAcls;
411         param_opt_struct *param_opt;
412
413         char dummy[3];          /* for alignment */
414 }
415 service;
416
417
418 /* This is a default service used to prime a services structure */
419 static service sDefault = {
420         True,                   /* valid */
421         False,                  /* not autoloaded */
422         NULL,                   /* szService */
423         NULL,                   /* szPath */
424         NULL,                   /* szUsername */
425         NULL,                   /* szInvalidUsers */
426         NULL,                   /* szValidUsers */
427         NULL,                   /* szAdminUsers */
428         NULL,                   /* szCopy */
429         NULL,                   /* szInclude */
430         NULL,                   /* szPreExec */
431         NULL,                   /* szPostExec */
432         NULL,                   /* szRootPreExec */
433         NULL,                   /* szRootPostExec */
434         NULL,                   /* szPrintcommand */
435         NULL,                   /* szLpqcommand */
436         NULL,                   /* szLprmcommand */
437         NULL,                   /* szLppausecommand */
438         NULL,                   /* szLpresumecommand */
439         NULL,                   /* szQueuepausecommand */
440         NULL,                   /* szQueueresumecommand */
441         NULL,                   /* szPrintername */
442         NULL,                   /* szDontdescend */
443         NULL,                   /* szHostsallow */
444         NULL,                   /* szHostsdeny */
445         NULL,                   /* szMagicScript */
446         NULL,                   /* szMagicOutput */
447         NULL,                   /* szMangledMap */
448         NULL,                   /* szVetoFiles */
449         NULL,                   /* szHideFiles */
450         NULL,                   /* szVetoOplockFiles */
451         NULL,                   /* comment */
452         NULL,                   /* force user */
453         NULL,                   /* force group */
454         NULL,                   /* readlist */
455         NULL,                   /* writelist */
456         NULL,                   /* printer admin */
457         NULL,                   /* volume */
458         NULL,                   /* fstype */
459         NULL,                   /* vfs object */
460         NULL,                   /* vfs options */
461         NULL,                   /* vfs path */
462         NULL,                   /* szMSDfsProxy */
463         0,                      /* iMinPrintSpace */
464         1000,                   /* iMaxPrintJobs */
465         0,                      /* iMaxReportedPrintJobs */
466         0,                      /* iWriteCacheSize */
467         0744,                   /* iCreate_mask */
468         0000,                   /* iCreate_force_mode */
469         0777,                   /* iSecurity_mask */
470         0,                      /* iSecurity_force_mode */
471         0755,                   /* iDir_mask */
472         0000,                   /* iDir_force_mode */
473         0777,                   /* iDir_Security_mask */
474         0,                      /* iDir_Security_force_mode */
475         0,                      /* iMaxConnections */
476         CASE_LOWER,             /* iDefaultCase */
477         DEFAULT_PRINTING,       /* iPrinting */
478         2,                      /* iOplockContentionLimit */
479         0,                      /* iCSCPolicy */
480         1024,           /* iBlock_size */
481         False,                  /* bPreexecClose */
482         False,                  /* bRootpreexecClose */
483         False,                  /* case sensitive */
484         True,                   /* case preserve */
485         True,                   /* short case preserve */
486         False,                  /* case mangle */
487         True,                   /* bHideDotFiles */
488         False,                  /* bHideSpecialFiles */
489         False,                  /* bHideUnReadable */
490         False,                  /* bHideUnWriteableFiles */
491         True,                   /* bBrowseable */
492         True,                   /* bAvailable */
493         True,                   /* bRead_only */
494         True,                   /* bNo_set_dir */
495         False,                  /* bGuest_only */
496         False,                  /* bGuest_ok */
497         False,                  /* bPrint_ok */
498         False,                  /* bMap_system */
499         False,                  /* bMap_hidden */
500         True,                   /* bMap_archive */
501         True,                   /* bLocking */
502         True,                   /* bStrictLocking */
503         True,                   /* bPosixLocking */
504         True,                   /* bShareModes */
505         True,                   /* bOpLocks */
506         True,                   /* bLevel2OpLocks */
507         False,                  /* bOnlyUser */
508         True,                   /* bMangledNames */
509         True,                   /* bWidelinks */
510         True,                   /* bSymlinks */
511         False,                  /* bSyncAlways */
512         False,                  /* bStrictAllocate */
513         False,                  /* bStrictSync */
514         '~',                    /* magic char */
515         NULL,                   /* copymap */
516         False,                  /* bDeleteReadonly */
517         False,                  /* bFakeOplocks */
518         False,                  /* bDeleteVetoFiles */
519         False,                  /* bDosFilemode */
520         False,                  /* bDosFiletimes */
521         False,                  /* bDosFiletimeResolution */
522         False,                  /* bFakeDirCreateTimes */
523         True,                   /* bBlockingLocks */
524         False,                  /* bInheritPerms */
525         False,                  /* bInheritACLS */
526         False,                  /* bMSDfsRoot */
527         False,                  /* bUseClientDriver */
528         False,                  /* bDefaultDevmode */
529         True,                   /* bNTAclSupport */
530         False,                  /* bUseSendfile */
531         False,                  /* bProfileAcls */
532         
533         NULL,                   /* Parametric options */
534
535         ""                      /* dummy */
536 };
537
538 /* local variables */
539 static service **ServicePtrs = NULL;
540 static int iNumServices = 0;
541 static int iServiceIndex = 0;
542 static BOOL bInGlobalSection = True;
543 static BOOL bGlobalOnly = False;
544 static int server_role;
545 static int default_server_announce;
546
547 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
548
549 /* prototypes for the special type handlers */
550 static BOOL handle_include(const char *pszParmValue, char **ptr);
551 static BOOL handle_copy(const char *pszParmValue, char **ptr);
552 static BOOL handle_source_env(const char *pszParmValue, char **ptr);
553 static BOOL handle_netbios_name(const char *pszParmValue, char **ptr);
554 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr);
555 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr);
556 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr);
557 static BOOL handle_debug_list( const char *pszParmValue, char **ptr );
558 static BOOL handle_workgroup( const char *pszParmValue, char **ptr );
559 static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr );
560 static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr );
561
562 static BOOL handle_ldap_machine_suffix ( const char *pszParmValue, char **ptr );
563 static BOOL handle_ldap_user_suffix ( const char *pszParmValue, char **ptr );
564 static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr );
565
566 static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr);
567
568 static void set_server_role(void);
569 static void set_default_server_announce_type(void);
570
571 static const struct enum_list enum_protocol[] = {
572         {PROTOCOL_NT1, "NT1"},
573         {PROTOCOL_LANMAN2, "LANMAN2"},
574         {PROTOCOL_LANMAN1, "LANMAN1"},
575         {PROTOCOL_CORE, "CORE"},
576         {PROTOCOL_COREPLUS, "COREPLUS"},
577         {PROTOCOL_COREPLUS, "CORE+"},
578         {-1, NULL}
579 };
580
581 static const struct enum_list enum_security[] = {
582         {SEC_SHARE, "SHARE"},
583         {SEC_USER, "USER"},
584         {SEC_SERVER, "SERVER"},
585         {SEC_DOMAIN, "DOMAIN"},
586 #ifdef HAVE_ADS
587         {SEC_ADS, "ADS"},
588 #endif
589         {-1, NULL}
590 };
591
592 static const struct enum_list enum_printing[] = {
593         {PRINT_SYSV, "sysv"},
594         {PRINT_AIX, "aix"},
595         {PRINT_HPUX, "hpux"},
596         {PRINT_BSD, "bsd"},
597         {PRINT_QNX, "qnx"},
598         {PRINT_PLP, "plp"},
599         {PRINT_LPRNG, "lprng"},
600         {PRINT_SOFTQ, "softq"},
601         {PRINT_CUPS, "cups"},
602         {PRINT_LPRNT, "nt"},
603         {PRINT_LPROS2, "os2"},
604 #ifdef DEVELOPER
605         {PRINT_TEST, "test"},
606         {PRINT_VLP, "vlp"},
607 #endif /* DEVELOPER */
608         {-1, NULL}
609 };
610
611 static const struct enum_list enum_ldap_ssl[] = {
612 #ifdef WITH_LDAP_SAMCONFIG
613         {LDAP_SSL_ON, "Yes"},
614         {LDAP_SSL_ON, "yes"},
615         {LDAP_SSL_ON, "on"},
616         {LDAP_SSL_ON, "On"},
617 #endif
618         {LDAP_SSL_OFF, "no"},
619         {LDAP_SSL_OFF, "No"},
620         {LDAP_SSL_OFF, "off"},
621         {LDAP_SSL_OFF, "Off"},
622         {LDAP_SSL_START_TLS, "start tls"},
623         {LDAP_SSL_START_TLS, "Start_tls"},
624         {-1, NULL}
625 };
626
627 static const struct enum_list enum_ldap_passwd_sync[] = {
628         {LDAP_PASSWD_SYNC_ON, "Yes"},
629         {LDAP_PASSWD_SYNC_ON, "yes"},
630         {LDAP_PASSWD_SYNC_ON, "on"},
631         {LDAP_PASSWD_SYNC_ON, "On"},
632         {LDAP_PASSWD_SYNC_OFF, "no"},
633         {LDAP_PASSWD_SYNC_OFF, "No"},
634         {LDAP_PASSWD_SYNC_OFF, "off"},
635         {LDAP_PASSWD_SYNC_OFF, "Off"},
636 #ifdef LDAP_EXOP_X_MODIFY_PASSWD        
637         {LDAP_PASSWD_SYNC_ONLY, "Only"},
638         {LDAP_PASSWD_SYNC_ONLY, "only"},
639 #endif /* LDAP_EXOP_X_MODIFY_PASSWD */  
640         {-1, NULL}
641 };
642
643 /* Types of machine we can announce as. */
644 #define ANNOUNCE_AS_NT_SERVER 1
645 #define ANNOUNCE_AS_WIN95 2
646 #define ANNOUNCE_AS_WFW 3
647 #define ANNOUNCE_AS_NT_WORKSTATION 4
648
649 static const struct enum_list enum_announce_as[] = {
650         {ANNOUNCE_AS_NT_SERVER, "NT"},
651         {ANNOUNCE_AS_NT_SERVER, "NT Server"},
652         {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"},
653         {ANNOUNCE_AS_WIN95, "win95"},
654         {ANNOUNCE_AS_WFW, "WfW"},
655         {-1, NULL}
656 };
657
658 static const struct enum_list enum_case[] = {
659         {CASE_LOWER, "lower"},
660         {CASE_UPPER, "upper"},
661         {-1, NULL}
662 };
663
664 static const struct enum_list enum_bool_auto[] = {
665         {False, "No"},
666         {False, "False"},
667         {False, "0"},
668         {True, "Yes"},
669         {True, "True"},
670         {True, "1"},
671         {Auto, "Auto"},
672         {-1, NULL}
673 };
674
675 /* Client-side offline caching policy types */
676 #define CSC_POLICY_MANUAL 0
677 #define CSC_POLICY_DOCUMENTS 1
678 #define CSC_POLICY_PROGRAMS 2
679 #define CSC_POLICY_DISABLE 3
680
681 static const struct enum_list enum_csc_policy[] = {
682         {CSC_POLICY_MANUAL, "manual"},
683         {CSC_POLICY_DOCUMENTS, "documents"},
684         {CSC_POLICY_PROGRAMS, "programs"},
685         {CSC_POLICY_DISABLE, "disable"},
686         {-1, NULL}
687 };
688
689 /* 
690    Do you want session setups at user level security with a invalid
691    password to be rejected or allowed in as guest? WinNT rejects them
692    but it can be a pain as it means "net view" needs to use a password
693
694    You have 3 choices in the setting of map_to_guest:
695
696    "Never" means session setups with an invalid password
697    are rejected. This is the default.
698
699    "Bad User" means session setups with an invalid password
700    are rejected, unless the username does not exist, in which case it
701    is treated as a guest login
702
703    "Bad Password" means session setups with an invalid password
704    are treated as a guest login
705
706    Note that map_to_guest only has an effect in user or server
707    level security.
708 */
709
710 static const struct enum_list enum_map_to_guest[] = {
711         {NEVER_MAP_TO_GUEST, "Never"},
712         {MAP_TO_GUEST_ON_BAD_USER, "Bad User"},
713         {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"},
714         {-1, NULL}
715 };
716
717 /* Note: We do not initialise the defaults union - it is not allowed in ANSI C
718  *
719  * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
720  * is implied in current control logic. This may change at some later time. A
721  * flag value of 0 means - show as development option only.
722  *
723  * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
724  * screen in SWAT. This is used to exclude parameters as well as to squash all
725  * parameters that have been duplicated by pseudonyms.
726  */
727 static struct parm_struct parm_table[] = {
728         {"Base Options", P_SEP, P_SEPARATOR},
729
730         {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
731         {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
732         {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
733         {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
734         {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
735         {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
736         {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
737         {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
738         {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
739         {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
740         {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
741         {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
742         {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
743         {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
744         {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
745
746         {"Security Options", P_SEP, P_SEPARATOR},
747         
748         {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
749         {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
750         {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
751         {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
752         {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
753         {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
754         {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIDMapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
755         {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
756         {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
757         {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED | FLAG_DEVELOPER},
758         {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
759         {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
760         {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
761         {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
762         {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
763         {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
764         {"sam backend", P_LIST, P_GLOBAL, &Globals.szSamBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
765         {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
766         {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
767         {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
768         {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
769         {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
770         {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
771         
772         {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
773         {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
774         {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
775         {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
776         {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEVELOPER},
777         {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
778         {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
779         {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
780         {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
781         {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
782         {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
783         {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
784         {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
785         
786         {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
787         {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
788         {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
789         
790         {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
791         {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
792         {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
793         {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
794         {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
795         {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_GLOBAL | FLAG_PRINT},
796         {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_SHARE},
797         {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_SHARE},
798         {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
799         
800         {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
801         {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
802         {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
803         {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
804         
805         {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
806         {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_GLOBAL},
807         {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
808         {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
809         {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
810         {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
811         {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL},
812         {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
813         {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
814         {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
815         {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_SHARE},
816         {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_SHARE},
817         {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_SHARE},
818         {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE},
819
820         {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
821         {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE},
822         
823         {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_SHARE},
824         {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
825         {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE},
826         {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
827         {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE},
828         {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL},
829
830         {"Logging Options", P_SEP, P_SEPARATOR},
831
832         {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
833         {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE},
834         {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
835         {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
836         {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
837         
838         {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
839         {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
840         {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_DEVELOPER},
841         {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_DEVELOPER},
842         {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_DEVELOPER},
843         {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_DEVELOPER},
844         
845         {"Protocol Options", P_SEP, P_SEPARATOR},
846         
847         {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
848         {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED | FLAG_DEVELOPER},
849         {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
850         {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
851         {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
852         {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
853         {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, FLAG_DEVELOPER},
854         {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
855         {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
856         {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
857         
858         {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_SHARE | FLAG_GLOBAL | FLAG_ADVANCED},
859         {"nt acl support", P_BOOL,  P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_ADVANCED | FLAG_WIZARD},
860         {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
861         {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
862         {"profile acls", P_BOOL,  P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE  | FLAG_ADVANCED | FLAG_WIZARD},
863         
864         {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
865         {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
866         {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
867         {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
868         
869         {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
870         {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
871         {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
872         {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
873         {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
874         {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
875         {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
876         {"client signing", P_BOOL, P_GLOBAL, &Globals.client_signing, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
877         {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER},
878
879         {"Tuning Options", P_SEP, P_SEPARATOR},
880         
881         {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
882         {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL, NULL, FLAG_DEVELOPER},
883         {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_DEVELOPER},
884         {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_DEVELOPER},
885         {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
886         {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_DEVELOPER},
887         
888         {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_DEVELOPER},
889         {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_DEVELOPER},
890         {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
891         {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
892         {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_DEVELOPER},
893         {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
894         {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_PRINT},
895         {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL, FLAG_DEVELOPER},
896         
897         {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, FLAG_DEVELOPER},
898         {"stat cache size", P_INTEGER, P_GLOBAL, &Globals.stat_cache_size, NULL, NULL, FLAG_DEVELOPER},
899         {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_SHARE},
900         {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_SHARE},
901         {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_SHARE},
902         {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_DEVELOPER},
903         {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_SHARE},
904         {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
905         {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_SHARE},
906
907         {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
908
909         {"Printing Options", P_SEP, P_SEPARATOR},
910         
911         {"total print jobs", P_INTEGER, P_GLOBAL, &Globals.iTotalPrintJobs, NULL, NULL, FLAG_PRINT},
912         {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, NULL, NULL, FLAG_PRINT},
913         {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
914         {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
915         {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT | FLAG_DEVELOPER},
916         {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE},
917         {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
918         {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
919         {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_PRINT | FLAG_GLOBAL},
920         {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
921         {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
922         {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
923         {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
924         {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
925         {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
926         {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
927         {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
928
929         {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
930         {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
931         {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
932         {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
933         {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
934         
935         {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
936         {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
937         {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_PRINT},
938         {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_PRINT},
939
940         {"Filename Handling", P_SEP, P_SEPARATOR},
941         {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
942         {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
943         {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
944         
945         {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
946         {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_SHARE},
947         {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
948         {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE},
949         {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
950         {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
951         {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
952         {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
953         {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
954         {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
955         {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
956         {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
957         {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
958         {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL },
959         {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL },
960         {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL },
961         {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
962         {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
963         {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
964         {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
965         {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
966         {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_DEVELOPER},
967
968         {"Domain Options", P_SEP, P_SEPARATOR},
969         
970         {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
971
972         {"Logon Options", P_SEP, P_SEPARATOR},
973
974         {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
975         {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
976         {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
977         {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
978         {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
979         {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
980         {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
981         {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
982         {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
983         {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
984
985         {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
986         {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
987         {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
988         {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
989         {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
990
991         {"Browse Options", P_SEP, P_SEPARATOR},
992         
993         {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
994         {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_DEVELOPER},
995         {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
996         {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
997         {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
998         {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
999         {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
1000         {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1001         {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
1002         {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
1003         {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_DEVELOPER | FLAG_ADVANCED},
1004
1005         {"WINS Options", P_SEP, P_SEPARATOR},
1006         {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1007         {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1008         
1009         {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
1010         {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
1011         {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1012         {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
1013
1014         {"Locking Options", P_SEP, P_SEPARATOR},
1015         
1016         {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1017         {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL},
1018         {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_SHARE},
1019         {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_GLOBAL},
1020         {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1021         {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL},
1022         {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL},
1023         
1024         {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1025         {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1026         {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_GLOBAL},
1027         {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1028         {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1029         {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1030         {"share modes", P_BOOL, P_LOCAL,  &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL},
1031
1032         {"Ldap Options", P_SEP, P_SEPARATOR},
1033         
1034 #ifdef WITH_LDAP_SAMCONFIG
1035         {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0},
1036         {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, 
1037 #endif
1038         {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1039         {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_machine_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1040         {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_user_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1041         {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1042         {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1043         {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED | FLAG_DEVELOPER},
1044         {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED | FLAG_DEVELOPER},
1045         {"ldap trust ids", P_BOOL, P_GLOBAL, &Globals.ldap_trust_ids, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1046         {"ldap del only sam attr", P_BOOL, P_GLOBAL, &Globals.ldap_del_only_sam, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1047
1048         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
1049         {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1050         {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1051         {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1052         
1053         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
1054         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1055         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1056         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
1057         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1058         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
1059 #ifdef WITH_UTMP
1060         {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1061         {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1062         {"utmp",          P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1063 #endif
1064         
1065         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1066         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
1067         {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1068         {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1069         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1070         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1071         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
1072         {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1073         {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1074         {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1075         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
1076         
1077         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
1078         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
1079         {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1080         {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1081         
1082         {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_SHARE},
1083         {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1084         {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1085         {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_SHARE},
1086         {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1087         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
1088         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
1089         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
1090         {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_SHARE},
1091         {"source environment", P_STRING, P_GLOBAL, &Globals.szSourceEnv, handle_source_env, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1092         {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1093         {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1094         {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_SHARE},
1095         {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_SHARE},
1096         {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_SHARE},
1097         {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1098         {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1099         {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1100         {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1101
1102         {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1103         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1104         {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1105
1106         {"VFS module options", P_SEP, P_SEPARATOR},
1107         
1108         {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjectFile, NULL, NULL, FLAG_SHARE},
1109         {"vfs options", P_STRING, P_LOCAL, &sDefault.szVfsOptions, NULL, NULL, FLAG_SHARE},
1110         {"vfs path", P_STRING, P_LOCAL, &sDefault.szVfsPath, NULL, NULL, FLAG_SHARE},
1111
1112         
1113         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
1114         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE},
1115         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1116
1117         {"Winbind options", P_SEP, P_SEPARATOR},
1118
1119         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1120         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1121         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1122         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1123         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1124         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1125         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1126         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1127         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1128
1129         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
1130 };
1131
1132 /***************************************************************************
1133  Initialise the sDefault parameter structure for the printer values.
1134 ***************************************************************************/
1135
1136 static void init_printer_values(void)
1137 {
1138         /* choose defaults depending on the type of printing */
1139         switch (sDefault.iPrinting) {
1140                 case PRINT_BSD:
1141                 case PRINT_AIX:
1142                 case PRINT_LPRNT:
1143                 case PRINT_LPROS2:
1144                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
1145                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
1146                         string_set(&sDefault.szPrintcommand,
1147                                    "lpr -r -P'%p' %s");
1148                         break;
1149
1150                 case PRINT_LPRNG:
1151                 case PRINT_PLP:
1152                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
1153                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
1154                         string_set(&sDefault.szPrintcommand,
1155                                    "lpr -r -P'%p' %s");
1156                         string_set(&sDefault.szQueuepausecommand,
1157                                    "lpc stop '%p'");
1158                         string_set(&sDefault.szQueueresumecommand,
1159                                    "lpc start '%p'");
1160                         string_set(&sDefault.szLppausecommand,
1161                                    "lpc hold '%p' %j");
1162                         string_set(&sDefault.szLpresumecommand,
1163                                    "lpc release '%p' %j");
1164                         break;
1165
1166                 case PRINT_CUPS:
1167 #ifdef HAVE_CUPS
1168                         string_set(&sDefault.szLpqcommand, "");
1169                         string_set(&sDefault.szLprmcommand, "");
1170                         string_set(&sDefault.szPrintcommand, "");
1171                         string_set(&sDefault.szLppausecommand, "");
1172                         string_set(&sDefault.szLpresumecommand, "");
1173                         string_set(&sDefault.szQueuepausecommand, "");
1174                         string_set(&sDefault.szQueueresumecommand, "");
1175
1176                         string_set(&Globals.szPrintcapname, "cups");
1177 #else
1178                         string_set(&sDefault.szLpqcommand,
1179                                    "/usr/bin/lpstat -o '%p'");
1180                         string_set(&sDefault.szLprmcommand,
1181                                    "/usr/bin/cancel '%p-%j'");
1182                         string_set(&sDefault.szPrintcommand,
1183                                    "/usr/bin/lp -d '%p' %s; rm %s");
1184                         string_set(&sDefault.szLppausecommand,
1185                                    "lp -i '%p-%j' -H hold");
1186                         string_set(&sDefault.szLpresumecommand,
1187                                    "lp -i '%p-%j' -H resume");
1188                         string_set(&sDefault.szQueuepausecommand,
1189                                    "/usr/bin/disable '%p'");
1190                         string_set(&sDefault.szQueueresumecommand,
1191                                    "/usr/bin/enable '%p'");
1192                         string_set(&Globals.szPrintcapname, "lpstat");
1193 #endif /* HAVE_CUPS */
1194                         break;
1195
1196                 case PRINT_SYSV:
1197                 case PRINT_HPUX:
1198                         string_set(&sDefault.szLpqcommand, "lpstat -o%p");
1199                         string_set(&sDefault.szLprmcommand, "cancel %p-%j");
1200                         string_set(&sDefault.szPrintcommand,
1201                                    "lp -c -d%p %s; rm %s");
1202                         string_set(&sDefault.szQueuepausecommand,
1203                                    "disable %p");
1204                         string_set(&sDefault.szQueueresumecommand,
1205                                    "enable %p");
1206 #ifndef HPUX
1207                         string_set(&sDefault.szLppausecommand,
1208                                    "lp -i %p-%j -H hold");
1209                         string_set(&sDefault.szLpresumecommand,
1210                                    "lp -i %p-%j -H resume");
1211 #endif /* HPUX */
1212                         break;
1213
1214                 case PRINT_QNX:
1215                         string_set(&sDefault.szLpqcommand, "lpq -P%p");
1216                         string_set(&sDefault.szLprmcommand, "lprm -P%p %j");
1217                         string_set(&sDefault.szPrintcommand, "lp -r -P%p %s");
1218                         break;
1219
1220                 case PRINT_SOFTQ:
1221                         string_set(&sDefault.szLpqcommand, "qstat -l -d%p");
1222                         string_set(&sDefault.szLprmcommand,
1223                                    "qstat -s -j%j -c");
1224                         string_set(&sDefault.szPrintcommand,
1225                                    "lp -d%p -s %s; rm %s");
1226                         string_set(&sDefault.szLppausecommand,
1227                                    "qstat -s -j%j -h");
1228                         string_set(&sDefault.szLpresumecommand,
1229                                    "qstat -s -j%j -r");
1230                         break;
1231 #ifdef DEVELOPER
1232         case PRINT_TEST:
1233         case PRINT_VLP:
1234                 string_set(&sDefault.szPrintcommand, "vlp print %p %s");
1235                 string_set(&sDefault.szLpqcommand, "vlp lpq %p");
1236                 string_set(&sDefault.szLprmcommand, "vlp lprm %p %j");
1237                 string_set(&sDefault.szLppausecommand, "vlp lppause %p %j");
1238                 string_set(&sDefault.szLpresumecommand, "vlp lpresum %p %j");
1239                 string_set(&sDefault.szQueuepausecommand, "vlp queuepause %p");
1240                 string_set(&sDefault.szQueueresumecommand, "vlp queueresume %p");
1241                 break;
1242 #endif /* DEVELOPER */
1243
1244         }
1245 }
1246
1247 /***************************************************************************
1248  Initialise the global parameter structure.
1249 ***************************************************************************/
1250
1251 static void init_globals(void)
1252 {
1253         static BOOL done_init = False;
1254         pstring s;
1255
1256         if (!done_init) {
1257                 int i;
1258                 memset((void *)&Globals, '\0', sizeof(Globals));
1259
1260                 for (i = 0; parm_table[i].label; i++)
1261                         if ((parm_table[i].type == P_STRING ||
1262                              parm_table[i].type == P_USTRING) &&
1263                             parm_table[i].ptr)
1264                                 string_set(parm_table[i].ptr, "");
1265
1266                 string_set(&sDefault.fstype, FSTYPE_STRING);
1267
1268                 init_printer_values();
1269
1270                 done_init = True;
1271         }
1272
1273
1274         DEBUG(3, ("Initialising global parameters\n"));
1275
1276         string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
1277         string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
1278
1279         /* use the new 'hash2' method by default, with a prefix of 1 */
1280         string_set(&Globals.szManglingMethod, "hash2");
1281         Globals.mangle_prefix = 1;
1282
1283         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
1284
1285         /* using UTF8 by default allows us to support all chars */
1286         string_set(&Globals.unix_charset, "UTF8");
1287
1288         /* using UTF8 by default allows us to support all chars */
1289         string_set(&Globals.display_charset, "ASCII");
1290
1291         /* Use codepage 850 as a default for the dos character set */
1292         string_set(&Globals.dos_charset, "CP850");
1293
1294         /*
1295          * Allow the default PASSWD_CHAT to be overridden in local.h.
1296          */
1297         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
1298         
1299         set_global_myname(myhostname());
1300         string_set(&Globals.szNetbiosName,global_myname());
1301
1302         set_global_myworkgroup(WORKGROUP);
1303         string_set(&Globals.szWorkgroup, lp_workgroup());
1304         
1305         string_set(&Globals.szPasswdProgram, "");
1306         string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
1307         string_set(&Globals.szPidDir, dyn_PIDDIR);
1308         string_set(&Globals.szLockDir, dyn_LOCKDIR);
1309         string_set(&Globals.szSocketAddress, "0.0.0.0");
1310         pstrcpy(s, "Samba ");
1311         pstrcat(s, VERSION);
1312         string_set(&Globals.szServerString, s);
1313         slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
1314                  DEFAULT_MINOR_VERSION);
1315         string_set(&Globals.szAnnounceVersion, s);
1316
1317         pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
1318
1319         string_set(&Globals.szLogonDrive, "");
1320         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
1321         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
1322         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
1323
1324         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
1325         string_set(&Globals.szPasswordServer, "*");
1326
1327         Globals.AlgorithmicRidBase = BASE_RID;
1328
1329         Globals.bLoadPrinters = True;
1330         Globals.mangled_stack = 50;
1331         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
1332         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
1333         Globals.max_xmit = 0x4104;
1334         Globals.max_mux = 50;   /* This is *needed* for profile support. */
1335         Globals.lpqcachetime = 10;
1336         Globals.bDisableSpoolss = False;
1337         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
1338         Globals.iTotalPrintJobs = 0;  /* no limit specified */
1339         Globals.pwordlevel = 0;
1340         Globals.unamelevel = 0;
1341         Globals.deadtime = 0;
1342         Globals.bLargeReadwrite = True;
1343         Globals.max_log_size = 5000;
1344         Globals.max_open_files = MAX_OPEN_FILES;
1345         Globals.maxprotocol = PROTOCOL_NT1;
1346         Globals.minprotocol = PROTOCOL_CORE;
1347         Globals.security = SEC_USER;
1348         Globals.paranoid_server_security = True;
1349         Globals.bEncryptPasswords = True;
1350         Globals.bUpdateEncrypt = False;
1351         Globals.bReadRaw = True;
1352         Globals.bWriteRaw = True;
1353         Globals.bReadPrediction = False;
1354         Globals.bReadbmpx = False;
1355         Globals.bNullPasswords = False;
1356         Globals.bObeyPamRestrictions = False;
1357         Globals.bStripDot = False;
1358         Globals.syslog = 1;
1359         Globals.bSyslogOnly = False;
1360         Globals.bTimestampLogs = True;
1361         string_set(&Globals.szLogLevel, "0");
1362         Globals.bDebugHiresTimestamp = False;
1363         Globals.bDebugPid = False;
1364         Globals.bDebugUid = False;
1365         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1366         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1367         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1368         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1369         Globals.change_notify_timeout = 60;     /* 1 minute default. */
1370         Globals.bKernelChangeNotify = True;     /* On if we have it. */
1371         Globals.ReadSize = 16 * 1024;
1372         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1373         Globals.lm_interval = 60;
1374         Globals.stat_cache_size = 50;   /* Number of stat translations we'll keep */
1375         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1376 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1377         Globals.bNISHomeMap = False;
1378 #ifdef WITH_NISPLUS_HOME
1379         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
1380 #else
1381         string_set(&Globals.szNISHomeMapName, "auto.home");
1382 #endif
1383 #endif
1384         Globals.bTimeServer = False;
1385         Globals.bBindInterfacesOnly = False;
1386         Globals.bUnixPasswdSync = False;
1387         Globals.bPamPasswordChange = False;
1388         Globals.bPasswdChatDebug = False;
1389         Globals.bUnicode = True;        /* Do unicode on the wire by default */
1390         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
1391         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1392         Globals.bStatCache = True;      /* use stat cache by default */
1393         Globals.restrict_anonymous = 0;
1394         Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
1395         Globals.bLanmanAuth = True;     /* Do use the LanMan hash if it is available */
1396         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is available (otherwise NTLMv2) */
1397         
1398         Globals.map_to_guest = 0;       /* By Default, "Never" */
1399         Globals.min_passwd_length = MINPASSWDLENGTH;    /* By Default, 5. */
1400         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
1401         Globals.enhanced_browsing = True; 
1402         Globals.iLockSpinCount = 3; /* Try 2 times. */
1403         Globals.iLockSpinTime = 10; /* usec. */
1404 #ifdef MMAP_BLACKLIST
1405         Globals.bUseMmap = False;
1406 #else
1407         Globals.bUseMmap = True;
1408 #endif
1409         Globals.bUnixExtensions = False;
1410
1411         /* hostname lookups can be very expensive and are broken on
1412            a large number of sites (tridge) */
1413         Globals.bHostnameLookups = False;
1414
1415 #ifdef WITH_LDAP_SAMCONFIG
1416         string_set(&Globals.szLdapServer, "localhost");
1417         Globals.ldap_port = 636;
1418         Globals.szPassdbBackend = str_list_make("ldapsam guest", NULL);
1419 #else
1420         Globals.szPassdbBackend = str_list_make("smbpasswd guest", NULL);
1421 #endif /* WITH_LDAP_SAMCONFIG */
1422
1423         string_set(&Globals.szLdapSuffix, "");
1424         string_set(&Globals.szLdapMachineSuffix, "");
1425         string_set(&Globals.szLdapUserSuffix, "");
1426
1427         string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
1428         string_set(&Globals.szLdapAdminDn, "");
1429         Globals.ldap_ssl = LDAP_SSL_ON;
1430         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1431         Globals.ldap_del_only_sam = True;
1432
1433 /* these parameters are set to defaults that are more appropriate
1434    for the increasing samba install base:
1435
1436    as a member of the workgroup, that will possibly become a
1437    _local_ master browser (lm = True).  this is opposed to a forced
1438    local master browser startup (pm = True).
1439
1440    doesn't provide WINS server service by default (wsupp = False),
1441    and doesn't provide domain master browser services by default, either.
1442
1443 */
1444
1445         Globals.bMsAddPrinterWizard = True;
1446         Globals.bPreferredMaster = Auto;        /* depending on bDomainMaster */
1447         Globals.os_level = 20;
1448         Globals.bLocalMaster = True;
1449         Globals.bDomainMaster = Auto;   /* depending on bDomainLogons */
1450         Globals.bDomainLogons = False;
1451         Globals.bBrowseList = True;
1452         Globals.bWINSsupport = False;
1453         Globals.bWINSproxy = False;
1454
1455         Globals.bDNSproxy = True;
1456
1457         /* this just means to use them if they exist */
1458         Globals.bKernelOplocks = True;
1459
1460         Globals.bAllowTrustedDomains = True;
1461
1462         string_set(&Globals.szTemplateShell, "/bin/false");
1463         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1464         string_set(&Globals.szWinbindSeparator, "\\");
1465         string_set(&Globals.szAclCompat, "");
1466
1467         Globals.winbind_cache_time = 15;
1468         Globals.bWinbindEnumUsers = True;
1469         Globals.bWinbindEnumGroups = True;
1470         Globals.bWinbindUseDefaultDomain = False;
1471
1472         string_set(&Globals.szIDMapBackend, "tdb");
1473
1474         Globals.name_cache_timeout = 660; /* In seconds */
1475
1476         Globals.bUseSpnego = True;
1477         Globals.bClientUseSpnego = True;
1478
1479         string_set(&Globals.smb_ports, SMB_PORTS);
1480 }
1481
1482 static TALLOC_CTX *lp_talloc;
1483
1484 /******************************************************************* a
1485  Free up temporary memory - called from the main loop.
1486 ********************************************************************/
1487
1488 void lp_talloc_free(void)
1489 {
1490         if (!lp_talloc)
1491                 return;
1492         talloc_destroy(lp_talloc);
1493         lp_talloc = NULL;
1494 }
1495
1496 /*******************************************************************
1497  Convenience routine to grab string parameters into temporary memory
1498  and run standard_sub_basic on them. The buffers can be written to by
1499  callers without affecting the source string.
1500 ********************************************************************/
1501
1502 static char *lp_string(const char *s)
1503 {
1504         size_t len = s ? strlen(s) : 0;
1505         char *ret;
1506
1507         /* The follow debug is useful for tracking down memory problems
1508            especially if you have an inner loop that is calling a lp_*()
1509            function that returns a string.  Perhaps this debug should be
1510            present all the time? */
1511
1512 #if 0
1513         DEBUG(10, ("lp_string(%s)\n", s));
1514 #endif
1515
1516         if (!lp_talloc)
1517                 lp_talloc = talloc_init("lp_talloc");
1518
1519         ret = (char *)talloc(lp_talloc, len + 100);     /* leave room for substitution */
1520
1521         if (!ret)
1522                 return NULL;
1523
1524         /* Note: StrnCpy touches len+1 bytes, but we allocate 100
1525          * extra bytes so we're OK. */
1526
1527         if (!s)
1528                 *ret = 0;
1529         else
1530                 StrnCpy(ret, s, len);
1531
1532         if (trim_string(ret, "\"", "\"")) {
1533                 if (strchr(ret,'"') != NULL)
1534                         StrnCpy(ret, s, len);
1535         }
1536
1537         standard_sub_basic(current_user_info.smb_name,ret,len+100);
1538         return (ret);
1539 }
1540
1541 /*
1542    In this section all the functions that are used to access the 
1543    parameters from the rest of the program are defined 
1544 */
1545
1546 #define FN_GLOBAL_STRING(fn_name,ptr) \
1547  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1548 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1549  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1550 #define FN_GLOBAL_LIST(fn_name,ptr) \
1551  const char **fn_name(void) {return(*(const char ***)(ptr));}
1552 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1553  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1554 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1555  char fn_name(void) {return(*(char *)(ptr));}
1556 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1557  int fn_name(void) {return(*(int *)(ptr));}
1558
1559 #define FN_LOCAL_STRING(fn_name,val) \
1560  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1561 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1562  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1563 #define FN_LOCAL_LIST(fn_name,val) \
1564  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1565 #define FN_LOCAL_BOOL(fn_name,val) \
1566  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1567 #define FN_LOCAL_CHAR(fn_name,val) \
1568  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1569 #define FN_LOCAL_INTEGER(fn_name,val) \
1570  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1571
1572 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1573 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1574 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1575 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1576 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1577 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1578 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1579 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1580 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1581 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1582 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1583 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1584 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1585 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1586 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1587 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1588 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1589 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1590 #ifdef WITH_UTMP
1591 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1592 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1593 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1594 #endif
1595 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1596 FN_GLOBAL_STRING(lp_source_environment, &Globals.szSourceEnv)
1597 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1598 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1599 FN_GLOBAL_STRING(lp_dfree_command, &Globals.szDfree)
1600 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1601 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1602 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1603 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1604 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1605 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1606 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1607 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1608 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1609 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1610 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1611 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1612 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1613 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1614 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1615 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1616 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1617 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1618 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1619 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1620 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1621 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
1622 FN_GLOBAL_LIST(lp_sam_backend, &Globals.szSamBackend)
1623 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1624 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1625 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1626 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1627
1628 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1629 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1630 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1631 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1632 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1633 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1634
1635 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1636
1637 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1638 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1639
1640 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1641 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1642 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1643 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1644 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1645 FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
1646 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1647 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1648 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1649 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1650
1651 #ifdef WITH_LDAP_SAMCONFIG
1652 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
1653 FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
1654 #endif
1655 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1656 FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix)
1657 FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
1658 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
1659 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1660 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1661 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1662 FN_GLOBAL_BOOL(lp_ldap_trust_ids, &Globals.ldap_trust_ids)
1663 FN_GLOBAL_BOOL(lp_ldap_del_only_sam, &Globals.ldap_del_only_sam)
1664 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1665 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1666 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1667
1668 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1669 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1670 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1671 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1672 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1673 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1674 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1675 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1676 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1677 FN_GLOBAL_BOOL(lp_readprediction, &Globals.bReadPrediction)
1678 FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx)
1679 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1680 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1681 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1682 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1683 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1684 FN_GLOBAL_BOOL(lp_strip_dot, &Globals.bStripDot)
1685 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1686 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1687 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
1688 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
1689 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
1690 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
1691 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
1692 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
1693 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
1694 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1695 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1696 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1697 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1698 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
1699 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1700 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
1701 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1702 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
1703 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1704 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1705 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1706 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1707 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1708 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1709 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1710 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
1711 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1712 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1713 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1714 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1715 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
1716 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1717 FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
1718 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1719 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1720 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1721 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1722 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
1723 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
1724 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
1725 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1726 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1727 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1728 FN_GLOBAL_INTEGER(lp_readsize, &Globals.ReadSize)
1729 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
1730 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1731 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1732 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1733 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1734 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1735 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
1736 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1737 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
1738 FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
1739 FN_GLOBAL_INTEGER(lp_totalprintjobs, &Globals.iTotalPrintJobs)
1740 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
1741 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1742 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1743 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1744 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1745 FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
1746 FN_GLOBAL_INTEGER(lp_stat_cache_size, &Globals.stat_cache_size)
1747 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
1748 FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
1749 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
1750 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1751 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
1752 FN_LOCAL_STRING(lp_preexec, szPreExec)
1753 FN_LOCAL_STRING(lp_postexec, szPostExec)
1754 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
1755 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
1756 FN_LOCAL_STRING(lp_servicename, szService)
1757 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1758 FN_LOCAL_STRING(lp_pathname, szPath)
1759 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
1760 FN_LOCAL_STRING(lp_username, szUsername)
1761 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1762 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1763 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1764 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1765 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1766 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1767 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1768 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1769 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1770 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1771 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1772 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1773 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1774 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
1775 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
1776 FN_LOCAL_STRING(lp_comment, comment)
1777 FN_LOCAL_STRING(lp_force_user, force_user)
1778 FN_LOCAL_STRING(lp_force_group, force_group)
1779 FN_LOCAL_LIST(lp_readlist, readlist)
1780 FN_LOCAL_LIST(lp_writelist, writelist)
1781 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
1782 FN_LOCAL_STRING(lp_fstype, fstype)
1783 FN_LOCAL_LIST(lp_vfsobj, szVfsObjectFile)
1784 FN_LOCAL_STRING(lp_vfs_options, szVfsOptions)
1785 FN_LOCAL_STRING(lp_vfs_path, szVfsPath)
1786 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1787 static FN_LOCAL_STRING(lp_volume, volume)
1788 FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
1789 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
1790 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
1791 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
1792 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
1793 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
1794 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
1795 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
1796 FN_LOCAL_BOOL(lp_casesensitive, bCaseSensitive)
1797 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
1798 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
1799 FN_LOCAL_BOOL(lp_casemangle, bCaseMangle)
1800 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
1801 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
1802 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
1803 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
1804 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
1805 FN_LOCAL_BOOL(lp_readonly, bRead_only)
1806 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
1807 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
1808 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
1809 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
1810 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
1811 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
1812 FN_LOCAL_BOOL(lp_locking, bLocking)
1813 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
1814 FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
1815 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
1816 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
1817 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
1818 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
1819 FN_LOCAL_BOOL(lp_manglednames, bMangledNames)
1820 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
1821 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
1822 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
1823 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
1824 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
1825 FN_LOCAL_BOOL(lp_map_system, bMap_system)
1826 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
1827 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
1828 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
1829 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
1830 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
1831 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
1832 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
1833 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
1834 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
1835 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
1836 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
1837 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
1838 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
1839 FN_LOCAL_BOOL(lp_use_sendfile, bUseSendfile)
1840 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
1841 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
1842 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
1843 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
1844 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
1845 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
1846 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
1847 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
1848 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
1849 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
1850 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
1851 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
1852 FN_LOCAL_INTEGER(lp_printing, iPrinting)
1853 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
1854 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
1855 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
1856 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
1857 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
1858 FN_LOCAL_CHAR(lp_magicchar, magic_char)
1859 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
1860 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
1861 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
1862 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
1863 FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing)
1864
1865 /* local prototypes */
1866
1867 static int map_parameter(const char *pszParmName);
1868 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
1869 static int getservicebyname(const char *pszServiceName,
1870                             service * pserviceDest);
1871 static void copy_service(service * pserviceDest,
1872                          service * pserviceSource, BOOL *pcopymapDest);
1873 static BOOL service_ok(int iService);
1874 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
1875 static BOOL do_section(const char *pszSectionName);
1876 static void init_copymap(service * pservice);
1877
1878 /* This is a helper function for parametrical options support. */
1879 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1880 /* Actual parametrical functions are quite simple */
1881 static const char *get_parametrics(int lookup_service, const char *type, const char *option)
1882 {
1883         char* vfskey;
1884         param_opt_struct *data;
1885         
1886         if (lookup_service >= iNumServices) return NULL;
1887         
1888         data = (lookup_service < 0) ? 
1889                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
1890     
1891         asprintf(&vfskey, "%s:%s", type, option);
1892         while (data) {
1893                 if (strcmp(data->key, vfskey) == 0) {
1894                         string_free(&vfskey);
1895                         return data->value;
1896                 }
1897                 data = data->next;
1898         }
1899
1900         if (lookup_service >= 0) {
1901                 /* Try to fetch the same option but from globals */
1902                 /* but only if we are not already working with Globals */
1903                 data = Globals.param_opt;
1904                 while (data) {
1905                         if (strcmp(data->key, vfskey) == 0) {
1906                                 string_free(&vfskey);
1907                                 return data->value;
1908                         }
1909                         data = data->next;
1910                 }
1911         }
1912
1913         string_free(&vfskey);
1914         
1915         return NULL;
1916 }
1917
1918
1919 /*******************************************************************
1920 convenience routine to return int parameters.
1921 ********************************************************************/
1922 static int lp_int(const char *s)
1923 {
1924
1925         if (!s) {
1926                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1927                 return (-1);
1928         }
1929
1930         return atoi(s); 
1931 }
1932
1933 /*******************************************************************
1934 convenience routine to return unsigned long parameters.
1935 ********************************************************************/
1936 static int lp_ulong(const char *s)
1937 {
1938
1939         if (!s) {
1940                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1941                 return (-1);
1942         }
1943
1944         return strtoul(s, NULL, 10);
1945 }
1946
1947 /*******************************************************************
1948 convenience routine to return boolean parameters.
1949 ********************************************************************/
1950 static BOOL lp_bool(const char *s)
1951 {
1952         BOOL ret = False;
1953
1954         if (!s) {
1955                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1956                 return False;
1957         }
1958         
1959         if (!set_boolean(&ret,s)) {
1960                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1961                 return False;
1962         }
1963
1964         return ret;
1965 }
1966
1967 /*******************************************************************
1968 convenience routine to return enum parameters.
1969 ********************************************************************/
1970 static int lp_enum(const char *s,const struct enum_list *_enum)
1971 {
1972         int i;
1973
1974         if (!s || !_enum) {
1975                 DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
1976                 return False;
1977         }
1978         
1979         for (i=0; _enum[i].name; i++) {
1980                 if (strcasecmp(_enum[i].name,s)==0)
1981                         return _enum[i].value;
1982         }
1983
1984         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1985         return (-1);
1986 }
1987
1988 /* Return parametric option from a given service. Type is a part of option before ':' */
1989 /* Parametric option has following syntax: 'Type: option = value' */
1990 /* Returned value is allocated in 'lp_talloc' context */
1991
1992 char *lp_parm_string(int lookup_service, const char *type, const char *option)
1993 {
1994         const char *value = get_parametrics(lookup_service, type, option);
1995         
1996         if (value)
1997                 return lp_string(value);
1998
1999         return NULL;
2000 }
2001
2002 /* Return parametric option from a given service. Type is a part of option before ':' */
2003 /* Parametric option has following syntax: 'Type: option = value' */
2004 /* Returned value is allocated in 'lp_talloc' context */
2005
2006 char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
2007                            const char *separator)
2008 {
2009         const char *value = get_parametrics(lookup_service, type, option);
2010         
2011         if (value)
2012                 return str_list_make(value, separator);
2013
2014         return NULL;
2015 }
2016
2017 /* Return parametric option from a given service. Type is a part of option before ':' */
2018 /* Parametric option has following syntax: 'Type: option = value' */
2019
2020 int lp_parm_int(int lookup_service, const char *type, const char *option)
2021 {
2022         const char *value = get_parametrics(lookup_service, type, option);
2023         
2024         if (value)
2025                 return lp_int(value);
2026
2027         return (-1);
2028 }
2029
2030 /* Return parametric option from a given service. Type is a part of option before ':' */
2031 /* Parametric option has following syntax: 'Type: option = value' */
2032
2033 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
2034 {
2035         const char *value = get_parametrics(lookup_service, type, option);
2036         
2037         if (value)
2038                 return lp_ulong(value);
2039
2040         return (0);
2041 }
2042
2043 /* Return parametric option from a given service. Type is a part of option before ':' */
2044 /* Parametric option has following syntax: 'Type: option = value' */
2045
2046 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option)
2047 {
2048         const char *value = get_parametrics(lookup_service, type, option);
2049         
2050         if (value)
2051                 return lp_bool(value);
2052
2053         return False;
2054 }
2055
2056 /* Return parametric option from a given service. Type is a part of option before ':' */
2057 /* Parametric option has following syntax: 'Type: option = value' */
2058
2059 int lp_parm_enum(int lookup_service, const char *type, const char *option,
2060                  const struct enum_list *_enum)
2061 {
2062         const char *value = get_parametrics(lookup_service, type, option);
2063         
2064         if (value)
2065                 return lp_enum(value, _enum);
2066
2067         return (-1);
2068 }
2069
2070
2071 /***************************************************************************
2072  Initialise a service to the defaults.
2073 ***************************************************************************/
2074
2075 static void init_service(service * pservice)
2076 {
2077         memset((char *)pservice, '\0', sizeof(service));
2078         copy_service(pservice, &sDefault, NULL);
2079 }
2080
2081 /***************************************************************************
2082  Free the dynamically allocated parts of a service struct.
2083 ***************************************************************************/
2084
2085 static void free_service(service *pservice)
2086 {
2087         int i;
2088         param_opt_struct *data, *pdata;
2089         if (!pservice)
2090                 return;
2091
2092         if (pservice->szService)
2093                 DEBUG(5, ("free_service: Freeing service %s\n",
2094                        pservice->szService));
2095
2096         string_free(&pservice->szService);
2097         SAFE_FREE(pservice->copymap);
2098
2099         for (i = 0; parm_table[i].label; i++) {
2100                 if ((parm_table[i].type == P_STRING ||
2101                      parm_table[i].type == P_USTRING) &&
2102                     parm_table[i].class == P_LOCAL)
2103                         string_free((char **)
2104                                     (((char *)pservice) +
2105                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2106                 else if (parm_table[i].type == P_LIST &&
2107                          parm_table[i].class == P_LOCAL)
2108                              str_list_free((char ***)
2109                                             (((char *)pservice) +
2110                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
2111         }
2112                                 
2113         DEBUG(5,("Freeing parametrics:\n"));
2114         data = pservice->param_opt;
2115         while (data) {
2116                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2117                 string_free(&data->key);
2118                 string_free(&data->value);
2119                 pdata = data->next;
2120                 SAFE_FREE(data);
2121                 data = pdata;
2122         }
2123
2124         ZERO_STRUCTP(pservice);
2125 }
2126
2127 /***************************************************************************
2128  Add a new service to the services array initialising it with the given 
2129  service. 
2130 ***************************************************************************/
2131
2132 static int add_a_service(const service *pservice, const char *name)
2133 {
2134         int i;
2135         service tservice;
2136         int num_to_alloc = iNumServices + 1;
2137         param_opt_struct *data, *pdata;
2138
2139         tservice = *pservice;
2140
2141         /* it might already exist */
2142         if (name) {
2143                 i = getservicebyname(name, NULL);
2144                 if (i >= 0) {
2145                         /* Clean all parametric options for service */
2146                         /* They will be added during parsing again */
2147                         data = ServicePtrs[i]->param_opt;
2148                         while (data) {
2149                                 string_free(&data->key);
2150                                 string_free(&data->value);
2151                                 pdata = data->next;
2152                                 SAFE_FREE(data);
2153                                 data = pdata;
2154                         }
2155                         ServicePtrs[i]->param_opt = NULL;
2156                         return (i);
2157                 }
2158         }
2159
2160         /* find an invalid one */
2161         for (i = 0; i < iNumServices; i++)
2162                 if (!ServicePtrs[i]->valid)
2163                         break;
2164
2165         /* if not, then create one */
2166         if (i == iNumServices) {
2167                 service **tsp;
2168                 
2169                 tsp = (service **) Realloc(ServicePtrs,
2170                                            sizeof(service *) *
2171                                            num_to_alloc);
2172                                            
2173                 if (!tsp) {
2174                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2175                         return (-1);
2176                 }
2177                 else {
2178                         ServicePtrs = tsp;
2179                         ServicePtrs[iNumServices] =
2180                                 (service *) malloc(sizeof(service));
2181                 }
2182                 if (!ServicePtrs[iNumServices]) {
2183                         DEBUG(0,("add_a_service: out of memory!\n"));
2184                         return (-1);
2185                 }
2186
2187                 iNumServices++;
2188         } else
2189                 free_service(ServicePtrs[i]);
2190
2191         ServicePtrs[i]->valid = True;
2192
2193         init_service(ServicePtrs[i]);
2194         copy_service(ServicePtrs[i], &tservice, NULL);
2195         if (name)
2196                 string_set(&ServicePtrs[i]->szService, name);
2197         return (i);
2198 }
2199
2200 /***************************************************************************
2201  Add a new home service, with the specified home directory, defaults coming 
2202  from service ifrom.
2203 ***************************************************************************/
2204
2205 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
2206                  const char *user, const char *pszHomedir)
2207 {
2208         int i;
2209         pstring newHomedir;
2210
2211         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2212
2213         if (i < 0)
2214                 return (False);
2215
2216         if (!(*(ServicePtrs[iDefaultService]->szPath))
2217             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
2218                 pstrcpy(newHomedir, pszHomedir);
2219         } else {
2220                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
2221                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
2222         }
2223
2224         string_set(&ServicePtrs[i]->szPath, newHomedir);
2225
2226         if (!(*(ServicePtrs[i]->comment))) {
2227                 pstring comment;
2228                 slprintf(comment, sizeof(comment) - 1,
2229                          "Home directory of %s", user);
2230                 string_set(&ServicePtrs[i]->comment, comment);
2231         }
2232         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
2233         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2234
2235         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2236                user, newHomedir));
2237         
2238         return (True);
2239 }
2240
2241 /***************************************************************************
2242  Add a new service, based on an old one.
2243 ***************************************************************************/
2244
2245 int lp_add_service(const char *pszService, int iDefaultService)
2246 {
2247         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2248 }
2249
2250 /***************************************************************************
2251  Add the IPC service.
2252 ***************************************************************************/
2253
2254 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
2255 {
2256         pstring comment;
2257         int i = add_a_service(&sDefault, ipc_name);
2258
2259         if (i < 0)
2260                 return (False);
2261
2262         slprintf(comment, sizeof(comment) - 1,
2263                  "IPC Service (%s)", Globals.szServerString);
2264
2265         string_set(&ServicePtrs[i]->szPath, tmpdir());
2266         string_set(&ServicePtrs[i]->szUsername, "");
2267         string_set(&ServicePtrs[i]->comment, comment);
2268         string_set(&ServicePtrs[i]->fstype, "IPC");
2269         ServicePtrs[i]->iMaxConnections = 0;
2270         ServicePtrs[i]->bAvailable = True;
2271         ServicePtrs[i]->bRead_only = True;
2272         ServicePtrs[i]->bGuest_only = False;
2273         ServicePtrs[i]->bGuest_ok = guest_ok;
2274         ServicePtrs[i]->bPrint_ok = False;
2275         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2276
2277         DEBUG(3, ("adding IPC service\n"));
2278
2279         return (True);
2280 }
2281
2282 /***************************************************************************
2283  Add a new printer service, with defaults coming from service iFrom.
2284 ***************************************************************************/
2285
2286 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
2287 {
2288         const char *comment = "From Printcap";
2289         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2290
2291         if (i < 0)
2292                 return (False);
2293
2294         /* note that we do NOT default the availability flag to True - */
2295         /* we take it from the default service passed. This allows all */
2296         /* dynamic printers to be disabled by disabling the [printers] */
2297         /* entry (if/when the 'available' keyword is implemented!).    */
2298
2299         /* the printer name is set to the service name. */
2300         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2301         string_set(&ServicePtrs[i]->comment, comment);
2302         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2303         /* Printers cannot be read_only. */
2304         ServicePtrs[i]->bRead_only = False;
2305         /* No share modes on printer services. */
2306         ServicePtrs[i]->bShareModes = False;
2307         /* No oplocks on printer services. */
2308         ServicePtrs[i]->bOpLocks = False;
2309         /* Printer services must be printable. */
2310         ServicePtrs[i]->bPrint_ok = True;
2311
2312         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2313
2314         update_server_announce_as_printserver();
2315
2316         return (True);
2317 }
2318
2319 /***************************************************************************
2320  Map a parameter's string representation to something we can use. 
2321  Returns False if the parameter string is not recognised, else TRUE.
2322 ***************************************************************************/
2323
2324 static int map_parameter(const char *pszParmName)
2325 {
2326         int iIndex;
2327
2328         if (*pszParmName == '-')
2329                 return (-1);
2330
2331         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2332                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2333                         return (iIndex);
2334
2335         /* Warn only if it isn't parametric option */
2336         if (strchr(pszParmName, ':') == NULL)
2337                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2338         /* We do return 'fail' for parametric options as well because they are
2339            stored in different storage
2340          */
2341         return (-1);
2342 }
2343
2344 /***************************************************************************
2345  Set a boolean variable from the text value stored in the passed string.
2346  Returns True in success, False if the passed string does not correctly 
2347  represent a boolean.
2348 ***************************************************************************/
2349
2350 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
2351 {
2352         BOOL bRetval;
2353
2354         bRetval = True;
2355         if (strwicmp(pszParmValue, "yes") == 0 ||
2356             strwicmp(pszParmValue, "true") == 0 ||
2357             strwicmp(pszParmValue, "1") == 0)
2358                 *pb = True;
2359         else if (strwicmp(pszParmValue, "no") == 0 ||
2360                     strwicmp(pszParmValue, "False") == 0 ||
2361                     strwicmp(pszParmValue, "0") == 0)
2362                 *pb = False;
2363         else {
2364                 DEBUG(0,
2365                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
2366                        pszParmValue));
2367                 bRetval = False;
2368         }
2369         return (bRetval);
2370 }
2371
2372 /***************************************************************************
2373 Find a service by name. Otherwise works like get_service.
2374 ***************************************************************************/
2375
2376 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
2377 {
2378         int iService;
2379
2380         for (iService = iNumServices - 1; iService >= 0; iService--)
2381                 if (VALID(iService) &&
2382                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
2383                         if (pserviceDest != NULL)
2384                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2385                         break;
2386                 }
2387
2388         return (iService);
2389 }
2390
2391 /***************************************************************************
2392  Copy a service structure to another.
2393  If pcopymapDest is NULL then copy all fields
2394 ***************************************************************************/
2395
2396 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
2397 {
2398         int i;
2399         BOOL bcopyall = (pcopymapDest == NULL);
2400         param_opt_struct *data, *pdata, *paramo;
2401         BOOL not_added;
2402
2403         for (i = 0; parm_table[i].label; i++)
2404                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
2405                     (bcopyall || pcopymapDest[i])) {
2406                         void *def_ptr = parm_table[i].ptr;
2407                         void *src_ptr =
2408                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
2409                                                                     &sDefault);
2410                         void *dest_ptr =
2411                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
2412                                                                   &sDefault);
2413
2414                         switch (parm_table[i].type) {
2415                                 case P_BOOL:
2416                                 case P_BOOLREV:
2417                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
2418                                         break;
2419
2420                                 case P_INTEGER:
2421                                 case P_ENUM:
2422                                 case P_OCTAL:
2423                                         *(int *)dest_ptr = *(int *)src_ptr;
2424                                         break;
2425
2426                                 case P_CHAR:
2427                                         *(char *)dest_ptr = *(char *)src_ptr;
2428                                         break;
2429
2430                                 case P_STRING:
2431                                         string_set(dest_ptr,
2432                                                    *(char **)src_ptr);
2433                                         break;
2434
2435                                 case P_USTRING:
2436                                         string_set(dest_ptr,
2437                                                    *(char **)src_ptr);
2438                                         strupper(*(char **)dest_ptr);
2439                                         break;
2440                                 case P_LIST:
2441                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
2442                                         break;
2443                                 default:
2444                                         break;
2445                         }
2446                 }
2447
2448         if (bcopyall) {
2449                 init_copymap(pserviceDest);
2450                 if (pserviceSource->copymap)
2451                         memcpy((void *)pserviceDest->copymap,
2452                                (void *)pserviceSource->copymap,
2453                                sizeof(BOOL) * NUMPARAMETERS);
2454         }
2455         
2456         data = pserviceSource->param_opt;
2457         while (data) {
2458                 not_added = True;
2459                 pdata = pserviceDest->param_opt;
2460                 /* Traverse destination */
2461                 while (pdata) {
2462                         /* If we already have same option, override it */
2463                         if (strcmp(pdata->key, data->key) == 0) {
2464                                 string_free(&pdata->value);
2465                                 pdata->value = strdup(data->value);
2466                                 not_added = False;
2467                                 break;
2468                         }
2469                         pdata = pdata->next;
2470                 }
2471                 if (not_added) {
2472                     paramo = smb_xmalloc(sizeof(param_opt_struct));
2473                     paramo->key = strdup(data->key);
2474                     paramo->value = strdup(data->value);
2475                     DLIST_ADD(pserviceDest->param_opt, paramo);
2476                 }
2477                 data = data->next;
2478         }
2479 }
2480
2481 /***************************************************************************
2482 Check a service for consistency. Return False if the service is in any way
2483 incomplete or faulty, else True.
2484 ***************************************************************************/
2485
2486 static BOOL service_ok(int iService)
2487 {
2488         BOOL bRetval;
2489
2490         bRetval = True;
2491         if (ServicePtrs[iService]->szService[0] == '\0') {
2492                 DEBUG(0, ("The following message indicates an internal error:\n"));
2493                 DEBUG(0, ("No service name in service entry.\n"));
2494                 bRetval = False;
2495         }
2496
2497         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2498         /* I can't see why you'd want a non-printable printer service...        */
2499         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2500                 if (!ServicePtrs[iService]->bPrint_ok) {
2501                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2502                                ServicePtrs[iService]->szService));
2503                         ServicePtrs[iService]->bPrint_ok = True;
2504                 }
2505                 /* [printers] service must also be non-browsable. */
2506                 if (ServicePtrs[iService]->bBrowseable)
2507                         ServicePtrs[iService]->bBrowseable = False;
2508         }
2509
2510         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2511             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0) {
2512                 DEBUG(0, ("No path in service %s - using %s\n",
2513                        ServicePtrs[iService]->szService, tmpdir()));
2514                 string_set(&ServicePtrs[iService]->szPath, tmpdir());
2515         }
2516
2517         /* If a service is flagged unavailable, log the fact at level 0. */
2518         if (!ServicePtrs[iService]->bAvailable)
2519                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2520                           ServicePtrs[iService]->szService));
2521
2522         return (bRetval);
2523 }
2524
2525 static struct file_lists {
2526         struct file_lists *next;
2527         char *name;
2528         char *subfname;
2529         time_t modtime;
2530 } *file_lists = NULL;
2531
2532 /*******************************************************************
2533  Keep a linked list of all config files so we know when one has changed 
2534  it's date and needs to be reloaded.
2535 ********************************************************************/
2536
2537 static void add_to_file_list(const char *fname, const char *subfname)
2538 {
2539         struct file_lists *f = file_lists;
2540
2541         while (f) {
2542                 if (f->name && !strcmp(f->name, fname))
2543                         break;
2544                 f = f->next;
2545         }
2546
2547         if (!f) {
2548                 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
2549                 if (!f)
2550                         return;
2551                 f->next = file_lists;
2552                 f->name = strdup(fname);
2553                 if (!f->name) {
2554                         SAFE_FREE(f);
2555                         return;
2556                 }
2557                 f->subfname = strdup(subfname);
2558                 if (!f->subfname) {
2559                         SAFE_FREE(f);
2560                         return;
2561                 }
2562                 file_lists = f;
2563                 f->modtime = file_modtime(subfname);
2564         } else {
2565                 time_t t = file_modtime(subfname);
2566                 if (t)
2567                         f->modtime = t;
2568         }
2569 }
2570
2571 /*******************************************************************
2572  Check if a config file has changed date.
2573 ********************************************************************/
2574
2575 BOOL lp_file_list_changed(void)
2576 {
2577         struct file_lists *f = file_lists;
2578         DEBUG(6, ("lp_file_list_changed()\n"));
2579
2580         while (f) {
2581                 pstring n2;
2582                 time_t mod_time;
2583
2584                 pstrcpy(n2, f->name);
2585                 standard_sub_basic(current_user_info.smb_name, n2,sizeof(n2));
2586
2587                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2588                              f->name, n2, ctime(&f->modtime)));
2589
2590                 mod_time = file_modtime(n2);
2591
2592                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2593                         DEBUGADD(6,
2594                                  ("file %s modified: %s\n", n2,
2595                                   ctime(&mod_time)));
2596                         f->modtime = mod_time;
2597                         SAFE_FREE(f->subfname);
2598                         f->subfname = strdup(n2);
2599                         return (True);
2600                 }
2601                 f = f->next;
2602         }
2603         return (False);
2604 }
2605
2606 /***************************************************************************
2607  Run standard_sub_basic on netbios name... needed because global_myname
2608  is not accessed through any lp_ macro.
2609  Note: We must *NOT* use string_set() here as ptr points to global_myname.
2610 ***************************************************************************/
2611
2612 static BOOL handle_netbios_name(const char *pszParmValue, char **ptr)
2613 {
2614         BOOL ret;
2615         pstring netbios_name;
2616
2617         pstrcpy(netbios_name, pszParmValue);
2618
2619         standard_sub_basic(current_user_info.smb_name, netbios_name,sizeof(netbios_name));
2620
2621
2622         ret = set_global_myname(netbios_name);
2623         string_set(&Globals.szNetbiosName,global_myname());
2624         
2625         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
2626                global_myname()));
2627
2628         return ret;
2629 }
2630
2631 static BOOL handle_workgroup(const char *pszParmValue, char **ptr)
2632 {
2633         BOOL ret;
2634         
2635         ret = set_global_myworkgroup(pszParmValue);
2636         string_set(&Globals.szWorkgroup,lp_workgroup());
2637         
2638         return ret;
2639 }
2640
2641 static BOOL handle_netbios_scope(const char *pszParmValue, char **ptr)
2642 {
2643         BOOL ret;
2644         
2645         ret = set_global_scope(pszParmValue);
2646         string_set(&Globals.szNetbiosScope,global_scope());
2647
2648         return ret;
2649 }
2650
2651 static BOOL handle_netbios_aliases(const char *pszParmValue, char **ptr)
2652 {
2653         Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
2654         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
2655 }
2656
2657 /***************************************************************************
2658  Do the work of sourcing in environment variable/value pairs.
2659 ***************************************************************************/
2660
2661 static BOOL source_env(char **lines)
2662 {
2663         char *varval;
2664         size_t len;
2665         int i;
2666         char *p;
2667
2668         for (i = 0; lines[i]; i++) {
2669                 char *line = lines[i];
2670
2671                 if ((len = strlen(line)) == 0)
2672                         continue;
2673
2674                 if (line[len - 1] == '\n')
2675                         line[--len] = '\0';
2676
2677                 if ((varval = malloc(len + 1)) == NULL) {
2678                         DEBUG(0, ("source_env: Not enough memory!\n"));
2679                         return (False);
2680                 }
2681
2682                 DEBUG(4, ("source_env: Adding to environment: %s\n", line));
2683                 strncpy(varval, line, len);
2684                 varval[len] = '\0';
2685
2686                 p = strchr_m(line, (int)'=');
2687                 if (p == NULL) {
2688                         DEBUG(4, ("source_env: missing '=': %s\n", line));
2689                         continue;
2690                 }
2691
2692                 if (putenv(varval)) {
2693                         DEBUG(0, ("source_env: Failed to put environment variable %s\n",
2694                                varval));
2695                         continue;
2696                 }
2697
2698                 *p = '\0';
2699                 p++;
2700                 DEBUG(4, ("source_env: getting var %s = %s\n", line, getenv(line)));
2701         }
2702
2703         DEBUG(4, ("source_env: returning successfully\n"));
2704         return (True);
2705 }
2706
2707 /***************************************************************************
2708  Handle the source environment operation.
2709 ***************************************************************************/
2710
2711 static BOOL handle_source_env(const char *pszParmValue, char **ptr)
2712 {
2713         pstring fname;
2714         char *p = fname;
2715         BOOL result;
2716         char **lines;
2717
2718         pstrcpy(fname, pszParmValue);
2719
2720         standard_sub_basic(current_user_info.smb_name, fname,sizeof(fname));
2721
2722         string_set(ptr, pszParmValue);
2723
2724         DEBUG(4, ("handle_source_env: checking env type\n"));
2725
2726         /*
2727          * Filename starting with '|' means popen and read from stdin.
2728          */
2729
2730         if (*p == '|')
2731                 lines = file_lines_pload(p + 1, NULL);
2732         else
2733                 lines = file_lines_load(fname, NULL);
2734
2735         if (!lines) {
2736                 DEBUG(0, ("handle_source_env: Failed to open file %s, Error was %s\n",
2737                        fname, strerror(errno)));
2738                 return (False);
2739         }
2740
2741         result = source_env(lines);
2742         file_lines_free(lines);
2743
2744         return (result);
2745 }
2746
2747 /***************************************************************************
2748  Handle the include operation.
2749 ***************************************************************************/
2750
2751 static BOOL handle_include(const char *pszParmValue, char **ptr)
2752 {
2753         pstring fname;
2754         pstrcpy(fname, pszParmValue);
2755
2756         standard_sub_basic(current_user_info.smb_name, fname,sizeof(fname));
2757
2758         add_to_file_list(pszParmValue, fname);
2759
2760         string_set(ptr, fname);
2761
2762         if (file_exist(fname, NULL))
2763                 return (pm_process(fname, do_section, do_parameter));
2764
2765         DEBUG(2, ("Can't find include file %s\n", fname));
2766
2767         return (False);
2768 }
2769
2770 /***************************************************************************
2771  Handle the interpretation of the copy parameter.
2772 ***************************************************************************/
2773
2774 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2775 {
2776         BOOL bRetval;
2777         int iTemp;
2778         service serviceTemp;
2779
2780         string_set(ptr, pszParmValue);
2781
2782         init_service(&serviceTemp);
2783
2784         bRetval = False;
2785
2786         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2787
2788         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2789                 if (iTemp == iServiceIndex) {
2790                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2791                 } else {
2792                         copy_service(ServicePtrs[iServiceIndex],
2793                                      &serviceTemp,
2794                                      ServicePtrs[iServiceIndex]->copymap);
2795                         bRetval = True;
2796                 }
2797         } else {
2798                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2799                 bRetval = False;
2800         }
2801
2802         free_service(&serviceTemp);
2803         return (bRetval);
2804 }
2805
2806 /***************************************************************************
2807  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2808  parameters is:
2809
2810  [global]
2811
2812         winbind uid = 1000-1999
2813         winbind gid = 700-899
2814
2815  We only do simple parsing checks here.  The strings are parsed into useful
2816  structures in the winbind daemon code.
2817
2818 ***************************************************************************/
2819
2820 /* Some lp_ routines to return winbind [ug]id information */
2821
2822 static uid_t winbind_uid_low, winbind_uid_high;
2823 static gid_t winbind_gid_low, winbind_gid_high;
2824 static uint32 non_unix_account_low, non_unix_account_high;
2825
2826 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2827 {
2828         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2829                 return False;
2830
2831         if (low)
2832                 *low = winbind_uid_low;
2833
2834         if (high)
2835                 *high = winbind_uid_high;
2836
2837         return True;
2838 }
2839
2840 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2841 {
2842         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2843                 return False;
2844
2845         if (low)
2846                 *low = winbind_gid_low;
2847
2848         if (high)
2849                 *high = winbind_gid_high;
2850
2851         return True;
2852 }
2853
2854 BOOL lp_non_unix_account_range(uint32 *low, uint32 *high)
2855 {
2856         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2857                 return False;
2858
2859         if (low)
2860                 *low = non_unix_account_low;
2861
2862         if (high)
2863                 *high = non_unix_account_high;
2864
2865         return True;
2866 }
2867
2868 /* Do some simple checks on "winbind [ug]id" parameter values */
2869
2870 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2871 {
2872         uint32 low, high;
2873
2874         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2875                 return False;
2876
2877         /* Parse OK */
2878
2879         string_set(ptr, pszParmValue);
2880
2881         winbind_uid_low = low;
2882         winbind_uid_high = high;
2883
2884         return True;
2885 }
2886
2887 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2888 {
2889         uint32 low, high;
2890
2891         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2892                 return False;
2893
2894         /* Parse OK */
2895
2896         string_set(ptr, pszParmValue);
2897
2898         winbind_gid_low = low;
2899         winbind_gid_high = high;
2900
2901         return True;
2902 }
2903
2904 /***************************************************************************
2905  Do some simple checks on "non unix account range" parameter values.
2906 ***************************************************************************/
2907
2908 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2909 {
2910         uint32 low, high;
2911
2912         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2913                 return False;
2914
2915         /* Parse OK */
2916
2917         string_set(ptr, pszParmValue);
2918
2919         non_unix_account_low = low;
2920         non_unix_account_high = high;
2921
2922         return True;
2923 }
2924
2925 /***************************************************************************
2926  Handle the DEBUG level list.
2927 ***************************************************************************/
2928
2929 static BOOL handle_debug_list( const char *pszParmValueIn, char **ptr )
2930 {
2931         pstring pszParmValue;
2932
2933         pstrcpy(pszParmValue, pszParmValueIn);
2934         string_set(ptr, pszParmValueIn);
2935         return debug_parse_levels( pszParmValue );
2936 }
2937
2938 /***************************************************************************
2939  Handle the ldap machine suffix option.
2940 ***************************************************************************/
2941
2942 static BOOL handle_ldap_machine_suffix( const char *pszParmValue, char **ptr)
2943 {
2944        pstring suffix;
2945        
2946        pstrcpy(suffix, pszParmValue);
2947
2948        if (! *Globals.szLdapSuffix ) {
2949                string_set( ptr, suffix );
2950                return True;
2951        }
2952
2953        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2954                if ( *pszParmValue )
2955                        pstrcat(suffix, ",");
2956                pstrcat(suffix, Globals.szLdapSuffix);
2957        }
2958        string_set( ptr, suffix );
2959        return True;
2960 }
2961
2962 /***************************************************************************
2963  Handle the ldap user suffix option.
2964 ***************************************************************************/
2965
2966 static BOOL handle_ldap_user_suffix( const char *pszParmValue, char **ptr)
2967 {
2968        pstring suffix;
2969        
2970        pstrcpy(suffix, pszParmValue);
2971
2972        if (! *Globals.szLdapSuffix ) {
2973                string_set( ptr, suffix );
2974                return True;
2975        }
2976        
2977        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2978                if ( *pszParmValue )
2979                        pstrcat(suffix, ",");
2980                pstrcat(suffix, Globals.szLdapSuffix);
2981        }
2982        string_set( ptr, suffix );
2983        return True;
2984 }
2985
2986 /***************************************************************************
2987  Handle setting ldap suffix and determines whether ldap machine suffix needs
2988  to be set as well.
2989 ***************************************************************************/
2990
2991 static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr)
2992 {
2993        pstring suffix;
2994        pstring user_suffix;
2995        pstring machine_suffix;
2996                
2997        pstrcpy(suffix, pszParmValue);
2998
2999        if (! *Globals.szLdapMachineSuffix )
3000                string_set(&Globals.szLdapMachineSuffix, suffix);
3001        if (! *Globals.szLdapUserSuffix ) 
3002                string_set(&Globals.szLdapUserSuffix, suffix);
3003        
3004        if (! strstr(Globals.szLdapMachineSuffix, suffix)) {
3005                pstrcpy(machine_suffix, Globals.szLdapMachineSuffix);
3006                if ( *Globals.szLdapMachineSuffix )
3007                        pstrcat(machine_suffix, ",");
3008                pstrcat(machine_suffix, suffix);
3009                string_set(&Globals.szLdapMachineSuffix, machine_suffix);       
3010        }
3011
3012        if (! strstr(Globals.szLdapUserSuffix, suffix)) {
3013                pstrcpy(user_suffix, Globals.szLdapUserSuffix);
3014                if ( *Globals.szLdapUserSuffix )
3015                        pstrcat(user_suffix, ",");
3016                pstrcat(user_suffix, suffix);   
3017                string_set(&Globals.szLdapUserSuffix, user_suffix);
3018        } 
3019
3020        string_set(ptr, suffix); 
3021        return True;
3022 }
3023
3024 static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr)
3025 {
3026         if (strequal(pszParmValue, "auto"))
3027                 string_set(ptr, "");
3028         else if (strequal(pszParmValue, "winnt"))
3029                 string_set(ptr, "winnt");
3030         else if (strequal(pszParmValue, "win2k"))
3031                 string_set(ptr, "win2k");
3032         else
3033                 return False;
3034
3035         return True;
3036 }
3037 /***************************************************************************
3038  Initialise a copymap.
3039 ***************************************************************************/
3040
3041 static void init_copymap(service * pservice)
3042 {
3043         int i;
3044         SAFE_FREE(pservice->copymap);
3045         pservice->copymap = (BOOL *)malloc(sizeof(BOOL) * NUMPARAMETERS);
3046         if (!pservice->copymap)
3047                 DEBUG(0,
3048                       ("Couldn't allocate copymap!! (size %d)\n",
3049                        (int)NUMPARAMETERS));
3050         else
3051                 for (i = 0; i < NUMPARAMETERS; i++)
3052                         pservice->copymap[i] = True;
3053 }
3054
3055 /***************************************************************************
3056  Return the local pointer to a parameter given the service number and the 
3057  pointer into the default structure.
3058 ***************************************************************************/
3059
3060 void *lp_local_ptr(int snum, void *ptr)
3061 {
3062         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3063 }
3064
3065 /***************************************************************************
3066  Process a parameter for a particular service number. If snum < 0
3067  then assume we are in the globals.
3068 ***************************************************************************/
3069
3070 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3071 {
3072         int parmnum, i, slen;
3073         void *parm_ptr = NULL;  /* where we are going to store the result */
3074         void *def_ptr = NULL;
3075         pstring vfskey;
3076         char *sep;
3077         param_opt_struct *paramo, *data;
3078         BOOL not_added;
3079
3080         parmnum = map_parameter(pszParmName);
3081
3082         if (parmnum < 0) {
3083                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3084                         *sep = 0;
3085                         ZERO_STRUCT(vfskey);
3086                         pstr_sprintf(vfskey, "%s:", pszParmName);
3087                         slen = strlen(vfskey);
3088                         pstrcat(vfskey, sep+1);
3089                         trim_string(vfskey+slen, " ", " ");
3090                         not_added = True;
3091                         data = (snum < 0) ? Globals.param_opt : 
3092                                 ServicePtrs[snum]->param_opt;
3093                         /* Traverse destination */
3094                         while (data) {
3095                                 /* If we already have same option, override it */
3096                                 if (strcmp(data->key, vfskey) == 0) {
3097                                         string_free(&data->value);
3098                                         data->value = strdup(pszParmValue);
3099                                         not_added = False;
3100                                         break;
3101                                 }
3102                                 data = data->next;
3103                         }
3104                         if (not_added) {
3105                                 paramo = smb_xmalloc(sizeof(param_opt_struct));
3106                                 paramo->key = strdup(vfskey);
3107                                 paramo->value = strdup(pszParmValue);
3108                                 if (snum < 0) {
3109                                         DLIST_ADD(Globals.param_opt, paramo);
3110                                 } else {
3111                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3112                                 }
3113                         }
3114
3115                         *sep = ':';
3116                         return (True);
3117                 }
3118                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3119                 return (True);
3120         }
3121
3122         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3123                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3124                           pszParmName));
3125         }
3126
3127         def_ptr = parm_table[parmnum].ptr;
3128
3129         /* we might point at a service, the default service or a global */
3130         if (snum < 0) {
3131                 parm_ptr = def_ptr;
3132         } else {
3133                 if (parm_table[parmnum].class == P_GLOBAL) {
3134                         DEBUG(0,
3135                               ("Global parameter %s found in service section!\n",
3136                                pszParmName));
3137                         return (True);
3138                 }
3139                 parm_ptr =
3140                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3141                                                             &sDefault);
3142         }
3143
3144         if (snum >= 0) {
3145                 if (!ServicePtrs[snum]->copymap)
3146                         init_copymap(ServicePtrs[snum]);
3147
3148                 /* this handles the aliases - set the copymap for other entries with
3149                    the same data pointer */
3150                 for (i = 0; parm_table[i].label; i++)
3151                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3152                                 ServicePtrs[snum]->copymap[i] = False;
3153         }
3154
3155         /* if it is a special case then go ahead */
3156         if (parm_table[parmnum].special) {
3157                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
3158                 return (True);
3159         }
3160
3161         /* now switch on the type of variable it is */
3162         switch (parm_table[parmnum].type)
3163         {
3164                 case P_BOOL:
3165                         set_boolean(parm_ptr, pszParmValue);
3166                         break;
3167
3168                 case P_BOOLREV:
3169                         set_boolean(parm_ptr, pszParmValue);
3170                         *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
3171                         break;
3172
3173                 case P_INTEGER:
3174                         *(int *)parm_ptr = atoi(pszParmValue);
3175                         break;
3176
3177                 case P_CHAR:
3178                         *(char *)parm_ptr = *pszParmValue;
3179                         break;
3180
3181                 case P_OCTAL:
3182                         sscanf(pszParmValue, "%o", (int *)parm_ptr);
3183                         break;
3184
3185                 case P_LIST:
3186                         str_list_free(parm_ptr);
3187                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
3188                         break;
3189
3190                 case P_STRING:
3191                         string_set(parm_ptr, pszParmValue);
3192                         break;
3193
3194                 case P_USTRING:
3195                         string_set(parm_ptr, pszParmValue);
3196                         strupper(*(char **)parm_ptr);
3197                         break;
3198
3199                 case P_GSTRING:
3200                         pstrcpy((char *)parm_ptr, pszParmValue);
3201                         break;
3202
3203                 case P_UGSTRING:
3204                         pstrcpy((char *)parm_ptr, pszParmValue);
3205                         strupper((char *)parm_ptr);
3206                         break;
3207
3208                 case P_ENUM:
3209                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
3210                                 if (strequal
3211                                     (pszParmValue,
3212                                      parm_table[parmnum].enum_list[i].name)) {
3213                                         *(int *)parm_ptr =
3214                                                 parm_table[parmnum].
3215                                                 enum_list[i].value;
3216                                         break;
3217                                 }
3218                         }
3219                         break;
3220                 case P_SEP:
3221                         break;
3222         }
3223
3224         return (True);
3225 }
3226
3227 /***************************************************************************
3228  Process a parameter.
3229 ***************************************************************************/
3230
3231 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
3232 {
3233         if (!bInGlobalSection && bGlobalOnly)
3234                 return (True);
3235
3236         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3237
3238         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3239                                 pszParmName, pszParmValue));
3240 }
3241
3242 /***************************************************************************
3243  Print a parameter of the specified type.
3244 ***************************************************************************/
3245
3246 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3247 {
3248         int i;
3249         switch (p->type)
3250         {
3251                 case P_ENUM:
3252                         for (i = 0; p->enum_list[i].name; i++) {
3253                                 if (*(int *)ptr == p->enum_list[i].value) {
3254                                         fprintf(f, "%s",
3255                                                 p->enum_list[i].name);
3256                                         break;
3257                                 }
3258                         }
3259                         break;
3260
3261                 case P_BOOL:
3262                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
3263                         break;
3264
3265                 case P_BOOLREV:
3266                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
3267                         break;
3268
3269                 case P_INTEGER:
3270                         fprintf(f, "%d", *(int *)ptr);
3271                         break;
3272
3273                 case P_CHAR:
3274                         fprintf(f, "%c", *(char *)ptr);
3275                         break;
3276
3277                 case P_OCTAL:
3278                         fprintf(f, "%s", octal_string(*(int *)ptr));
3279                         break;
3280
3281                 case P_LIST:
3282                         if ((char ***)ptr && *(char ***)ptr) {
3283                                 char **list = *(char ***)ptr;
3284                                 
3285                                 for (; *list; list++)
3286                                         fprintf(f, "%s%s", *list,
3287                                                 ((*(list+1))?", ":""));
3288                         }
3289                         break;
3290
3291                 case P_GSTRING:
3292                 case P_UGSTRING:
3293                         if ((char *)ptr) {
3294                                 fprintf(f, "%s", (char *)ptr);
3295                         }
3296                         break;
3297
3298                 case P_STRING:
3299                 case P_USTRING:
3300                         if (*(char **)ptr) {
3301                                 fprintf(f, "%s", *(char **)ptr);
3302                         }
3303                         break;
3304                 case P_SEP:
3305                         break;
3306         }
3307 }
3308
3309 /***************************************************************************
3310  Check if two parameters are equal.
3311 ***************************************************************************/
3312
3313 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
3314 {
3315         switch (type) {
3316                 case P_BOOL:
3317                 case P_BOOLREV:
3318                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
3319
3320                 case P_INTEGER:
3321                 case P_ENUM:
3322                 case P_OCTAL:
3323                         return (*((int *)ptr1) == *((int *)ptr2));
3324
3325                 case P_CHAR:
3326                         return (*((char *)ptr1) == *((char *)ptr2));
3327                 
3328                 case P_LIST:
3329                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
3330
3331                 case P_GSTRING:
3332                 case P_UGSTRING:
3333                 {
3334                         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
3335                         if (p1 && !*p1)
3336                                 p1 = NULL;
3337                         if (p2 && !*p2)
3338                                 p2 = NULL;
3339                         return (p1 == p2 || strequal(p1, p2));
3340                 }
3341                 case P_STRING:
3342                 case P_USTRING:
3343                 {
3344                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3345                         if (p1 && !*p1)
3346                                 p1 = NULL;
3347                         if (p2 && !*p2)
3348                                 p2 = NULL;
3349                         return (p1 == p2 || strequal(p1, p2));
3350                 }
3351                 case P_SEP:
3352                         break;
3353         }
3354         return (False);
3355 }
3356
3357 /***************************************************************************
3358  Initialize any local varients in the sDefault table.
3359 ***************************************************************************/
3360
3361 void init_locals(void)
3362 {
3363         /* None as yet. */
3364 }
3365
3366 /***************************************************************************
3367  Process a new section (service). At this stage all sections are services.
3368  Later we'll have special sections that permit server parameters to be set.
3369  Returns True on success, False on failure. 
3370 ***************************************************************************/
3371
3372 static BOOL do_section(const char *pszSectionName)
3373 {
3374         BOOL bRetval;
3375         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3376                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3377         bRetval = False;
3378
3379         /* if we were in a global section then do the local inits */
3380         if (bInGlobalSection && !isglobal)
3381                 init_locals();
3382
3383         /* if we've just struck a global section, note the fact. */
3384         bInGlobalSection = isglobal;
3385
3386         /* check for multiple global sections */
3387         if (bInGlobalSection) {
3388                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3389                 return (True);
3390         }
3391
3392         if (!bInGlobalSection && bGlobalOnly)
3393                 return (True);
3394
3395         /* if we have a current service, tidy it up before moving on */
3396         bRetval = True;
3397
3398         if (iServiceIndex >= 0)
3399                 bRetval = service_ok(iServiceIndex);
3400
3401         /* if all is still well, move to the next record in the services array */
3402         if (bRetval) {
3403                 /* We put this here to avoid an odd message order if messages are */
3404                 /* issued by the post-processing of a previous section. */
3405                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3406
3407                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
3408                     < 0) {
3409                         DEBUG(0, ("Failed to add a new service\n"));
3410                         return (False);
3411                 }
3412         }
3413
3414         return (bRetval);
3415 }
3416
3417
3418 /***************************************************************************
3419  Determine if a partcular base parameter is currentl set to the default value.
3420 ***************************************************************************/
3421
3422 static BOOL is_default(int i)
3423 {
3424         if (!defaults_saved)
3425                 return False;
3426         switch (parm_table[i].type) {
3427                 case P_LIST:
3428                         return str_list_compare (parm_table[i].def.lvalue, 
3429                                                 *(char ***)parm_table[i].ptr);
3430                 case P_STRING:
3431                 case P_USTRING:
3432                         return strequal(parm_table[i].def.svalue,
3433                                         *(char **)parm_table[i].ptr);
3434                 case P_GSTRING:
3435                 case P_UGSTRING:
3436                         return strequal(parm_table[i].def.svalue,
3437                                         (char *)parm_table[i].ptr);
3438                 case P_BOOL:
3439                 case P_BOOLREV:
3440                         return parm_table[i].def.bvalue ==
3441                                 *(BOOL *)parm_table[i].ptr;
3442                 case P_CHAR:
3443                         return parm_table[i].def.cvalue ==
3444                                 *(char *)parm_table[i].ptr;
3445                 case P_INTEGER:
3446                 case P_OCTAL:
3447                 case P_ENUM:
3448                         return parm_table[i].def.ivalue ==
3449                                 *(int *)parm_table[i].ptr;
3450                 case P_SEP:
3451                         break;
3452         }
3453         return False;
3454 }
3455
3456 /***************************************************************************
3457 Display the contents of the global structure.
3458 ***************************************************************************/
3459
3460 static void dump_globals(FILE *f)
3461 {
3462         int i;
3463         param_opt_struct *data;
3464         
3465         fprintf(f, "# Global parameters\n[global]\n");
3466
3467         for (i = 0; parm_table[i].label; i++)
3468                 if (parm_table[i].class == P_GLOBAL &&
3469                     parm_table[i].ptr &&
3470                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3471                         if (defaults_saved && is_default(i))
3472                                 continue;
3473                         fprintf(f, "\t%s = ", parm_table[i].label);
3474                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
3475                         fprintf(f, "\n");
3476         }
3477         if (Globals.param_opt != NULL) {
3478                 data = Globals.param_opt;
3479                 while(data) {
3480                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3481                         data = data->next;
3482                 }
3483         }
3484
3485 }
3486
3487 /***************************************************************************
3488  Return True if a local parameter is currently set to the global default.
3489 ***************************************************************************/
3490
3491 BOOL lp_is_default(int snum, struct parm_struct *parm)
3492 {
3493         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
3494
3495         return equal_parameter(parm->type,
3496                                ((char *)ServicePtrs[snum]) + pdiff,
3497                                ((char *)&sDefault) + pdiff);
3498 }
3499
3500 /***************************************************************************
3501  Display the contents of a single services record.
3502 ***************************************************************************/
3503
3504 static void dump_a_service(service * pService, FILE * f)
3505 {
3506         int i;
3507         param_opt_struct *data;
3508         
3509         if (pService != &sDefault)
3510                 fprintf(f, "\n[%s]\n", pService->szService);
3511
3512         for (i = 0; parm_table[i].label; i++)
3513                 if (parm_table[i].class == P_LOCAL &&
3514                     parm_table[i].ptr &&
3515                     (*parm_table[i].label != '-') &&
3516                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3517                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
3518
3519                         if (pService == &sDefault) {
3520                                 if (defaults_saved && is_default(i))
3521                                         continue;
3522                         } else {
3523                                 if (equal_parameter(parm_table[i].type,
3524                                                     ((char *)pService) +
3525                                                     pdiff,
3526                                                     ((char *)&sDefault) +
3527                                                     pdiff))
3528                                         continue;
3529                         }
3530
3531                         fprintf(f, "\t%s = ", parm_table[i].label);
3532                         print_parameter(&parm_table[i],
3533                                         ((char *)pService) + pdiff, f);
3534                         fprintf(f, "\n");
3535         }
3536         if (pService->param_opt != NULL) {
3537                 data = pService->param_opt;
3538                 while(data) {
3539                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3540                         data = data->next;
3541                 }
3542         }
3543 }
3544
3545
3546 /***************************************************************************
3547  Return info about the next service  in a service. snum==-1 gives the globals.
3548  Return NULL when out of parameters.
3549 ***************************************************************************/
3550
3551 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3552 {
3553         if (snum == -1) {
3554                 /* do the globals */
3555                 for (; parm_table[*i].label; (*i)++) {
3556                         if (parm_table[*i].class == P_SEPARATOR)
3557                                 return &parm_table[(*i)++];
3558
3559                         if (!parm_table[*i].ptr
3560                             || (*parm_table[*i].label == '-'))
3561                                 continue;
3562
3563                         if ((*i) > 0
3564                             && (parm_table[*i].ptr ==
3565                                 parm_table[(*i) - 1].ptr))
3566                                 continue;
3567
3568                         return &parm_table[(*i)++];
3569                 }
3570         } else {
3571                 service *pService = ServicePtrs[snum];
3572
3573                 for (; parm_table[*i].label; (*i)++) {
3574                         if (parm_table[*i].class == P_SEPARATOR)
3575                                 return &parm_table[(*i)++];
3576
3577                         if (parm_table[*i].class == P_LOCAL &&
3578                             parm_table[*i].ptr &&
3579                             (*parm_table[*i].label != '-') &&
3580                             ((*i) == 0 ||
3581                              (parm_table[*i].ptr !=
3582                               parm_table[(*i) - 1].ptr)))
3583                         {
3584                                 int pdiff =
3585                                         PTR_DIFF(parm_table[*i].ptr,
3586                                                  &sDefault);
3587
3588                                 if (allparameters ||
3589                                     !equal_parameter(parm_table[*i].type,
3590                                                      ((char *)pService) +
3591                                                      pdiff,
3592                                                      ((char *)&sDefault) +
3593                                                      pdiff))
3594                                 {
3595                                         return &parm_table[(*i)++];
3596                                 }
3597                         }
3598                 }
3599         }
3600
3601         return NULL;
3602 }
3603
3604
3605 #if 0
3606 /***************************************************************************
3607  Display the contents of a single copy structure.
3608 ***************************************************************************/
3609 static void dump_copy_map(BOOL *pcopymap)
3610 {
3611         int i;
3612         if (!pcopymap)
3613                 return;
3614
3615         printf("\n\tNon-Copied parameters:\n");
3616
3617         for (i = 0; parm_table[i].label; i++)
3618                 if (parm_table[i].class == P_LOCAL &&
3619                     parm_table[i].ptr && !pcopymap[i] &&
3620                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3621                 {
3622                         printf("\t\t%s\n", parm_table[i].label);
3623                 }
3624 }
3625 #endif
3626
3627 /***************************************************************************
3628  Return TRUE if the passed service number is within range.
3629 ***************************************************************************/
3630
3631 BOOL lp_snum_ok(int iService)
3632 {
3633         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3634 }
3635
3636 /***************************************************************************
3637  Auto-load some home services.
3638 ***************************************************************************/
3639
3640 static void lp_add_auto_services(char *str)
3641 {
3642         char *s;
3643         char *p;
3644         int homes;
3645
3646         if (!str)
3647                 return;
3648
3649         s = strdup(str);
3650         if (!s)
3651                 return;
3652
3653         homes = lp_servicenumber(HOMES_NAME);
3654
3655         for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
3656                 char *home = get_user_home_dir(p);
3657
3658                 if (lp_servicenumber(p) >= 0)
3659                         continue;
3660
3661                 if (home && homes >= 0)
3662                         lp_add_home(p, homes, p, home);
3663         }
3664         SAFE_FREE(s);
3665 }
3666
3667 /***************************************************************************
3668  Auto-load one printer.
3669 ***************************************************************************/
3670
3671 void lp_add_one_printer(char *name, char *comment)
3672 {
3673         int printers = lp_servicenumber(PRINTERS_NAME);
3674         int i;
3675
3676         if (lp_servicenumber(name) < 0) {
3677                 lp_add_printer(name, printers);
3678                 if ((i = lp_servicenumber(name)) >= 0) {
3679                         string_set(&ServicePtrs[i]->comment, comment);
3680                         ServicePtrs[i]->autoloaded = True;
3681                 }
3682         }
3683 }
3684
3685 /***************************************************************************
3686  Announce ourselves as a print server.
3687 ***************************************************************************/
3688
3689 void update_server_announce_as_printserver(void)
3690 {
3691         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
3692 }
3693
3694 /***************************************************************************
3695  Have we loaded a services file yet?
3696 ***************************************************************************/
3697
3698 BOOL lp_loaded(void)
3699 {
3700         return (bLoaded);
3701 }
3702
3703 /***************************************************************************
3704  Unload unused services.
3705 ***************************************************************************/
3706
3707 void lp_killunused(BOOL (*snumused) (int))
3708 {
3709         int i;
3710         for (i = 0; i < iNumServices; i++) {
3711                 if (!VALID(i))
3712                         continue;
3713
3714                 if (!snumused || !snumused(i)) {
3715                         ServicePtrs[i]->valid = False;
3716                         free_service(ServicePtrs[i]);
3717                 }
3718         }
3719 }
3720
3721 /***************************************************************************
3722  Unload a service.
3723 ***************************************************************************/
3724
3725 void lp_killservice(int iServiceIn)
3726 {
3727         if (VALID(iServiceIn)) {
3728                 ServicePtrs[iServiceIn]->valid = False;
3729                 free_service(ServicePtrs[iServiceIn]);
3730         }
3731 }
3732
3733 /***************************************************************************
3734  Save the curent values of all global and sDefault parameters into the 
3735  defaults union. This allows swat and testparm to show only the
3736  changed (ie. non-default) parameters.
3737 ***************************************************************************/
3738
3739 static void lp_save_defaults(void)
3740 {
3741         int i;
3742         for (i = 0; parm_table[i].label; i++) {
3743                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
3744                         continue;
3745                 switch (parm_table[i].type) {
3746                         case P_LIST:
3747                                 str_list_copy(&(parm_table[i].def.lvalue),
3748                                             *(const char ***)parm_table[i].ptr);
3749                                 break;
3750                         case P_STRING:
3751                         case P_USTRING:
3752                                 if (parm_table[i].ptr) {
3753                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
3754                                 } else {
3755                                         parm_table[i].def.svalue = NULL;
3756                                 }
3757                                 break;
3758                         case P_GSTRING:
3759                         case P_UGSTRING:
3760                                 if (parm_table[i].ptr) {
3761                                         parm_table[i].def.svalue = strdup((char *)parm_table[i].ptr);
3762                                 } else {
3763                                         parm_table[i].def.svalue = NULL;
3764                                 }
3765                                 break;
3766                         case P_BOOL:
3767                         case P_BOOLREV:
3768                                 parm_table[i].def.bvalue =
3769                                         *(BOOL *)parm_table[i].ptr;
3770                                 break;
3771                         case P_CHAR:
3772                                 parm_table[i].def.cvalue =
3773                                         *(char *)parm_table[i].ptr;
3774                                 break;
3775                         case P_INTEGER:
3776                         case P_OCTAL:
3777                         case P_ENUM:
3778                                 parm_table[i].def.ivalue =
3779                                         *(int *)parm_table[i].ptr;
3780                                 break;
3781                         case P_SEP:
3782                                 break;
3783                 }
3784         }
3785         defaults_saved = True;
3786 }
3787
3788 /*******************************************************************
3789  Set the server type we will announce as via nmbd.
3790 ********************************************************************/
3791
3792 static void set_server_role(void)
3793 {
3794         server_role = ROLE_STANDALONE;
3795
3796         switch (lp_security()) {
3797                 case SEC_SHARE:
3798                         if (lp_domain_logons())
3799                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
3800                         break;
3801                 case SEC_SERVER:
3802                         if (lp_domain_logons())
3803                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
3804                         server_role = ROLE_DOMAIN_MEMBER;
3805                         break;
3806                 case SEC_DOMAIN:
3807                         if (lp_domain_logons()) {
3808                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
3809                                 server_role = ROLE_DOMAIN_BDC;
3810                                 break;
3811                         }
3812                         server_role = ROLE_DOMAIN_MEMBER;
3813                         break;
3814                 case SEC_ADS:
3815                         if (lp_domain_logons()) {
3816                                 server_role = ROLE_DOMAIN_PDC;
3817                                 break;
3818                         }
3819                         server_role = ROLE_DOMAIN_MEMBER;
3820                         break;
3821                 case SEC_USER:
3822                         if (lp_domain_logons()) {
3823
3824                                 if (Globals.bDomainMaster) /* auto or yes */ 
3825                                         server_role = ROLE_DOMAIN_PDC;
3826                                 else
3827                                         server_role = ROLE_DOMAIN_BDC;
3828                         }
3829                         break;
3830                 default:
3831                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
3832                         break;
3833         }
3834
3835         DEBUG(10, ("set_server_role: role = "));
3836
3837         switch(server_role) {
3838         case ROLE_STANDALONE:
3839                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
3840                 break;
3841         case ROLE_DOMAIN_MEMBER:
3842                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
3843                 break;
3844         case ROLE_DOMAIN_BDC:
3845                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
3846                 break;
3847         case ROLE_DOMAIN_PDC:
3848                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
3849                 break;
3850         }
3851 }
3852
3853 /***************************************************************************
3854  Load the services array from the services file. Return True on success, 
3855  False on failure.
3856 ***************************************************************************/
3857
3858 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
3859              BOOL add_ipc)
3860 {
3861         pstring n2;
3862         BOOL bRetval;
3863         param_opt_struct *data, *pdata;
3864
3865         pstrcpy(n2, pszFname);
3866         standard_sub_basic(current_user_info.smb_name, n2,sizeof(n2));
3867
3868         add_to_file_list(pszFname, n2);
3869
3870         bRetval = False;
3871
3872         DEBUG(3, ("lp_load: refreshing parameters\n"));
3873         
3874         bInGlobalSection = True;
3875         bGlobalOnly = global_only;
3876
3877         init_globals();
3878         debug_init();
3879
3880         if (save_defaults)
3881         {
3882                 init_locals();
3883                 lp_save_defaults();
3884         }
3885
3886         if (Globals.param_opt != NULL) {
3887                 data = Globals.param_opt;
3888                 while (data) {
3889                         string_free(&data->key);
3890                         string_free(&data->value);
3891                         pdata = data->next;
3892                         SAFE_FREE(data);
3893                         data = pdata;
3894                 }
3895                 Globals.param_opt = NULL;
3896         }
3897         
3898         /* We get sections first, so have to start 'behind' to make up */
3899         iServiceIndex = -1;
3900         bRetval = pm_process(n2, do_section, do_parameter);
3901
3902         /* finish up the last section */
3903         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3904         if (bRetval)
3905                 if (iServiceIndex >= 0)
3906                         bRetval = service_ok(iServiceIndex);
3907
3908         lp_add_auto_services(lp_auto_services());
3909
3910         if (add_ipc) {
3911                 /* When 'restrict anonymous = 2' guest connections to ipc$
3912                    are denied */
3913                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3914                 lp_add_ipc("ADMIN$", False);
3915         }
3916
3917         set_server_role();
3918         set_default_server_announce_type();
3919
3920         bLoaded = True;
3921
3922         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3923         /* if bWINSsupport is true and we are in the client            */
3924         if (in_client && Globals.bWINSsupport) {
3925                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3926         }
3927
3928         init_iconv();
3929
3930         return (bRetval);
3931 }
3932
3933 /***************************************************************************
3934  Reset the max number of services.
3935 ***************************************************************************/
3936
3937 void lp_resetnumservices(void)
3938 {
3939         iNumServices = 0;
3940 }
3941
3942 /***************************************************************************
3943  Return the max number of services.
3944 ***************************************************************************/
3945
3946 int lp_numservices(void)
3947 {
3948         return (iNumServices);
3949 }
3950
3951 /***************************************************************************
3952 Display the contents of the services array in human-readable form.
3953 ***************************************************************************/
3954
3955 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3956 {
3957         int iService;
3958
3959         if (show_defaults)
3960                 defaults_saved = False;
3961
3962         dump_globals(f);
3963
3964         dump_a_service(&sDefault, f);
3965
3966         for (iService = 0; iService < maxtoprint; iService++)
3967                 lp_dump_one(f, show_defaults, iService);
3968 }
3969
3970 /***************************************************************************
3971 Display the contents of one service in human-readable form.
3972 ***************************************************************************/
3973
3974 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3975 {
3976         if (VALID(snum)) {
3977                 if (ServicePtrs[snum]->szService[0] == '\0')
3978                         return;
3979                 dump_a_service(ServicePtrs[snum], f);
3980         }
3981 }
3982
3983 /***************************************************************************
3984 Return the number of the service with the given name, or -1 if it doesn't
3985 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3986 getservicebyname()! This works ONLY if all services have been loaded, and
3987 does not copy the found service.
3988 ***************************************************************************/
3989
3990 int lp_servicenumber(const char *pszServiceName)
3991 {
3992         int iService;
3993         fstring serviceName;
3994  
3995  
3996         for (iService = iNumServices - 1; iService >= 0; iService--) {
3997                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3998                         /*
3999                          * The substitution here is used to support %U is
4000                          * service names
4001                          */
4002                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
4003                         standard_sub_basic(current_user_info.smb_name, serviceName,sizeof(serviceName));
4004                         if (strequal(serviceName, pszServiceName))
4005                                 break;
4006                 }
4007         }
4008
4009         if (iService < 0)
4010                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4011
4012         return (iService);
4013 }
4014
4015 /*******************************************************************
4016  A useful volume label function. 
4017 ********************************************************************/
4018
4019 char *volume_label(int snum)
4020 {
4021         char *ret = lp_volume(snum);
4022         if (!*ret)
4023                 return lp_servicename(snum);
4024         return (ret);
4025 }
4026
4027
4028 /*******************************************************************
4029  Set the server type we will announce as via nmbd.
4030 ********************************************************************/
4031
4032 static void set_default_server_announce_type(void)
4033 {
4034         default_server_announce = 0;
4035         default_server_announce |= SV_TYPE_WORKSTATION;
4036         default_server_announce |= SV_TYPE_SERVER;
4037         default_server_announce |= SV_TYPE_SERVER_UNIX;
4038
4039         switch (lp_announce_as()) {
4040                 case ANNOUNCE_AS_NT_SERVER:
4041                         default_server_announce |= SV_TYPE_SERVER_NT;
4042                         /* fall through... */
4043                 case ANNOUNCE_AS_NT_WORKSTATION:
4044                         default_server_announce |= SV_TYPE_NT;
4045                         break;
4046                 case ANNOUNCE_AS_WIN95:
4047                         default_server_announce |= SV_TYPE_WIN95_PLUS;
4048                         break;
4049                 case ANNOUNCE_AS_WFW:
4050                         default_server_announce |= SV_TYPE_WFW;
4051                         break;
4052                 default:
4053                         break;
4054         }
4055
4056         switch (lp_server_role()) {
4057                 case ROLE_DOMAIN_MEMBER:
4058                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4059                         break;
4060                 case ROLE_DOMAIN_PDC:
4061                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4062                         break;
4063                 case ROLE_DOMAIN_BDC:
4064                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4065                         break;
4066                 case ROLE_STANDALONE:
4067                 default:
4068                         break;
4069         }
4070         if (lp_time_server())
4071                 default_server_announce |= SV_TYPE_TIME_SOURCE;
4072
4073         if (lp_host_msdfs())
4074                 default_server_announce |= SV_TYPE_DFS_SERVER;
4075 }
4076
4077 /***********************************************************
4078  returns role of Samba server
4079 ************************************************************/
4080
4081 int lp_server_role(void)
4082 {
4083         return server_role;
4084 }
4085
4086 /***********************************************************
4087  If we are PDC then prefer us as DMB
4088 ************************************************************/
4089
4090 BOOL lp_domain_master(void)
4091 {
4092         if (Globals.bDomainMaster == Auto)
4093                 return (lp_server_role() == ROLE_DOMAIN_PDC);
4094
4095         return Globals.bDomainMaster;
4096 }
4097
4098 /***********************************************************
4099  If we are DMB then prefer us as LMB
4100 ************************************************************/
4101
4102 BOOL lp_preferred_master(void)
4103 {
4104         if (Globals.bPreferredMaster == Auto)
4105                 return (lp_local_master() && lp_domain_master());
4106
4107         return Globals.bPreferredMaster;
4108 }
4109
4110 /*******************************************************************
4111  Remove a service.
4112 ********************************************************************/
4113
4114 void lp_remove_service(int snum)
4115 {
4116         ServicePtrs[snum]->valid = False;
4117 }
4118
4119 /*******************************************************************
4120  Copy a service.
4121 ********************************************************************/
4122
4123 void lp_copy_service(int snum, const char *new_name)
4124 {
4125         char *oldname = lp_servicename(snum);
4126         do_section(new_name);
4127         if (snum >= 0) {
4128                 snum = lp_servicenumber(new_name);
4129                 if (snum >= 0)
4130                         lp_do_parameter(snum, "copy", oldname);
4131         }
4132 }
4133
4134
4135 /*******************************************************************
4136  Get the default server type we will announce as via nmbd.
4137 ********************************************************************/
4138
4139 int lp_default_server_announce(void)
4140 {
4141         return default_server_announce;
4142 }
4143
4144 /*******************************************************************
4145  Split the announce version into major and minor numbers.
4146 ********************************************************************/
4147
4148 int lp_major_announce_version(void)
4149 {
4150         static BOOL got_major = False;
4151         static int major_version = DEFAULT_MAJOR_VERSION;
4152         char *vers;
4153         char *p;
4154
4155         if (got_major)
4156                 return major_version;
4157
4158         got_major = True;
4159         if ((vers = lp_announce_version()) == NULL)
4160                 return major_version;
4161
4162         if ((p = strchr_m(vers, '.')) == 0)
4163                 return major_version;
4164
4165         *p = '\0';
4166         major_version = atoi(vers);
4167         return major_version;
4168 }
4169
4170 int lp_minor_announce_version(void)
4171 {
4172         static BOOL got_minor = False;
4173         static int minor_version = DEFAULT_MINOR_VERSION;
4174         char *vers;
4175         char *p;
4176
4177         if (got_minor)
4178                 return minor_version;
4179
4180         got_minor = True;
4181         if ((vers = lp_announce_version()) == NULL)
4182                 return minor_version;
4183
4184         if ((p = strchr_m(vers, '.')) == 0)
4185                 return minor_version;
4186
4187         p++;
4188         minor_version = atoi(p);
4189         return minor_version;
4190 }
4191
4192 /***********************************************************
4193  Set the global name resolution order (used in smbclient).
4194 ************************************************************/
4195
4196 void lp_set_name_resolve_order(char *new_order)
4197 {
4198         Globals.szNameResolveOrder = new_order;
4199 }
4200
4201 const char *lp_printername(int snum)
4202 {
4203         const char *ret = _lp_printername(snum);
4204         if (ret == NULL || (ret != NULL && *ret == '\0'))
4205                 ret = lp_const_servicename(snum);
4206
4207         return ret;
4208 }
4209
4210
4211 /****************************************************************
4212  Compatibility fn. for 2.2.2 code.....
4213 *****************************************************************/
4214
4215 void get_private_directory(pstring privdir)
4216 {
4217         pstrcpy (privdir, lp_private_dir());
4218 }
4219
4220 /***********************************************************
4221  Allow daemons such as winbindd to fix their logfile name.
4222 ************************************************************/
4223
4224 void lp_set_logfile(const char *name)
4225 {
4226         extern pstring debugf;
4227         string_set(&Globals.szLogFile, name);
4228         pstrcpy(debugf, name);
4229 }
4230
4231 /*******************************************************************
4232  Return the NetBIOS called name.
4233 ********************************************************************/
4234
4235 const char *get_called_name(void)
4236 {
4237         extern fstring local_machine;
4238         static fstring called_name;
4239
4240         if (! *local_machine)
4241                 return global_myname();
4242
4243         /*
4244          * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV"
4245          * arrggg!!! but we've already rewritten the client's
4246          * netbios name at this point...
4247          */
4248
4249         if (*local_machine) {
4250                 if (!StrCaseCmp(local_machine, "_SMBSERVER") || !StrCaseCmp(local_machine, "_SMBSERV")) {
4251                         fstrcpy(called_name, get_my_primary_ip());
4252                         DEBUG(8,("get_called_name: assuming that client used IP address [%s] as called name.\n",
4253                                 called_name));
4254                         return called_name;
4255                 }
4256         }
4257
4258         return local_machine;
4259 }
4260
4261 /*******************************************************************
4262  Return the max print jobs per queue.
4263 ********************************************************************/
4264
4265 int lp_maxprintjobs(int snum)
4266 {
4267         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4268         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4269                 maxjobs = PRINT_MAX_JOBID - 1;
4270
4271         return maxjobs;
4272 }