This adds 'ldap delete dn' as the recommended parameter
[kai/samba.git] / source3 / param / loadparm.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5
6    Largely re-written by Andrew Tridgell, September 1994
7
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) 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_delete_dn;
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 delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1047         {"ldap del only sam attr", P_BOOLREV, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1048
1049         {"Miscellaneous Options", P_SEP, P_SEPARATOR},
1050         {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1051         {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1052         {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1053         
1054         {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
1055         {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1056         {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1057         {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
1058         {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1059         {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
1060 #ifdef WITH_UTMP
1061         {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1062         {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1063         {"utmp",          P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1064 #endif
1065         
1066         {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1067         {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
1068         {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1069         {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1070         {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1071         {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1072         {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
1073         {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1074         {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1075         {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1076         {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
1077         
1078         {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
1079         {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
1080         {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1081         {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1082         
1083         {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_SHARE},
1084         {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1085         {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1086         {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_SHARE},
1087         {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
1088         {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
1089         {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
1090         {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
1091         {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_SHARE},
1092         {"source environment", P_STRING, P_GLOBAL, &Globals.szSourceEnv, handle_source_env, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1093         {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1094         {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1095         {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_SHARE},
1096         {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_SHARE},
1097         {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_SHARE},
1098         {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1099         {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1100         {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1101         {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1102
1103         {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
1104         {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1105         {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1106
1107         {"VFS module options", P_SEP, P_SEPARATOR},
1108         
1109         {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjectFile, NULL, NULL, FLAG_SHARE},
1110         {"vfs options", P_STRING, P_LOCAL, &sDefault.szVfsOptions, NULL, NULL, FLAG_SHARE},
1111         {"vfs path", P_STRING, P_LOCAL, &sDefault.szVfsPath, NULL, NULL, FLAG_SHARE},
1112
1113         
1114         {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
1115         {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE},
1116         {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1117
1118         {"Winbind options", P_SEP, P_SEPARATOR},
1119
1120         {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1121         {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1122         {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1123         {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1124         {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1125         {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1126         {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1127         {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1128         {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
1129
1130         {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
1131 };
1132
1133 /***************************************************************************
1134  Initialise the sDefault parameter structure for the printer values.
1135 ***************************************************************************/
1136
1137 static void init_printer_values(void)
1138 {
1139         /* choose defaults depending on the type of printing */
1140         switch (sDefault.iPrinting) {
1141                 case PRINT_BSD:
1142                 case PRINT_AIX:
1143                 case PRINT_LPRNT:
1144                 case PRINT_LPROS2:
1145                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
1146                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
1147                         string_set(&sDefault.szPrintcommand,
1148                                    "lpr -r -P'%p' %s");
1149                         break;
1150
1151                 case PRINT_LPRNG:
1152                 case PRINT_PLP:
1153                         string_set(&sDefault.szLpqcommand, "lpq -P'%p'");
1154                         string_set(&sDefault.szLprmcommand, "lprm -P'%p' %j");
1155                         string_set(&sDefault.szPrintcommand,
1156                                    "lpr -r -P'%p' %s");
1157                         string_set(&sDefault.szQueuepausecommand,
1158                                    "lpc stop '%p'");
1159                         string_set(&sDefault.szQueueresumecommand,
1160                                    "lpc start '%p'");
1161                         string_set(&sDefault.szLppausecommand,
1162                                    "lpc hold '%p' %j");
1163                         string_set(&sDefault.szLpresumecommand,
1164                                    "lpc release '%p' %j");
1165                         break;
1166
1167                 case PRINT_CUPS:
1168 #ifdef HAVE_CUPS
1169                         string_set(&sDefault.szLpqcommand, "");
1170                         string_set(&sDefault.szLprmcommand, "");
1171                         string_set(&sDefault.szPrintcommand, "");
1172                         string_set(&sDefault.szLppausecommand, "");
1173                         string_set(&sDefault.szLpresumecommand, "");
1174                         string_set(&sDefault.szQueuepausecommand, "");
1175                         string_set(&sDefault.szQueueresumecommand, "");
1176
1177                         string_set(&Globals.szPrintcapname, "cups");
1178 #else
1179                         string_set(&sDefault.szLpqcommand,
1180                                    "/usr/bin/lpstat -o '%p'");
1181                         string_set(&sDefault.szLprmcommand,
1182                                    "/usr/bin/cancel '%p-%j'");
1183                         string_set(&sDefault.szPrintcommand,
1184                                    "/usr/bin/lp -d '%p' %s; rm %s");
1185                         string_set(&sDefault.szLppausecommand,
1186                                    "lp -i '%p-%j' -H hold");
1187                         string_set(&sDefault.szLpresumecommand,
1188                                    "lp -i '%p-%j' -H resume");
1189                         string_set(&sDefault.szQueuepausecommand,
1190                                    "/usr/bin/disable '%p'");
1191                         string_set(&sDefault.szQueueresumecommand,
1192                                    "/usr/bin/enable '%p'");
1193                         string_set(&Globals.szPrintcapname, "lpstat");
1194 #endif /* HAVE_CUPS */
1195                         break;
1196
1197                 case PRINT_SYSV:
1198                 case PRINT_HPUX:
1199                         string_set(&sDefault.szLpqcommand, "lpstat -o%p");
1200                         string_set(&sDefault.szLprmcommand, "cancel %p-%j");
1201                         string_set(&sDefault.szPrintcommand,
1202                                    "lp -c -d%p %s; rm %s");
1203                         string_set(&sDefault.szQueuepausecommand,
1204                                    "disable %p");
1205                         string_set(&sDefault.szQueueresumecommand,
1206                                    "enable %p");
1207 #ifndef HPUX
1208                         string_set(&sDefault.szLppausecommand,
1209                                    "lp -i %p-%j -H hold");
1210                         string_set(&sDefault.szLpresumecommand,
1211                                    "lp -i %p-%j -H resume");
1212 #endif /* HPUX */
1213                         break;
1214
1215                 case PRINT_QNX:
1216                         string_set(&sDefault.szLpqcommand, "lpq -P%p");
1217                         string_set(&sDefault.szLprmcommand, "lprm -P%p %j");
1218                         string_set(&sDefault.szPrintcommand, "lp -r -P%p %s");
1219                         break;
1220
1221                 case PRINT_SOFTQ:
1222                         string_set(&sDefault.szLpqcommand, "qstat -l -d%p");
1223                         string_set(&sDefault.szLprmcommand,
1224                                    "qstat -s -j%j -c");
1225                         string_set(&sDefault.szPrintcommand,
1226                                    "lp -d%p -s %s; rm %s");
1227                         string_set(&sDefault.szLppausecommand,
1228                                    "qstat -s -j%j -h");
1229                         string_set(&sDefault.szLpresumecommand,
1230                                    "qstat -s -j%j -r");
1231                         break;
1232 #ifdef DEVELOPER
1233         case PRINT_TEST:
1234         case PRINT_VLP:
1235                 string_set(&sDefault.szPrintcommand, "vlp print %p %s");
1236                 string_set(&sDefault.szLpqcommand, "vlp lpq %p");
1237                 string_set(&sDefault.szLprmcommand, "vlp lprm %p %j");
1238                 string_set(&sDefault.szLppausecommand, "vlp lppause %p %j");
1239                 string_set(&sDefault.szLpresumecommand, "vlp lpresum %p %j");
1240                 string_set(&sDefault.szQueuepausecommand, "vlp queuepause %p");
1241                 string_set(&sDefault.szQueueresumecommand, "vlp queueresume %p");
1242                 break;
1243 #endif /* DEVELOPER */
1244
1245         }
1246 }
1247
1248 /***************************************************************************
1249  Initialise the global parameter structure.
1250 ***************************************************************************/
1251
1252 static void init_globals(void)
1253 {
1254         static BOOL done_init = False;
1255         pstring s;
1256
1257         if (!done_init) {
1258                 int i;
1259                 memset((void *)&Globals, '\0', sizeof(Globals));
1260
1261                 for (i = 0; parm_table[i].label; i++)
1262                         if ((parm_table[i].type == P_STRING ||
1263                              parm_table[i].type == P_USTRING) &&
1264                             parm_table[i].ptr)
1265                                 string_set(parm_table[i].ptr, "");
1266
1267                 string_set(&sDefault.fstype, FSTYPE_STRING);
1268
1269                 init_printer_values();
1270
1271                 done_init = True;
1272         }
1273
1274
1275         DEBUG(3, ("Initialising global parameters\n"));
1276
1277         string_set(&Globals.szSMBPasswdFile, dyn_SMB_PASSWD_FILE);
1278         string_set(&Globals.szPrivateDir, dyn_PRIVATE_DIR);
1279
1280         /* use the new 'hash2' method by default, with a prefix of 1 */
1281         string_set(&Globals.szManglingMethod, "hash2");
1282         Globals.mangle_prefix = 1;
1283
1284         string_set(&Globals.szGuestaccount, GUEST_ACCOUNT);
1285
1286         /* using UTF8 by default allows us to support all chars */
1287         string_set(&Globals.unix_charset, "UTF8");
1288
1289         /* using UTF8 by default allows us to support all chars */
1290         string_set(&Globals.display_charset, "ASCII");
1291
1292         /* Use codepage 850 as a default for the dos character set */
1293         string_set(&Globals.dos_charset, "CP850");
1294
1295         /*
1296          * Allow the default PASSWD_CHAT to be overridden in local.h.
1297          */
1298         string_set(&Globals.szPasswdChat, DEFAULT_PASSWD_CHAT);
1299         
1300         set_global_myname(myhostname());
1301         string_set(&Globals.szNetbiosName,global_myname());
1302
1303         set_global_myworkgroup(WORKGROUP);
1304         string_set(&Globals.szWorkgroup, lp_workgroup());
1305         
1306         string_set(&Globals.szPasswdProgram, "");
1307         string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
1308         string_set(&Globals.szPidDir, dyn_PIDDIR);
1309         string_set(&Globals.szLockDir, dyn_LOCKDIR);
1310         string_set(&Globals.szSocketAddress, "0.0.0.0");
1311         pstrcpy(s, "Samba ");
1312         pstrcat(s, VERSION);
1313         string_set(&Globals.szServerString, s);
1314         slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
1315                  DEFAULT_MINOR_VERSION);
1316         string_set(&Globals.szAnnounceVersion, s);
1317
1318         pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
1319
1320         string_set(&Globals.szLogonDrive, "");
1321         /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
1322         string_set(&Globals.szLogonHome, "\\\\%N\\%U");
1323         string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
1324
1325         string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
1326         string_set(&Globals.szPasswordServer, "*");
1327
1328         Globals.AlgorithmicRidBase = BASE_RID;
1329
1330         Globals.bLoadPrinters = True;
1331         Globals.mangled_stack = 50;
1332         /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
1333         /* Discovered by 2 days of pain by Don McCall @ HP :-). */
1334         Globals.max_xmit = 0x4104;
1335         Globals.max_mux = 50;   /* This is *needed* for profile support. */
1336         Globals.lpqcachetime = 10;
1337         Globals.bDisableSpoolss = False;
1338         Globals.iMaxSmbdProcesses = 0;/* no limit specified */
1339         Globals.iTotalPrintJobs = 0;  /* no limit specified */
1340         Globals.pwordlevel = 0;
1341         Globals.unamelevel = 0;
1342         Globals.deadtime = 0;
1343         Globals.bLargeReadwrite = True;
1344         Globals.max_log_size = 5000;
1345         Globals.max_open_files = MAX_OPEN_FILES;
1346         Globals.maxprotocol = PROTOCOL_NT1;
1347         Globals.minprotocol = PROTOCOL_CORE;
1348         Globals.security = SEC_USER;
1349         Globals.paranoid_server_security = True;
1350         Globals.bEncryptPasswords = True;
1351         Globals.bUpdateEncrypt = False;
1352         Globals.bReadRaw = True;
1353         Globals.bWriteRaw = True;
1354         Globals.bReadPrediction = False;
1355         Globals.bReadbmpx = False;
1356         Globals.bNullPasswords = False;
1357         Globals.bObeyPamRestrictions = False;
1358         Globals.bStripDot = False;
1359         Globals.syslog = 1;
1360         Globals.bSyslogOnly = False;
1361         Globals.bTimestampLogs = True;
1362         string_set(&Globals.szLogLevel, "0");
1363         Globals.bDebugHiresTimestamp = False;
1364         Globals.bDebugPid = False;
1365         Globals.bDebugUid = False;
1366         Globals.max_ttl = 60 * 60 * 24 * 3;     /* 3 days default. */
1367         Globals.max_wins_ttl = 60 * 60 * 24 * 6;        /* 6 days default. */
1368         Globals.min_wins_ttl = 60 * 60 * 6;     /* 6 hours default. */
1369         Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
1370         Globals.change_notify_timeout = 60;     /* 1 minute default. */
1371         Globals.bKernelChangeNotify = True;     /* On if we have it. */
1372         Globals.ReadSize = 16 * 1024;
1373         Globals.lm_announce = 2;        /* = Auto: send only if LM clients found */
1374         Globals.lm_interval = 60;
1375         Globals.stat_cache_size = 50;   /* Number of stat translations we'll keep */
1376         Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
1377 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1378         Globals.bNISHomeMap = False;
1379 #ifdef WITH_NISPLUS_HOME
1380         string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
1381 #else
1382         string_set(&Globals.szNISHomeMapName, "auto.home");
1383 #endif
1384 #endif
1385         Globals.bTimeServer = False;
1386         Globals.bBindInterfacesOnly = False;
1387         Globals.bUnixPasswdSync = False;
1388         Globals.bPamPasswordChange = False;
1389         Globals.bPasswdChatDebug = False;
1390         Globals.bUnicode = True;        /* Do unicode on the wire by default */
1391         Globals.bNTPipeSupport = True;  /* Do NT pipes by default. */
1392         Globals.bNTStatusSupport = True; /* Use NT status by default. */
1393         Globals.bStatCache = True;      /* use stat cache by default */
1394         Globals.restrict_anonymous = 0;
1395         Globals.bClientLanManAuth = True;       /* Do use the LanMan hash if it is available */
1396         Globals.bLanmanAuth = True;     /* Do use the LanMan hash if it is available */
1397         Globals.bNTLMAuth = True;       /* Do use NTLMv1 if it is available (otherwise NTLMv2) */
1398         
1399         Globals.map_to_guest = 0;       /* By Default, "Never" */
1400         Globals.min_passwd_length = MINPASSWDLENGTH;    /* By Default, 5. */
1401         Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
1402         Globals.enhanced_browsing = True; 
1403         Globals.iLockSpinCount = 3; /* Try 2 times. */
1404         Globals.iLockSpinTime = 10; /* usec. */
1405 #ifdef MMAP_BLACKLIST
1406         Globals.bUseMmap = False;
1407 #else
1408         Globals.bUseMmap = True;
1409 #endif
1410         Globals.bUnixExtensions = False;
1411
1412         /* hostname lookups can be very expensive and are broken on
1413            a large number of sites (tridge) */
1414         Globals.bHostnameLookups = False;
1415
1416 #ifdef WITH_LDAP_SAMCONFIG
1417         string_set(&Globals.szLdapServer, "localhost");
1418         Globals.ldap_port = 636;
1419         Globals.szPassdbBackend = str_list_make("ldapsam guest", NULL);
1420 #else
1421         Globals.szPassdbBackend = str_list_make("smbpasswd guest", NULL);
1422 #endif /* WITH_LDAP_SAMCONFIG */
1423
1424         string_set(&Globals.szLdapSuffix, "");
1425         string_set(&Globals.szLdapMachineSuffix, "");
1426         string_set(&Globals.szLdapUserSuffix, "");
1427
1428         string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
1429         string_set(&Globals.szLdapAdminDn, "");
1430         Globals.ldap_ssl = LDAP_SSL_ON;
1431         Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
1432         Globals.ldap_delete_dn = False;
1433
1434 /* these parameters are set to defaults that are more appropriate
1435    for the increasing samba install base:
1436
1437    as a member of the workgroup, that will possibly become a
1438    _local_ master browser (lm = True).  this is opposed to a forced
1439    local master browser startup (pm = True).
1440
1441    doesn't provide WINS server service by default (wsupp = False),
1442    and doesn't provide domain master browser services by default, either.
1443
1444 */
1445
1446         Globals.bMsAddPrinterWizard = True;
1447         Globals.bPreferredMaster = Auto;        /* depending on bDomainMaster */
1448         Globals.os_level = 20;
1449         Globals.bLocalMaster = True;
1450         Globals.bDomainMaster = Auto;   /* depending on bDomainLogons */
1451         Globals.bDomainLogons = False;
1452         Globals.bBrowseList = True;
1453         Globals.bWINSsupport = False;
1454         Globals.bWINSproxy = False;
1455
1456         Globals.bDNSproxy = True;
1457
1458         /* this just means to use them if they exist */
1459         Globals.bKernelOplocks = True;
1460
1461         Globals.bAllowTrustedDomains = True;
1462
1463         string_set(&Globals.szTemplateShell, "/bin/false");
1464         string_set(&Globals.szTemplateHomedir, "/home/%D/%U");
1465         string_set(&Globals.szWinbindSeparator, "\\");
1466         string_set(&Globals.szAclCompat, "");
1467
1468         Globals.winbind_cache_time = 15;
1469         Globals.bWinbindEnumUsers = True;
1470         Globals.bWinbindEnumGroups = True;
1471         Globals.bWinbindUseDefaultDomain = False;
1472
1473         string_set(&Globals.szIDMapBackend, "tdb");
1474
1475         Globals.name_cache_timeout = 660; /* In seconds */
1476
1477         Globals.bUseSpnego = True;
1478         Globals.bClientUseSpnego = True;
1479
1480         string_set(&Globals.smb_ports, SMB_PORTS);
1481 }
1482
1483 static TALLOC_CTX *lp_talloc;
1484
1485 /******************************************************************* a
1486  Free up temporary memory - called from the main loop.
1487 ********************************************************************/
1488
1489 void lp_talloc_free(void)
1490 {
1491         if (!lp_talloc)
1492                 return;
1493         talloc_destroy(lp_talloc);
1494         lp_talloc = NULL;
1495 }
1496
1497 /*******************************************************************
1498  Convenience routine to grab string parameters into temporary memory
1499  and run standard_sub_basic on them. The buffers can be written to by
1500  callers without affecting the source string.
1501 ********************************************************************/
1502
1503 static char *lp_string(const char *s)
1504 {
1505         size_t len = s ? strlen(s) : 0;
1506         char *ret;
1507
1508         /* The follow debug is useful for tracking down memory problems
1509            especially if you have an inner loop that is calling a lp_*()
1510            function that returns a string.  Perhaps this debug should be
1511            present all the time? */
1512
1513 #if 0
1514         DEBUG(10, ("lp_string(%s)\n", s));
1515 #endif
1516
1517         if (!lp_talloc)
1518                 lp_talloc = talloc_init("lp_talloc");
1519
1520         ret = (char *)talloc(lp_talloc, len + 100);     /* leave room for substitution */
1521
1522         if (!ret)
1523                 return NULL;
1524
1525         /* Note: StrnCpy touches len+1 bytes, but we allocate 100
1526          * extra bytes so we're OK. */
1527
1528         if (!s)
1529                 *ret = 0;
1530         else
1531                 StrnCpy(ret, s, len);
1532
1533         if (trim_string(ret, "\"", "\"")) {
1534                 if (strchr(ret,'"') != NULL)
1535                         StrnCpy(ret, s, len);
1536         }
1537
1538         standard_sub_basic(current_user_info.smb_name,ret,len+100);
1539         return (ret);
1540 }
1541
1542 /*
1543    In this section all the functions that are used to access the 
1544    parameters from the rest of the program are defined 
1545 */
1546
1547 #define FN_GLOBAL_STRING(fn_name,ptr) \
1548  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1549 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1550  const char *fn_name(void) {return(*(const char **)(ptr) ? *(const char **)(ptr) : "");}
1551 #define FN_GLOBAL_LIST(fn_name,ptr) \
1552  const char **fn_name(void) {return(*(const char ***)(ptr));}
1553 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1554  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1555 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1556  char fn_name(void) {return(*(char *)(ptr));}
1557 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1558  int fn_name(void) {return(*(int *)(ptr));}
1559
1560 #define FN_LOCAL_STRING(fn_name,val) \
1561  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
1562 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1563  const char *fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1564 #define FN_LOCAL_LIST(fn_name,val) \
1565  const char **fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1566 #define FN_LOCAL_BOOL(fn_name,val) \
1567  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1568 #define FN_LOCAL_CHAR(fn_name,val) \
1569  char fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1570 #define FN_LOCAL_INTEGER(fn_name,val) \
1571  int fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1572
1573 FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports)
1574 FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset)
1575 FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset)
1576 FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset)
1577 FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
1578 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
1579 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
1580 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
1581 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
1582 FN_GLOBAL_STRING(lp_printcapname, &Globals.szPrintcapname)
1583 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
1584 FN_GLOBAL_STRING(lp_addprinter_cmd, &Globals.szAddPrinterCommand)
1585 FN_GLOBAL_STRING(lp_deleteprinter_cmd, &Globals.szDeletePrinterCommand)
1586 FN_GLOBAL_STRING(lp_os2_driver_map, &Globals.szOs2DriverMap)
1587 FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir)
1588 FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir)
1589 FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod)
1590 FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix)
1591 #ifdef WITH_UTMP
1592 FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir)
1593 FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir)
1594 FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp)
1595 #endif
1596 FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir)
1597 FN_GLOBAL_STRING(lp_source_environment, &Globals.szSourceEnv)
1598 FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService)
1599 FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand)
1600 FN_GLOBAL_STRING(lp_dfree_command, &Globals.szDfree)
1601 FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv)
1602 FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices)
1603 FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram)
1604 FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat)
1605 FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer)
1606 FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
1607 FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
1608 FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver)
1609 FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
1610 FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
1611 FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
1612 FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive)
1613 FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome)
1614 FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce)
1615 FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync)
1616 FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers)
1617 FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces)
1618 FN_GLOBAL_STRING(lp_socket_address, &Globals.szSocketAddress)
1619 FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
1620 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
1621 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
1622 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
1623 FN_GLOBAL_LIST(lp_sam_backend, &Globals.szSamBackend)
1624 FN_GLOBAL_LIST(lp_preload_modules, &Globals.szPreloadModules)
1625 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
1626 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
1627 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
1628
1629 FN_GLOBAL_CONST_STRING(lp_guestaccount, &Globals.szGuestaccount)
1630 FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
1631 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
1632 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
1633 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
1634 FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
1635
1636 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
1637
1638 FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
1639 FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
1640
1641 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
1642 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
1643 FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
1644 FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
1645 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
1646 FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
1647 FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers)
1648 FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
1649 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
1650 FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIDMapBackend)
1651
1652 #ifdef WITH_LDAP_SAMCONFIG
1653 FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer)
1654 FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port)
1655 #endif
1656 FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix)
1657 FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix)
1658 FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
1659 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
1660 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
1661 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
1662 FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
1663 FN_GLOBAL_BOOL(lp_ldap_trust_ids, &Globals.ldap_trust_ids)
1664 FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn)
1665 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
1666 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
1667 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
1668
1669 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
1670 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
1671 FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
1672 FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
1673 FN_GLOBAL_BOOL(lp_we_are_a_wins_server, &Globals.bWINSsupport)
1674 FN_GLOBAL_BOOL(lp_wins_proxy, &Globals.bWINSproxy)
1675 FN_GLOBAL_BOOL(lp_local_master, &Globals.bLocalMaster)
1676 FN_GLOBAL_BOOL(lp_domain_logons, &Globals.bDomainLogons)
1677 FN_GLOBAL_BOOL(lp_load_printers, &Globals.bLoadPrinters)
1678 FN_GLOBAL_BOOL(lp_readprediction, &Globals.bReadPrediction)
1679 FN_GLOBAL_BOOL(lp_readbmpx, &Globals.bReadbmpx)
1680 FN_GLOBAL_BOOL(lp_readraw, &Globals.bReadRaw)
1681 FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite)
1682 FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw)
1683 FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords)
1684 FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions)
1685 FN_GLOBAL_BOOL(lp_strip_dot, &Globals.bStripDot)
1686 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
1687 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
1688 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
1689 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
1690 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
1691 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
1692 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
1693 FN_GLOBAL_BOOL(lp_browse_list, &Globals.bBrowseList)
1694 FN_GLOBAL_BOOL(lp_nis_home_map, &Globals.bNISHomeMap)
1695 static FN_GLOBAL_BOOL(lp_time_server, &Globals.bTimeServer)
1696 FN_GLOBAL_BOOL(lp_bind_interfaces_only, &Globals.bBindInterfacesOnly)
1697 FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
1698 FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
1699 FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
1700 FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
1701 FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
1702 FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
1703 FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
1704 FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains)
1705 FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous)
1706 FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth)
1707 FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth)
1708 FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth)
1709 FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth)
1710 FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs)
1711 FN_GLOBAL_BOOL(lp_kernel_oplocks, &Globals.bKernelOplocks)
1712 FN_GLOBAL_BOOL(lp_enhanced_browsing, &Globals.enhanced_browsing)
1713 FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap)
1714 FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions)
1715 FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego)
1716 FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego)
1717 FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups)
1718 FN_GLOBAL_BOOL(lp_kernel_change_notify, &Globals.bKernelChangeNotify)
1719 FN_GLOBAL_INTEGER(lp_os_level, &Globals.os_level)
1720 FN_GLOBAL_INTEGER(lp_max_ttl, &Globals.max_ttl)
1721 FN_GLOBAL_INTEGER(lp_max_wins_ttl, &Globals.max_wins_ttl)
1722 FN_GLOBAL_INTEGER(lp_min_wins_ttl, &Globals.min_wins_ttl)
1723 FN_GLOBAL_INTEGER(lp_max_log_size, &Globals.max_log_size)
1724 FN_GLOBAL_INTEGER(lp_max_open_files, &Globals.max_open_files)
1725 FN_GLOBAL_INTEGER(lp_maxxmit, &Globals.max_xmit)
1726 FN_GLOBAL_INTEGER(lp_maxmux, &Globals.max_mux)
1727 FN_GLOBAL_INTEGER(lp_passwordlevel, &Globals.pwordlevel)
1728 FN_GLOBAL_INTEGER(lp_usernamelevel, &Globals.unamelevel)
1729 FN_GLOBAL_INTEGER(lp_readsize, &Globals.ReadSize)
1730 FN_GLOBAL_INTEGER(lp_deadtime, &Globals.deadtime)
1731 FN_GLOBAL_INTEGER(lp_maxprotocol, &Globals.maxprotocol)
1732 FN_GLOBAL_INTEGER(lp_minprotocol, &Globals.minprotocol)
1733 FN_GLOBAL_INTEGER(lp_security, &Globals.security)
1734 FN_GLOBAL_LIST(lp_auth_methods, &Globals.AuthMethods)
1735 FN_GLOBAL_BOOL(lp_paranoid_server_security, &Globals.paranoid_server_security)
1736 FN_GLOBAL_INTEGER(lp_maxdisksize, &Globals.maxdisksize)
1737 FN_GLOBAL_INTEGER(lp_lpqcachetime, &Globals.lpqcachetime)
1738 FN_GLOBAL_INTEGER(lp_max_smbd_processes, &Globals.iMaxSmbdProcesses)
1739 FN_GLOBAL_INTEGER(lp_disable_spoolss, &Globals.bDisableSpoolss)
1740 FN_GLOBAL_INTEGER(lp_totalprintjobs, &Globals.iTotalPrintJobs)
1741 FN_GLOBAL_INTEGER(lp_syslog, &Globals.syslog)
1742 static FN_GLOBAL_INTEGER(lp_announce_as, &Globals.announce_as)
1743 FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce)
1744 FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
1745 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
1746 FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
1747 FN_GLOBAL_INTEGER(lp_stat_cache_size, &Globals.stat_cache_size)
1748 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
1749 FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
1750 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
1751 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
1752 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
1753 FN_LOCAL_STRING(lp_preexec, szPreExec)
1754 FN_LOCAL_STRING(lp_postexec, szPostExec)
1755 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
1756 FN_LOCAL_STRING(lp_rootpostexec, szRootPostExec)
1757 FN_LOCAL_STRING(lp_servicename, szService)
1758 FN_LOCAL_CONST_STRING(lp_const_servicename, szService)
1759 FN_LOCAL_STRING(lp_pathname, szPath)
1760 FN_LOCAL_STRING(lp_dontdescend, szDontdescend)
1761 FN_LOCAL_STRING(lp_username, szUsername)
1762 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
1763 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
1764 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
1765 FN_LOCAL_STRING(lp_printcommand, szPrintcommand)
1766 FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand)
1767 FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand)
1768 FN_LOCAL_STRING(lp_lppausecommand, szLppausecommand)
1769 FN_LOCAL_STRING(lp_lpresumecommand, szLpresumecommand)
1770 FN_LOCAL_STRING(lp_queuepausecommand, szQueuepausecommand)
1771 FN_LOCAL_STRING(lp_queueresumecommand, szQueueresumecommand)
1772 static FN_LOCAL_STRING(_lp_printername, szPrintername)
1773 FN_LOCAL_LIST(lp_hostsallow, szHostsallow)
1774 FN_LOCAL_LIST(lp_hostsdeny, szHostsdeny)
1775 FN_LOCAL_STRING(lp_magicscript, szMagicScript)
1776 FN_LOCAL_STRING(lp_magicoutput, szMagicOutput)
1777 FN_LOCAL_STRING(lp_comment, comment)
1778 FN_LOCAL_STRING(lp_force_user, force_user)
1779 FN_LOCAL_STRING(lp_force_group, force_group)
1780 FN_LOCAL_LIST(lp_readlist, readlist)
1781 FN_LOCAL_LIST(lp_writelist, writelist)
1782 FN_LOCAL_LIST(lp_printer_admin, printer_admin)
1783 FN_LOCAL_STRING(lp_fstype, fstype)
1784 FN_LOCAL_LIST(lp_vfsobj, szVfsObjectFile)
1785 FN_LOCAL_STRING(lp_vfs_options, szVfsOptions)
1786 FN_LOCAL_STRING(lp_vfs_path, szVfsPath)
1787 FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy)
1788 static FN_LOCAL_STRING(lp_volume, volume)
1789 FN_LOCAL_STRING(lp_mangled_map, szMangledMap)
1790 FN_LOCAL_STRING(lp_veto_files, szVetoFiles)
1791 FN_LOCAL_STRING(lp_hide_files, szHideFiles)
1792 FN_LOCAL_STRING(lp_veto_oplocks, szVetoOplockFiles)
1793 FN_LOCAL_BOOL(lp_msdfs_root, bMSDfsRoot)
1794 FN_LOCAL_BOOL(lp_autoloaded, autoloaded)
1795 FN_LOCAL_BOOL(lp_preexec_close, bPreexecClose)
1796 FN_LOCAL_BOOL(lp_rootpreexec_close, bRootpreexecClose)
1797 FN_LOCAL_BOOL(lp_casesensitive, bCaseSensitive)
1798 FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
1799 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
1800 FN_LOCAL_BOOL(lp_casemangle, bCaseMangle)
1801 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
1802 FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
1803 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
1804 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
1805 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
1806 FN_LOCAL_BOOL(lp_readonly, bRead_only)
1807 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
1808 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
1809 FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
1810 FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
1811 FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
1812 FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
1813 FN_LOCAL_BOOL(lp_locking, bLocking)
1814 FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
1815 FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
1816 FN_LOCAL_BOOL(lp_share_modes, bShareModes)
1817 FN_LOCAL_BOOL(lp_oplocks, bOpLocks)
1818 FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks)
1819 FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser)
1820 FN_LOCAL_BOOL(lp_manglednames, bMangledNames)
1821 FN_LOCAL_BOOL(lp_widelinks, bWidelinks)
1822 FN_LOCAL_BOOL(lp_symlinks, bSymlinks)
1823 FN_LOCAL_BOOL(lp_syncalways, bSyncAlways)
1824 FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate)
1825 FN_LOCAL_BOOL(lp_strict_sync, bStrictSync)
1826 FN_LOCAL_BOOL(lp_map_system, bMap_system)
1827 FN_LOCAL_BOOL(lp_delete_readonly, bDeleteReadonly)
1828 FN_LOCAL_BOOL(lp_fake_oplocks, bFakeOplocks)
1829 FN_LOCAL_BOOL(lp_recursive_veto_delete, bDeleteVetoFiles)
1830 FN_LOCAL_BOOL(lp_dos_filemode, bDosFilemode)
1831 FN_LOCAL_BOOL(lp_dos_filetimes, bDosFiletimes)
1832 FN_LOCAL_BOOL(lp_dos_filetime_resolution, bDosFiletimeResolution)
1833 FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes)
1834 FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks)
1835 FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms)
1836 FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
1837 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
1838 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
1839 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
1840 FN_LOCAL_BOOL(lp_use_sendfile, bUseSendfile)
1841 FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
1842 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
1843 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
1844 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
1845 FN_LOCAL_INTEGER(lp_force_security_mode, iSecurity_force_mode)
1846 FN_LOCAL_INTEGER(lp_dir_mask, iDir_mask)
1847 FN_LOCAL_INTEGER(lp_force_dir_mode, iDir_force_mode)
1848 FN_LOCAL_INTEGER(lp_dir_security_mask, iDir_Security_mask)
1849 FN_LOCAL_INTEGER(lp_force_dir_security_mode, iDir_Security_force_mode)
1850 FN_LOCAL_INTEGER(lp_max_connections, iMaxConnections)
1851 FN_LOCAL_INTEGER(lp_defaultcase, iDefaultCase)
1852 FN_LOCAL_INTEGER(lp_minprintspace, iMinPrintSpace)
1853 FN_LOCAL_INTEGER(lp_printing, iPrinting)
1854 FN_LOCAL_INTEGER(lp_max_reported_jobs, iMaxReportedPrintJobs)
1855 FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
1856 FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
1857 FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
1858 FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
1859 FN_LOCAL_CHAR(lp_magicchar, magic_char)
1860 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
1861 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
1862 FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
1863 FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
1864 FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing)
1865
1866 /* local prototypes */
1867
1868 static int map_parameter(const char *pszParmName);
1869 static BOOL set_boolean(BOOL *pb, const char *pszParmValue);
1870 static int getservicebyname(const char *pszServiceName,
1871                             service * pserviceDest);
1872 static void copy_service(service * pserviceDest,
1873                          service * pserviceSource, BOOL *pcopymapDest);
1874 static BOOL service_ok(int iService);
1875 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue);
1876 static BOOL do_section(const char *pszSectionName);
1877 static void init_copymap(service * pservice);
1878
1879 /* This is a helper function for parametrical options support. */
1880 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
1881 /* Actual parametrical functions are quite simple */
1882 static const char *get_parametrics(int lookup_service, const char *type, const char *option)
1883 {
1884         char* vfskey;
1885         param_opt_struct *data;
1886         
1887         if (lookup_service >= iNumServices) return NULL;
1888         
1889         data = (lookup_service < 0) ? 
1890                 Globals.param_opt : ServicePtrs[lookup_service]->param_opt;
1891     
1892         asprintf(&vfskey, "%s:%s", type, option);
1893         while (data) {
1894                 if (strcmp(data->key, vfskey) == 0) {
1895                         string_free(&vfskey);
1896                         return data->value;
1897                 }
1898                 data = data->next;
1899         }
1900
1901         if (lookup_service >= 0) {
1902                 /* Try to fetch the same option but from globals */
1903                 /* but only if we are not already working with Globals */
1904                 data = Globals.param_opt;
1905                 while (data) {
1906                         if (strcmp(data->key, vfskey) == 0) {
1907                                 string_free(&vfskey);
1908                                 return data->value;
1909                         }
1910                         data = data->next;
1911                 }
1912         }
1913
1914         string_free(&vfskey);
1915         
1916         return NULL;
1917 }
1918
1919
1920 /*******************************************************************
1921 convenience routine to return int parameters.
1922 ********************************************************************/
1923 static int lp_int(const char *s)
1924 {
1925
1926         if (!s) {
1927                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1928                 return (-1);
1929         }
1930
1931         return atoi(s); 
1932 }
1933
1934 /*******************************************************************
1935 convenience routine to return unsigned long parameters.
1936 ********************************************************************/
1937 static int lp_ulong(const char *s)
1938 {
1939
1940         if (!s) {
1941                 DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
1942                 return (-1);
1943         }
1944
1945         return strtoul(s, NULL, 10);
1946 }
1947
1948 /*******************************************************************
1949 convenience routine to return boolean parameters.
1950 ********************************************************************/
1951 static BOOL lp_bool(const char *s)
1952 {
1953         BOOL ret = False;
1954
1955         if (!s) {
1956                 DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
1957                 return False;
1958         }
1959         
1960         if (!set_boolean(&ret,s)) {
1961                 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
1962                 return False;
1963         }
1964
1965         return ret;
1966 }
1967
1968 /*******************************************************************
1969 convenience routine to return enum parameters.
1970 ********************************************************************/
1971 static int lp_enum(const char *s,const struct enum_list *_enum)
1972 {
1973         int i;
1974
1975         if (!s || !_enum) {
1976                 DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s));
1977                 return False;
1978         }
1979         
1980         for (i=0; _enum[i].name; i++) {
1981                 if (strcasecmp(_enum[i].name,s)==0)
1982                         return _enum[i].value;
1983         }
1984
1985         DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
1986         return (-1);
1987 }
1988
1989 /* Return parametric option from a given service. Type is a part of option before ':' */
1990 /* Parametric option has following syntax: 'Type: option = value' */
1991 /* Returned value is allocated in 'lp_talloc' context */
1992
1993 char *lp_parm_string(int lookup_service, const char *type, const char *option)
1994 {
1995         const char *value = get_parametrics(lookup_service, type, option);
1996         
1997         if (value)
1998                 return lp_string(value);
1999
2000         return NULL;
2001 }
2002
2003 /* Return parametric option from a given service. Type is a part of option before ':' */
2004 /* Parametric option has following syntax: 'Type: option = value' */
2005 /* Returned value is allocated in 'lp_talloc' context */
2006
2007 char **lp_parm_string_list(int lookup_service, const char *type, const char *option,
2008                            const char *separator)
2009 {
2010         const char *value = get_parametrics(lookup_service, type, option);
2011         
2012         if (value)
2013                 return str_list_make(value, separator);
2014
2015         return NULL;
2016 }
2017
2018 /* Return parametric option from a given service. Type is a part of option before ':' */
2019 /* Parametric option has following syntax: 'Type: option = value' */
2020
2021 int lp_parm_int(int lookup_service, const char *type, const char *option)
2022 {
2023         const char *value = get_parametrics(lookup_service, type, option);
2024         
2025         if (value)
2026                 return lp_int(value);
2027
2028         return (-1);
2029 }
2030
2031 /* Return parametric option from a given service. Type is a part of option before ':' */
2032 /* Parametric option has following syntax: 'Type: option = value' */
2033
2034 unsigned long lp_parm_ulong(int lookup_service, const char *type, const char *option)
2035 {
2036         const char *value = get_parametrics(lookup_service, type, option);
2037         
2038         if (value)
2039                 return lp_ulong(value);
2040
2041         return (0);
2042 }
2043
2044 /* Return parametric option from a given service. Type is a part of option before ':' */
2045 /* Parametric option has following syntax: 'Type: option = value' */
2046
2047 BOOL lp_parm_bool(int lookup_service, const char *type, const char *option)
2048 {
2049         const char *value = get_parametrics(lookup_service, type, option);
2050         
2051         if (value)
2052                 return lp_bool(value);
2053
2054         return False;
2055 }
2056
2057 /* Return parametric option from a given service. Type is a part of option before ':' */
2058 /* Parametric option has following syntax: 'Type: option = value' */
2059
2060 int lp_parm_enum(int lookup_service, const char *type, const char *option,
2061                  const struct enum_list *_enum)
2062 {
2063         const char *value = get_parametrics(lookup_service, type, option);
2064         
2065         if (value)
2066                 return lp_enum(value, _enum);
2067
2068         return (-1);
2069 }
2070
2071
2072 /***************************************************************************
2073  Initialise a service to the defaults.
2074 ***************************************************************************/
2075
2076 static void init_service(service * pservice)
2077 {
2078         memset((char *)pservice, '\0', sizeof(service));
2079         copy_service(pservice, &sDefault, NULL);
2080 }
2081
2082 /***************************************************************************
2083  Free the dynamically allocated parts of a service struct.
2084 ***************************************************************************/
2085
2086 static void free_service(service *pservice)
2087 {
2088         int i;
2089         param_opt_struct *data, *pdata;
2090         if (!pservice)
2091                 return;
2092
2093         if (pservice->szService)
2094                 DEBUG(5, ("free_service: Freeing service %s\n",
2095                        pservice->szService));
2096
2097         string_free(&pservice->szService);
2098         SAFE_FREE(pservice->copymap);
2099
2100         for (i = 0; parm_table[i].label; i++) {
2101                 if ((parm_table[i].type == P_STRING ||
2102                      parm_table[i].type == P_USTRING) &&
2103                     parm_table[i].class == P_LOCAL)
2104                         string_free((char **)
2105                                     (((char *)pservice) +
2106                                      PTR_DIFF(parm_table[i].ptr, &sDefault)));
2107                 else if (parm_table[i].type == P_LIST &&
2108                          parm_table[i].class == P_LOCAL)
2109                              str_list_free((char ***)
2110                                             (((char *)pservice) +
2111                                              PTR_DIFF(parm_table[i].ptr, &sDefault)));
2112         }
2113                                 
2114         DEBUG(5,("Freeing parametrics:\n"));
2115         data = pservice->param_opt;
2116         while (data) {
2117                 DEBUG(5,("[%s = %s]\n", data->key, data->value));
2118                 string_free(&data->key);
2119                 string_free(&data->value);
2120                 pdata = data->next;
2121                 SAFE_FREE(data);
2122                 data = pdata;
2123         }
2124
2125         ZERO_STRUCTP(pservice);
2126 }
2127
2128 /***************************************************************************
2129  Add a new service to the services array initialising it with the given 
2130  service. 
2131 ***************************************************************************/
2132
2133 static int add_a_service(const service *pservice, const char *name)
2134 {
2135         int i;
2136         service tservice;
2137         int num_to_alloc = iNumServices + 1;
2138         param_opt_struct *data, *pdata;
2139
2140         tservice = *pservice;
2141
2142         /* it might already exist */
2143         if (name) {
2144                 i = getservicebyname(name, NULL);
2145                 if (i >= 0) {
2146                         /* Clean all parametric options for service */
2147                         /* They will be added during parsing again */
2148                         data = ServicePtrs[i]->param_opt;
2149                         while (data) {
2150                                 string_free(&data->key);
2151                                 string_free(&data->value);
2152                                 pdata = data->next;
2153                                 SAFE_FREE(data);
2154                                 data = pdata;
2155                         }
2156                         ServicePtrs[i]->param_opt = NULL;
2157                         return (i);
2158                 }
2159         }
2160
2161         /* find an invalid one */
2162         for (i = 0; i < iNumServices; i++)
2163                 if (!ServicePtrs[i]->valid)
2164                         break;
2165
2166         /* if not, then create one */
2167         if (i == iNumServices) {
2168                 service **tsp;
2169                 
2170                 tsp = (service **) Realloc(ServicePtrs,
2171                                            sizeof(service *) *
2172                                            num_to_alloc);
2173                                            
2174                 if (!tsp) {
2175                         DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
2176                         return (-1);
2177                 }
2178                 else {
2179                         ServicePtrs = tsp;
2180                         ServicePtrs[iNumServices] =
2181                                 (service *) malloc(sizeof(service));
2182                 }
2183                 if (!ServicePtrs[iNumServices]) {
2184                         DEBUG(0,("add_a_service: out of memory!\n"));
2185                         return (-1);
2186                 }
2187
2188                 iNumServices++;
2189         } else
2190                 free_service(ServicePtrs[i]);
2191
2192         ServicePtrs[i]->valid = True;
2193
2194         init_service(ServicePtrs[i]);
2195         copy_service(ServicePtrs[i], &tservice, NULL);
2196         if (name)
2197                 string_set(&ServicePtrs[i]->szService, name);
2198         return (i);
2199 }
2200
2201 /***************************************************************************
2202  Add a new home service, with the specified home directory, defaults coming 
2203  from service ifrom.
2204 ***************************************************************************/
2205
2206 BOOL lp_add_home(const char *pszHomename, int iDefaultService, 
2207                  const char *user, const char *pszHomedir)
2208 {
2209         int i;
2210         pstring newHomedir;
2211
2212         i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
2213
2214         if (i < 0)
2215                 return (False);
2216
2217         if (!(*(ServicePtrs[iDefaultService]->szPath))
2218             || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) {
2219                 pstrcpy(newHomedir, pszHomedir);
2220         } else {
2221                 pstrcpy(newHomedir, lp_pathname(iDefaultService));
2222                 string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); 
2223         }
2224
2225         string_set(&ServicePtrs[i]->szPath, newHomedir);
2226
2227         if (!(*(ServicePtrs[i]->comment))) {
2228                 pstring comment;
2229                 slprintf(comment, sizeof(comment) - 1,
2230                          "Home directory of %s", user);
2231                 string_set(&ServicePtrs[i]->comment, comment);
2232         }
2233         ServicePtrs[i]->bAvailable = sDefault.bAvailable;
2234         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2235
2236         DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, 
2237                user, newHomedir));
2238         
2239         return (True);
2240 }
2241
2242 /***************************************************************************
2243  Add a new service, based on an old one.
2244 ***************************************************************************/
2245
2246 int lp_add_service(const char *pszService, int iDefaultService)
2247 {
2248         return (add_a_service(ServicePtrs[iDefaultService], pszService));
2249 }
2250
2251 /***************************************************************************
2252  Add the IPC service.
2253 ***************************************************************************/
2254
2255 static BOOL lp_add_ipc(const char *ipc_name, BOOL guest_ok)
2256 {
2257         pstring comment;
2258         int i = add_a_service(&sDefault, ipc_name);
2259
2260         if (i < 0)
2261                 return (False);
2262
2263         slprintf(comment, sizeof(comment) - 1,
2264                  "IPC Service (%s)", Globals.szServerString);
2265
2266         string_set(&ServicePtrs[i]->szPath, tmpdir());
2267         string_set(&ServicePtrs[i]->szUsername, "");
2268         string_set(&ServicePtrs[i]->comment, comment);
2269         string_set(&ServicePtrs[i]->fstype, "IPC");
2270         ServicePtrs[i]->iMaxConnections = 0;
2271         ServicePtrs[i]->bAvailable = True;
2272         ServicePtrs[i]->bRead_only = True;
2273         ServicePtrs[i]->bGuest_only = False;
2274         ServicePtrs[i]->bGuest_ok = guest_ok;
2275         ServicePtrs[i]->bPrint_ok = False;
2276         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2277
2278         DEBUG(3, ("adding IPC service\n"));
2279
2280         return (True);
2281 }
2282
2283 /***************************************************************************
2284  Add a new printer service, with defaults coming from service iFrom.
2285 ***************************************************************************/
2286
2287 BOOL lp_add_printer(const char *pszPrintername, int iDefaultService)
2288 {
2289         const char *comment = "From Printcap";
2290         int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
2291
2292         if (i < 0)
2293                 return (False);
2294
2295         /* note that we do NOT default the availability flag to True - */
2296         /* we take it from the default service passed. This allows all */
2297         /* dynamic printers to be disabled by disabling the [printers] */
2298         /* entry (if/when the 'available' keyword is implemented!).    */
2299
2300         /* the printer name is set to the service name. */
2301         string_set(&ServicePtrs[i]->szPrintername, pszPrintername);
2302         string_set(&ServicePtrs[i]->comment, comment);
2303         ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
2304         /* Printers cannot be read_only. */
2305         ServicePtrs[i]->bRead_only = False;
2306         /* No share modes on printer services. */
2307         ServicePtrs[i]->bShareModes = False;
2308         /* No oplocks on printer services. */
2309         ServicePtrs[i]->bOpLocks = False;
2310         /* Printer services must be printable. */
2311         ServicePtrs[i]->bPrint_ok = True;
2312
2313         DEBUG(3, ("adding printer service %s\n", pszPrintername));
2314
2315         update_server_announce_as_printserver();
2316
2317         return (True);
2318 }
2319
2320 /***************************************************************************
2321  Map a parameter's string representation to something we can use. 
2322  Returns False if the parameter string is not recognised, else TRUE.
2323 ***************************************************************************/
2324
2325 static int map_parameter(const char *pszParmName)
2326 {
2327         int iIndex;
2328
2329         if (*pszParmName == '-')
2330                 return (-1);
2331
2332         for (iIndex = 0; parm_table[iIndex].label; iIndex++)
2333                 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
2334                         return (iIndex);
2335
2336         /* Warn only if it isn't parametric option */
2337         if (strchr(pszParmName, ':') == NULL)
2338                 DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
2339         /* We do return 'fail' for parametric options as well because they are
2340            stored in different storage
2341          */
2342         return (-1);
2343 }
2344
2345 /***************************************************************************
2346  Set a boolean variable from the text value stored in the passed string.
2347  Returns True in success, False if the passed string does not correctly 
2348  represent a boolean.
2349 ***************************************************************************/
2350
2351 static BOOL set_boolean(BOOL *pb, const char *pszParmValue)
2352 {
2353         BOOL bRetval;
2354
2355         bRetval = True;
2356         if (strwicmp(pszParmValue, "yes") == 0 ||
2357             strwicmp(pszParmValue, "true") == 0 ||
2358             strwicmp(pszParmValue, "1") == 0)
2359                 *pb = True;
2360         else if (strwicmp(pszParmValue, "no") == 0 ||
2361                     strwicmp(pszParmValue, "False") == 0 ||
2362                     strwicmp(pszParmValue, "0") == 0)
2363                 *pb = False;
2364         else {
2365                 DEBUG(0,
2366                       ("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
2367                        pszParmValue));
2368                 bRetval = False;
2369         }
2370         return (bRetval);
2371 }
2372
2373 /***************************************************************************
2374 Find a service by name. Otherwise works like get_service.
2375 ***************************************************************************/
2376
2377 static int getservicebyname(const char *pszServiceName, service * pserviceDest)
2378 {
2379         int iService;
2380
2381         for (iService = iNumServices - 1; iService >= 0; iService--)
2382                 if (VALID(iService) &&
2383                     strwicmp(ServicePtrs[iService]->szService, pszServiceName) == 0) {
2384                         if (pserviceDest != NULL)
2385                                 copy_service(pserviceDest, ServicePtrs[iService], NULL);
2386                         break;
2387                 }
2388
2389         return (iService);
2390 }
2391
2392 /***************************************************************************
2393  Copy a service structure to another.
2394  If pcopymapDest is NULL then copy all fields
2395 ***************************************************************************/
2396
2397 static void copy_service(service * pserviceDest, service * pserviceSource, BOOL *pcopymapDest)
2398 {
2399         int i;
2400         BOOL bcopyall = (pcopymapDest == NULL);
2401         param_opt_struct *data, *pdata, *paramo;
2402         BOOL not_added;
2403
2404         for (i = 0; parm_table[i].label; i++)
2405                 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
2406                     (bcopyall || pcopymapDest[i])) {
2407                         void *def_ptr = parm_table[i].ptr;
2408                         void *src_ptr =
2409                                 ((char *)pserviceSource) + PTR_DIFF(def_ptr,
2410                                                                     &sDefault);
2411                         void *dest_ptr =
2412                                 ((char *)pserviceDest) + PTR_DIFF(def_ptr,
2413                                                                   &sDefault);
2414
2415                         switch (parm_table[i].type) {
2416                                 case P_BOOL:
2417                                 case P_BOOLREV:
2418                                         *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
2419                                         break;
2420
2421                                 case P_INTEGER:
2422                                 case P_ENUM:
2423                                 case P_OCTAL:
2424                                         *(int *)dest_ptr = *(int *)src_ptr;
2425                                         break;
2426
2427                                 case P_CHAR:
2428                                         *(char *)dest_ptr = *(char *)src_ptr;
2429                                         break;
2430
2431                                 case P_STRING:
2432                                         string_set(dest_ptr,
2433                                                    *(char **)src_ptr);
2434                                         break;
2435
2436                                 case P_USTRING:
2437                                         string_set(dest_ptr,
2438                                                    *(char **)src_ptr);
2439                                         strupper(*(char **)dest_ptr);
2440                                         break;
2441                                 case P_LIST:
2442                                         str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr);
2443                                         break;
2444                                 default:
2445                                         break;
2446                         }
2447                 }
2448
2449         if (bcopyall) {
2450                 init_copymap(pserviceDest);
2451                 if (pserviceSource->copymap)
2452                         memcpy((void *)pserviceDest->copymap,
2453                                (void *)pserviceSource->copymap,
2454                                sizeof(BOOL) * NUMPARAMETERS);
2455         }
2456         
2457         data = pserviceSource->param_opt;
2458         while (data) {
2459                 not_added = True;
2460                 pdata = pserviceDest->param_opt;
2461                 /* Traverse destination */
2462                 while (pdata) {
2463                         /* If we already have same option, override it */
2464                         if (strcmp(pdata->key, data->key) == 0) {
2465                                 string_free(&pdata->value);
2466                                 pdata->value = strdup(data->value);
2467                                 not_added = False;
2468                                 break;
2469                         }
2470                         pdata = pdata->next;
2471                 }
2472                 if (not_added) {
2473                     paramo = smb_xmalloc(sizeof(param_opt_struct));
2474                     paramo->key = strdup(data->key);
2475                     paramo->value = strdup(data->value);
2476                     DLIST_ADD(pserviceDest->param_opt, paramo);
2477                 }
2478                 data = data->next;
2479         }
2480 }
2481
2482 /***************************************************************************
2483 Check a service for consistency. Return False if the service is in any way
2484 incomplete or faulty, else True.
2485 ***************************************************************************/
2486
2487 static BOOL service_ok(int iService)
2488 {
2489         BOOL bRetval;
2490
2491         bRetval = True;
2492         if (ServicePtrs[iService]->szService[0] == '\0') {
2493                 DEBUG(0, ("The following message indicates an internal error:\n"));
2494                 DEBUG(0, ("No service name in service entry.\n"));
2495                 bRetval = False;
2496         }
2497
2498         /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2499         /* I can't see why you'd want a non-printable printer service...        */
2500         if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
2501                 if (!ServicePtrs[iService]->bPrint_ok) {
2502                         DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2503                                ServicePtrs[iService]->szService));
2504                         ServicePtrs[iService]->bPrint_ok = True;
2505                 }
2506                 /* [printers] service must also be non-browsable. */
2507                 if (ServicePtrs[iService]->bBrowseable)
2508                         ServicePtrs[iService]->bBrowseable = False;
2509         }
2510
2511         if (ServicePtrs[iService]->szPath[0] == '\0' &&
2512             strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0) {
2513                 DEBUG(0, ("No path in service %s - using %s\n",
2514                        ServicePtrs[iService]->szService, tmpdir()));
2515                 string_set(&ServicePtrs[iService]->szPath, tmpdir());
2516         }
2517
2518         /* If a service is flagged unavailable, log the fact at level 0. */
2519         if (!ServicePtrs[iService]->bAvailable)
2520                 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2521                           ServicePtrs[iService]->szService));
2522
2523         return (bRetval);
2524 }
2525
2526 static struct file_lists {
2527         struct file_lists *next;
2528         char *name;
2529         char *subfname;
2530         time_t modtime;
2531 } *file_lists = NULL;
2532
2533 /*******************************************************************
2534  Keep a linked list of all config files so we know when one has changed 
2535  it's date and needs to be reloaded.
2536 ********************************************************************/
2537
2538 static void add_to_file_list(const char *fname, const char *subfname)
2539 {
2540         struct file_lists *f = file_lists;
2541
2542         while (f) {
2543                 if (f->name && !strcmp(f->name, fname))
2544                         break;
2545                 f = f->next;
2546         }
2547
2548         if (!f) {
2549                 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
2550                 if (!f)
2551                         return;
2552                 f->next = file_lists;
2553                 f->name = strdup(fname);
2554                 if (!f->name) {
2555                         SAFE_FREE(f);
2556                         return;
2557                 }
2558                 f->subfname = strdup(subfname);
2559                 if (!f->subfname) {
2560                         SAFE_FREE(f);
2561                         return;
2562                 }
2563                 file_lists = f;
2564                 f->modtime = file_modtime(subfname);
2565         } else {
2566                 time_t t = file_modtime(subfname);
2567                 if (t)
2568                         f->modtime = t;
2569         }
2570 }
2571
2572 /*******************************************************************
2573  Check if a config file has changed date.
2574 ********************************************************************/
2575
2576 BOOL lp_file_list_changed(void)
2577 {
2578         struct file_lists *f = file_lists;
2579         DEBUG(6, ("lp_file_list_changed()\n"));
2580
2581         while (f) {
2582                 pstring n2;
2583                 time_t mod_time;
2584
2585                 pstrcpy(n2, f->name);
2586                 standard_sub_basic(current_user_info.smb_name, n2,sizeof(n2));
2587
2588                 DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
2589                              f->name, n2, ctime(&f->modtime)));
2590
2591                 mod_time = file_modtime(n2);
2592
2593                 if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
2594                         DEBUGADD(6,
2595                                  ("file %s modified: %s\n", n2,
2596                                   ctime(&mod_time)));
2597                         f->modtime = mod_time;
2598                         SAFE_FREE(f->subfname);
2599                         f->subfname = strdup(n2);
2600                         return (True);
2601                 }
2602                 f = f->next;
2603         }
2604         return (False);
2605 }
2606
2607 /***************************************************************************
2608  Run standard_sub_basic on netbios name... needed because global_myname
2609  is not accessed through any lp_ macro.
2610  Note: We must *NOT* use string_set() here as ptr points to global_myname.
2611 ***************************************************************************/
2612
2613 static BOOL handle_netbios_name(const char *pszParmValue, char **ptr)
2614 {
2615         BOOL ret;
2616         pstring netbios_name;
2617
2618         pstrcpy(netbios_name, pszParmValue);
2619
2620         standard_sub_basic(current_user_info.smb_name, netbios_name,sizeof(netbios_name));
2621
2622
2623         ret = set_global_myname(netbios_name);
2624         string_set(&Globals.szNetbiosName,global_myname());
2625         
2626         DEBUG(4, ("handle_netbios_name: set global_myname to: %s\n",
2627                global_myname()));
2628
2629         return ret;
2630 }
2631
2632 static BOOL handle_workgroup(const char *pszParmValue, char **ptr)
2633 {
2634         BOOL ret;
2635         
2636         ret = set_global_myworkgroup(pszParmValue);
2637         string_set(&Globals.szWorkgroup,lp_workgroup());
2638         
2639         return ret;
2640 }
2641
2642 static BOOL handle_netbios_scope(const char *pszParmValue, char **ptr)
2643 {
2644         BOOL ret;
2645         
2646         ret = set_global_scope(pszParmValue);
2647         string_set(&Globals.szNetbiosScope,global_scope());
2648
2649         return ret;
2650 }
2651
2652 static BOOL handle_netbios_aliases(const char *pszParmValue, char **ptr)
2653 {
2654         Globals.szNetbiosAliases = str_list_make(pszParmValue, NULL);
2655         return set_netbios_aliases((const char **)Globals.szNetbiosAliases);
2656 }
2657
2658 /***************************************************************************
2659  Do the work of sourcing in environment variable/value pairs.
2660 ***************************************************************************/
2661
2662 static BOOL source_env(char **lines)
2663 {
2664         char *varval;
2665         size_t len;
2666         int i;
2667         char *p;
2668
2669         for (i = 0; lines[i]; i++) {
2670                 char *line = lines[i];
2671
2672                 if ((len = strlen(line)) == 0)
2673                         continue;
2674
2675                 if (line[len - 1] == '\n')
2676                         line[--len] = '\0';
2677
2678                 if ((varval = malloc(len + 1)) == NULL) {
2679                         DEBUG(0, ("source_env: Not enough memory!\n"));
2680                         return (False);
2681                 }
2682
2683                 DEBUG(4, ("source_env: Adding to environment: %s\n", line));
2684                 strncpy(varval, line, len);
2685                 varval[len] = '\0';
2686
2687                 p = strchr_m(line, (int)'=');
2688                 if (p == NULL) {
2689                         DEBUG(4, ("source_env: missing '=': %s\n", line));
2690                         continue;
2691                 }
2692
2693                 if (putenv(varval)) {
2694                         DEBUG(0, ("source_env: Failed to put environment variable %s\n",
2695                                varval));
2696                         continue;
2697                 }
2698
2699                 *p = '\0';
2700                 p++;
2701                 DEBUG(4, ("source_env: getting var %s = %s\n", line, getenv(line)));
2702         }
2703
2704         DEBUG(4, ("source_env: returning successfully\n"));
2705         return (True);
2706 }
2707
2708 /***************************************************************************
2709  Handle the source environment operation.
2710 ***************************************************************************/
2711
2712 static BOOL handle_source_env(const char *pszParmValue, char **ptr)
2713 {
2714         pstring fname;
2715         char *p = fname;
2716         BOOL result;
2717         char **lines;
2718
2719         pstrcpy(fname, pszParmValue);
2720
2721         standard_sub_basic(current_user_info.smb_name, fname,sizeof(fname));
2722
2723         string_set(ptr, pszParmValue);
2724
2725         DEBUG(4, ("handle_source_env: checking env type\n"));
2726
2727         /*
2728          * Filename starting with '|' means popen and read from stdin.
2729          */
2730
2731         if (*p == '|')
2732                 lines = file_lines_pload(p + 1, NULL);
2733         else
2734                 lines = file_lines_load(fname, NULL);
2735
2736         if (!lines) {
2737                 DEBUG(0, ("handle_source_env: Failed to open file %s, Error was %s\n",
2738                        fname, strerror(errno)));
2739                 return (False);
2740         }
2741
2742         result = source_env(lines);
2743         file_lines_free(lines);
2744
2745         return (result);
2746 }
2747
2748 /***************************************************************************
2749  Handle the include operation.
2750 ***************************************************************************/
2751
2752 static BOOL handle_include(const char *pszParmValue, char **ptr)
2753 {
2754         pstring fname;
2755         pstrcpy(fname, pszParmValue);
2756
2757         standard_sub_basic(current_user_info.smb_name, fname,sizeof(fname));
2758
2759         add_to_file_list(pszParmValue, fname);
2760
2761         string_set(ptr, fname);
2762
2763         if (file_exist(fname, NULL))
2764                 return (pm_process(fname, do_section, do_parameter));
2765
2766         DEBUG(2, ("Can't find include file %s\n", fname));
2767
2768         return (False);
2769 }
2770
2771 /***************************************************************************
2772  Handle the interpretation of the copy parameter.
2773 ***************************************************************************/
2774
2775 static BOOL handle_copy(const char *pszParmValue, char **ptr)
2776 {
2777         BOOL bRetval;
2778         int iTemp;
2779         service serviceTemp;
2780
2781         string_set(ptr, pszParmValue);
2782
2783         init_service(&serviceTemp);
2784
2785         bRetval = False;
2786
2787         DEBUG(3, ("Copying service from service %s\n", pszParmValue));
2788
2789         if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) {
2790                 if (iTemp == iServiceIndex) {
2791                         DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
2792                 } else {
2793                         copy_service(ServicePtrs[iServiceIndex],
2794                                      &serviceTemp,
2795                                      ServicePtrs[iServiceIndex]->copymap);
2796                         bRetval = True;
2797                 }
2798         } else {
2799                 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue));
2800                 bRetval = False;
2801         }
2802
2803         free_service(&serviceTemp);
2804         return (bRetval);
2805 }
2806
2807 /***************************************************************************
2808  Handle winbind/non unix account uid and gid allocation parameters.  The format of these
2809  parameters is:
2810
2811  [global]
2812
2813         winbind uid = 1000-1999
2814         winbind gid = 700-899
2815
2816  We only do simple parsing checks here.  The strings are parsed into useful
2817  structures in the winbind daemon code.
2818
2819 ***************************************************************************/
2820
2821 /* Some lp_ routines to return winbind [ug]id information */
2822
2823 static uid_t winbind_uid_low, winbind_uid_high;
2824 static gid_t winbind_gid_low, winbind_gid_high;
2825 static uint32 non_unix_account_low, non_unix_account_high;
2826
2827 BOOL lp_winbind_uid(uid_t *low, uid_t *high)
2828 {
2829         if (winbind_uid_low == 0 || winbind_uid_high == 0)
2830                 return False;
2831
2832         if (low)
2833                 *low = winbind_uid_low;
2834
2835         if (high)
2836                 *high = winbind_uid_high;
2837
2838         return True;
2839 }
2840
2841 BOOL lp_winbind_gid(gid_t *low, gid_t *high)
2842 {
2843         if (winbind_gid_low == 0 || winbind_gid_high == 0)
2844                 return False;
2845
2846         if (low)
2847                 *low = winbind_gid_low;
2848
2849         if (high)
2850                 *high = winbind_gid_high;
2851
2852         return True;
2853 }
2854
2855 BOOL lp_non_unix_account_range(uint32 *low, uint32 *high)
2856 {
2857         if (non_unix_account_low == 0 || non_unix_account_high == 0)
2858                 return False;
2859
2860         if (low)
2861                 *low = non_unix_account_low;
2862
2863         if (high)
2864                 *high = non_unix_account_high;
2865
2866         return True;
2867 }
2868
2869 /* Do some simple checks on "winbind [ug]id" parameter values */
2870
2871 static BOOL handle_winbind_uid(const char *pszParmValue, char **ptr)
2872 {
2873         uint32 low, high;
2874
2875         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2876                 return False;
2877
2878         /* Parse OK */
2879
2880         string_set(ptr, pszParmValue);
2881
2882         winbind_uid_low = low;
2883         winbind_uid_high = high;
2884
2885         return True;
2886 }
2887
2888 static BOOL handle_winbind_gid(const char *pszParmValue, char **ptr)
2889 {
2890         uint32 low, high;
2891
2892         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2893                 return False;
2894
2895         /* Parse OK */
2896
2897         string_set(ptr, pszParmValue);
2898
2899         winbind_gid_low = low;
2900         winbind_gid_high = high;
2901
2902         return True;
2903 }
2904
2905 /***************************************************************************
2906  Do some simple checks on "non unix account range" parameter values.
2907 ***************************************************************************/
2908
2909 static BOOL handle_non_unix_account_range(const char *pszParmValue, char **ptr)
2910 {
2911         uint32 low, high;
2912
2913         if (sscanf(pszParmValue, "%u-%u", &low, &high) != 2 || high < low)
2914                 return False;
2915
2916         /* Parse OK */
2917
2918         string_set(ptr, pszParmValue);
2919
2920         non_unix_account_low = low;
2921         non_unix_account_high = high;
2922
2923         return True;
2924 }
2925
2926 /***************************************************************************
2927  Handle the DEBUG level list.
2928 ***************************************************************************/
2929
2930 static BOOL handle_debug_list( const char *pszParmValueIn, char **ptr )
2931 {
2932         pstring pszParmValue;
2933
2934         pstrcpy(pszParmValue, pszParmValueIn);
2935         string_set(ptr, pszParmValueIn);
2936         return debug_parse_levels( pszParmValue );
2937 }
2938
2939 /***************************************************************************
2940  Handle the ldap machine suffix option.
2941 ***************************************************************************/
2942
2943 static BOOL handle_ldap_machine_suffix( const char *pszParmValue, char **ptr)
2944 {
2945        pstring suffix;
2946        
2947        pstrcpy(suffix, pszParmValue);
2948
2949        if (! *Globals.szLdapSuffix ) {
2950                string_set( ptr, suffix );
2951                return True;
2952        }
2953
2954        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2955                if ( *pszParmValue )
2956                        pstrcat(suffix, ",");
2957                pstrcat(suffix, Globals.szLdapSuffix);
2958        }
2959        string_set( ptr, suffix );
2960        return True;
2961 }
2962
2963 /***************************************************************************
2964  Handle the ldap user suffix option.
2965 ***************************************************************************/
2966
2967 static BOOL handle_ldap_user_suffix( const char *pszParmValue, char **ptr)
2968 {
2969        pstring suffix;
2970        
2971        pstrcpy(suffix, pszParmValue);
2972
2973        if (! *Globals.szLdapSuffix ) {
2974                string_set( ptr, suffix );
2975                return True;
2976        }
2977        
2978        if (! strstr(suffix, Globals.szLdapSuffix) ) {
2979                if ( *pszParmValue )
2980                        pstrcat(suffix, ",");
2981                pstrcat(suffix, Globals.szLdapSuffix);
2982        }
2983        string_set( ptr, suffix );
2984        return True;
2985 }
2986
2987 /***************************************************************************
2988  Handle setting ldap suffix and determines whether ldap machine suffix needs
2989  to be set as well.
2990 ***************************************************************************/
2991
2992 static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr)
2993 {
2994        pstring suffix;
2995        pstring user_suffix;
2996        pstring machine_suffix;
2997                
2998        pstrcpy(suffix, pszParmValue);
2999
3000        if (! *Globals.szLdapMachineSuffix )
3001                string_set(&Globals.szLdapMachineSuffix, suffix);
3002        if (! *Globals.szLdapUserSuffix ) 
3003                string_set(&Globals.szLdapUserSuffix, suffix);
3004        
3005        if (! strstr(Globals.szLdapMachineSuffix, suffix)) {
3006                pstrcpy(machine_suffix, Globals.szLdapMachineSuffix);
3007                if ( *Globals.szLdapMachineSuffix )
3008                        pstrcat(machine_suffix, ",");
3009                pstrcat(machine_suffix, suffix);
3010                string_set(&Globals.szLdapMachineSuffix, machine_suffix);       
3011        }
3012
3013        if (! strstr(Globals.szLdapUserSuffix, suffix)) {
3014                pstrcpy(user_suffix, Globals.szLdapUserSuffix);
3015                if ( *Globals.szLdapUserSuffix )
3016                        pstrcat(user_suffix, ",");
3017                pstrcat(user_suffix, suffix);   
3018                string_set(&Globals.szLdapUserSuffix, user_suffix);
3019        } 
3020
3021        string_set(ptr, suffix); 
3022        return True;
3023 }
3024
3025 static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr)
3026 {
3027         if (strequal(pszParmValue, "auto"))
3028                 string_set(ptr, "");
3029         else if (strequal(pszParmValue, "winnt"))
3030                 string_set(ptr, "winnt");
3031         else if (strequal(pszParmValue, "win2k"))
3032                 string_set(ptr, "win2k");
3033         else
3034                 return False;
3035
3036         return True;
3037 }
3038 /***************************************************************************
3039  Initialise a copymap.
3040 ***************************************************************************/
3041
3042 static void init_copymap(service * pservice)
3043 {
3044         int i;
3045         SAFE_FREE(pservice->copymap);
3046         pservice->copymap = (BOOL *)malloc(sizeof(BOOL) * NUMPARAMETERS);
3047         if (!pservice->copymap)
3048                 DEBUG(0,
3049                       ("Couldn't allocate copymap!! (size %d)\n",
3050                        (int)NUMPARAMETERS));
3051         else
3052                 for (i = 0; i < NUMPARAMETERS; i++)
3053                         pservice->copymap[i] = True;
3054 }
3055
3056 /***************************************************************************
3057  Return the local pointer to a parameter given the service number and the 
3058  pointer into the default structure.
3059 ***************************************************************************/
3060
3061 void *lp_local_ptr(int snum, void *ptr)
3062 {
3063         return (void *)(((char *)ServicePtrs[snum]) + PTR_DIFF(ptr, &sDefault));
3064 }
3065
3066 /***************************************************************************
3067  Process a parameter for a particular service number. If snum < 0
3068  then assume we are in the globals.
3069 ***************************************************************************/
3070
3071 BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
3072 {
3073         int parmnum, i, slen;
3074         void *parm_ptr = NULL;  /* where we are going to store the result */
3075         void *def_ptr = NULL;
3076         pstring vfskey;
3077         char *sep;
3078         param_opt_struct *paramo, *data;
3079         BOOL not_added;
3080
3081         parmnum = map_parameter(pszParmName);
3082
3083         if (parmnum < 0) {
3084                 if ((sep=strchr(pszParmName, ':')) != NULL) {
3085                         *sep = 0;
3086                         ZERO_STRUCT(vfskey);
3087                         pstr_sprintf(vfskey, "%s:", pszParmName);
3088                         slen = strlen(vfskey);
3089                         pstrcat(vfskey, sep+1);
3090                         trim_string(vfskey+slen, " ", " ");
3091                         not_added = True;
3092                         data = (snum < 0) ? Globals.param_opt : 
3093                                 ServicePtrs[snum]->param_opt;
3094                         /* Traverse destination */
3095                         while (data) {
3096                                 /* If we already have same option, override it */
3097                                 if (strcmp(data->key, vfskey) == 0) {
3098                                         string_free(&data->value);
3099                                         data->value = strdup(pszParmValue);
3100                                         not_added = False;
3101                                         break;
3102                                 }
3103                                 data = data->next;
3104                         }
3105                         if (not_added) {
3106                                 paramo = smb_xmalloc(sizeof(param_opt_struct));
3107                                 paramo->key = strdup(vfskey);
3108                                 paramo->value = strdup(pszParmValue);
3109                                 if (snum < 0) {
3110                                         DLIST_ADD(Globals.param_opt, paramo);
3111                                 } else {
3112                                         DLIST_ADD(ServicePtrs[snum]->param_opt, paramo);
3113                                 }
3114                         }
3115
3116                         *sep = ':';
3117                         return (True);
3118                 }
3119                 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
3120                 return (True);
3121         }
3122
3123         if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
3124                 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3125                           pszParmName));
3126         }
3127
3128         def_ptr = parm_table[parmnum].ptr;
3129
3130         /* we might point at a service, the default service or a global */
3131         if (snum < 0) {
3132                 parm_ptr = def_ptr;
3133         } else {
3134                 if (parm_table[parmnum].class == P_GLOBAL) {
3135                         DEBUG(0,
3136                               ("Global parameter %s found in service section!\n",
3137                                pszParmName));
3138                         return (True);
3139                 }
3140                 parm_ptr =
3141                         ((char *)ServicePtrs[snum]) + PTR_DIFF(def_ptr,
3142                                                             &sDefault);
3143         }
3144
3145         if (snum >= 0) {
3146                 if (!ServicePtrs[snum]->copymap)
3147                         init_copymap(ServicePtrs[snum]);
3148
3149                 /* this handles the aliases - set the copymap for other entries with
3150                    the same data pointer */
3151                 for (i = 0; parm_table[i].label; i++)
3152                         if (parm_table[i].ptr == parm_table[parmnum].ptr)
3153                                 ServicePtrs[snum]->copymap[i] = False;
3154         }
3155
3156         /* if it is a special case then go ahead */
3157         if (parm_table[parmnum].special) {
3158                 parm_table[parmnum].special(pszParmValue, (char **)parm_ptr);
3159                 return (True);
3160         }
3161
3162         /* now switch on the type of variable it is */
3163         switch (parm_table[parmnum].type)
3164         {
3165                 case P_BOOL:
3166                         set_boolean(parm_ptr, pszParmValue);
3167                         break;
3168
3169                 case P_BOOLREV:
3170                         set_boolean(parm_ptr, pszParmValue);
3171                         *(BOOL *)parm_ptr = !*(BOOL *)parm_ptr;
3172                         break;
3173
3174                 case P_INTEGER:
3175                         *(int *)parm_ptr = atoi(pszParmValue);
3176                         break;
3177
3178                 case P_CHAR:
3179                         *(char *)parm_ptr = *pszParmValue;
3180                         break;
3181
3182                 case P_OCTAL:
3183                         sscanf(pszParmValue, "%o", (int *)parm_ptr);
3184                         break;
3185
3186                 case P_LIST:
3187                         str_list_free(parm_ptr);
3188                         *(char ***)parm_ptr = str_list_make(pszParmValue, NULL);
3189                         break;
3190
3191                 case P_STRING:
3192                         string_set(parm_ptr, pszParmValue);
3193                         break;
3194
3195                 case P_USTRING:
3196                         string_set(parm_ptr, pszParmValue);
3197                         strupper(*(char **)parm_ptr);
3198                         break;
3199
3200                 case P_GSTRING:
3201                         pstrcpy((char *)parm_ptr, pszParmValue);
3202                         break;
3203
3204                 case P_UGSTRING:
3205                         pstrcpy((char *)parm_ptr, pszParmValue);
3206                         strupper((char *)parm_ptr);
3207                         break;
3208
3209                 case P_ENUM:
3210                         for (i = 0; parm_table[parmnum].enum_list[i].name; i++) {
3211                                 if (strequal
3212                                     (pszParmValue,
3213                                      parm_table[parmnum].enum_list[i].name)) {
3214                                         *(int *)parm_ptr =
3215                                                 parm_table[parmnum].
3216                                                 enum_list[i].value;
3217                                         break;
3218                                 }
3219                         }
3220                         break;
3221                 case P_SEP:
3222                         break;
3223         }
3224
3225         return (True);
3226 }
3227
3228 /***************************************************************************
3229  Process a parameter.
3230 ***************************************************************************/
3231
3232 static BOOL do_parameter(const char *pszParmName, const char *pszParmValue)
3233 {
3234         if (!bInGlobalSection && bGlobalOnly)
3235                 return (True);
3236
3237         DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
3238
3239         return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
3240                                 pszParmName, pszParmValue));
3241 }
3242
3243 /***************************************************************************
3244  Print a parameter of the specified type.
3245 ***************************************************************************/
3246
3247 static void print_parameter(struct parm_struct *p, void *ptr, FILE * f)
3248 {
3249         int i;
3250         switch (p->type)
3251         {
3252                 case P_ENUM:
3253                         for (i = 0; p->enum_list[i].name; i++) {
3254                                 if (*(int *)ptr == p->enum_list[i].value) {
3255                                         fprintf(f, "%s",
3256                                                 p->enum_list[i].name);
3257                                         break;
3258                                 }
3259                         }
3260                         break;
3261
3262                 case P_BOOL:
3263                         fprintf(f, "%s", BOOLSTR(*(BOOL *)ptr));
3264                         break;
3265
3266                 case P_BOOLREV:
3267                         fprintf(f, "%s", BOOLSTR(!*(BOOL *)ptr));
3268                         break;
3269
3270                 case P_INTEGER:
3271                         fprintf(f, "%d", *(int *)ptr);
3272                         break;
3273
3274                 case P_CHAR:
3275                         fprintf(f, "%c", *(char *)ptr);
3276                         break;
3277
3278                 case P_OCTAL:
3279                         fprintf(f, "%s", octal_string(*(int *)ptr));
3280                         break;
3281
3282                 case P_LIST:
3283                         if ((char ***)ptr && *(char ***)ptr) {
3284                                 char **list = *(char ***)ptr;
3285                                 
3286                                 for (; *list; list++)
3287                                         fprintf(f, "%s%s", *list,
3288                                                 ((*(list+1))?", ":""));
3289                         }
3290                         break;
3291
3292                 case P_GSTRING:
3293                 case P_UGSTRING:
3294                         if ((char *)ptr) {
3295                                 fprintf(f, "%s", (char *)ptr);
3296                         }
3297                         break;
3298
3299                 case P_STRING:
3300                 case P_USTRING:
3301                         if (*(char **)ptr) {
3302                                 fprintf(f, "%s", *(char **)ptr);
3303                         }
3304                         break;
3305                 case P_SEP:
3306                         break;
3307         }
3308 }
3309
3310 /***************************************************************************
3311  Check if two parameters are equal.
3312 ***************************************************************************/
3313
3314 static BOOL equal_parameter(parm_type type, void *ptr1, void *ptr2)
3315 {
3316         switch (type) {
3317                 case P_BOOL:
3318                 case P_BOOLREV:
3319                         return (*((BOOL *)ptr1) == *((BOOL *)ptr2));
3320
3321                 case P_INTEGER:
3322                 case P_ENUM:
3323                 case P_OCTAL:
3324                         return (*((int *)ptr1) == *((int *)ptr2));
3325
3326                 case P_CHAR:
3327                         return (*((char *)ptr1) == *((char *)ptr2));
3328                 
3329                 case P_LIST:
3330                         return str_list_compare(*(char ***)ptr1, *(char ***)ptr2);
3331
3332                 case P_GSTRING:
3333                 case P_UGSTRING:
3334                 {
3335                         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
3336                         if (p1 && !*p1)
3337                                 p1 = NULL;
3338                         if (p2 && !*p2)
3339                                 p2 = NULL;
3340                         return (p1 == p2 || strequal(p1, p2));
3341                 }
3342                 case P_STRING:
3343                 case P_USTRING:
3344                 {
3345                         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
3346                         if (p1 && !*p1)
3347                                 p1 = NULL;
3348                         if (p2 && !*p2)
3349                                 p2 = NULL;
3350                         return (p1 == p2 || strequal(p1, p2));
3351                 }
3352                 case P_SEP:
3353                         break;
3354         }
3355         return (False);
3356 }
3357
3358 /***************************************************************************
3359  Initialize any local varients in the sDefault table.
3360 ***************************************************************************/
3361
3362 void init_locals(void)
3363 {
3364         /* None as yet. */
3365 }
3366
3367 /***************************************************************************
3368  Process a new section (service). At this stage all sections are services.
3369  Later we'll have special sections that permit server parameters to be set.
3370  Returns True on success, False on failure. 
3371 ***************************************************************************/
3372
3373 static BOOL do_section(const char *pszSectionName)
3374 {
3375         BOOL bRetval;
3376         BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
3377                          (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
3378         bRetval = False;
3379
3380         /* if we were in a global section then do the local inits */
3381         if (bInGlobalSection && !isglobal)
3382                 init_locals();
3383
3384         /* if we've just struck a global section, note the fact. */
3385         bInGlobalSection = isglobal;
3386
3387         /* check for multiple global sections */
3388         if (bInGlobalSection) {
3389                 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
3390                 return (True);
3391         }
3392
3393         if (!bInGlobalSection && bGlobalOnly)
3394                 return (True);
3395
3396         /* if we have a current service, tidy it up before moving on */
3397         bRetval = True;
3398
3399         if (iServiceIndex >= 0)
3400                 bRetval = service_ok(iServiceIndex);
3401
3402         /* if all is still well, move to the next record in the services array */
3403         if (bRetval) {
3404                 /* We put this here to avoid an odd message order if messages are */
3405                 /* issued by the post-processing of a previous section. */
3406                 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
3407
3408                 if ((iServiceIndex = add_a_service(&sDefault, pszSectionName))
3409                     < 0) {
3410                         DEBUG(0, ("Failed to add a new service\n"));
3411                         return (False);
3412                 }
3413         }
3414
3415         return (bRetval);
3416 }
3417
3418
3419 /***************************************************************************
3420  Determine if a partcular base parameter is currentl set to the default value.
3421 ***************************************************************************/
3422
3423 static BOOL is_default(int i)
3424 {
3425         if (!defaults_saved)
3426                 return False;
3427         switch (parm_table[i].type) {
3428                 case P_LIST:
3429                         return str_list_compare (parm_table[i].def.lvalue, 
3430                                                 *(char ***)parm_table[i].ptr);
3431                 case P_STRING:
3432                 case P_USTRING:
3433                         return strequal(parm_table[i].def.svalue,
3434                                         *(char **)parm_table[i].ptr);
3435                 case P_GSTRING:
3436                 case P_UGSTRING:
3437                         return strequal(parm_table[i].def.svalue,
3438                                         (char *)parm_table[i].ptr);
3439                 case P_BOOL:
3440                 case P_BOOLREV:
3441                         return parm_table[i].def.bvalue ==
3442                                 *(BOOL *)parm_table[i].ptr;
3443                 case P_CHAR:
3444                         return parm_table[i].def.cvalue ==
3445                                 *(char *)parm_table[i].ptr;
3446                 case P_INTEGER:
3447                 case P_OCTAL:
3448                 case P_ENUM:
3449                         return parm_table[i].def.ivalue ==
3450                                 *(int *)parm_table[i].ptr;
3451                 case P_SEP:
3452                         break;
3453         }
3454         return False;
3455 }
3456
3457 /***************************************************************************
3458 Display the contents of the global structure.
3459 ***************************************************************************/
3460
3461 static void dump_globals(FILE *f)
3462 {
3463         int i;
3464         param_opt_struct *data;
3465         
3466         fprintf(f, "# Global parameters\n[global]\n");
3467
3468         for (i = 0; parm_table[i].label; i++)
3469                 if (parm_table[i].class == P_GLOBAL &&
3470                     parm_table[i].ptr &&
3471                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3472                         if (defaults_saved && is_default(i))
3473                                 continue;
3474                         fprintf(f, "\t%s = ", parm_table[i].label);
3475                         print_parameter(&parm_table[i], parm_table[i].ptr, f);
3476                         fprintf(f, "\n");
3477         }
3478         if (Globals.param_opt != NULL) {
3479                 data = Globals.param_opt;
3480                 while(data) {
3481                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3482                         data = data->next;
3483                 }
3484         }
3485
3486 }
3487
3488 /***************************************************************************
3489  Return True if a local parameter is currently set to the global default.
3490 ***************************************************************************/
3491
3492 BOOL lp_is_default(int snum, struct parm_struct *parm)
3493 {
3494         int pdiff = PTR_DIFF(parm->ptr, &sDefault);
3495
3496         return equal_parameter(parm->type,
3497                                ((char *)ServicePtrs[snum]) + pdiff,
3498                                ((char *)&sDefault) + pdiff);
3499 }
3500
3501 /***************************************************************************
3502  Display the contents of a single services record.
3503 ***************************************************************************/
3504
3505 static void dump_a_service(service * pService, FILE * f)
3506 {
3507         int i;
3508         param_opt_struct *data;
3509         
3510         if (pService != &sDefault)
3511                 fprintf(f, "\n[%s]\n", pService->szService);
3512
3513         for (i = 0; parm_table[i].label; i++)
3514                 if (parm_table[i].class == P_LOCAL &&
3515                     parm_table[i].ptr &&
3516                     (*parm_table[i].label != '-') &&
3517                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) {
3518                         int pdiff = PTR_DIFF(parm_table[i].ptr, &sDefault);
3519
3520                         if (pService == &sDefault) {
3521                                 if (defaults_saved && is_default(i))
3522                                         continue;
3523                         } else {
3524                                 if (equal_parameter(parm_table[i].type,
3525                                                     ((char *)pService) +
3526                                                     pdiff,
3527                                                     ((char *)&sDefault) +
3528                                                     pdiff))
3529                                         continue;
3530                         }
3531
3532                         fprintf(f, "\t%s = ", parm_table[i].label);
3533                         print_parameter(&parm_table[i],
3534                                         ((char *)pService) + pdiff, f);
3535                         fprintf(f, "\n");
3536         }
3537         if (pService->param_opt != NULL) {
3538                 data = pService->param_opt;
3539                 while(data) {
3540                         fprintf(f, "\t%s = %s\n", data->key, data->value);
3541                         data = data->next;
3542                 }
3543         }
3544 }
3545
3546
3547 /***************************************************************************
3548  Return info about the next service  in a service. snum==-1 gives the globals.
3549  Return NULL when out of parameters.
3550 ***************************************************************************/
3551
3552 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
3553 {
3554         if (snum == -1) {
3555                 /* do the globals */
3556                 for (; parm_table[*i].label; (*i)++) {
3557                         if (parm_table[*i].class == P_SEPARATOR)
3558                                 return &parm_table[(*i)++];
3559
3560                         if (!parm_table[*i].ptr
3561                             || (*parm_table[*i].label == '-'))
3562                                 continue;
3563
3564                         if ((*i) > 0
3565                             && (parm_table[*i].ptr ==
3566                                 parm_table[(*i) - 1].ptr))
3567                                 continue;
3568
3569                         return &parm_table[(*i)++];
3570                 }
3571         } else {
3572                 service *pService = ServicePtrs[snum];
3573
3574                 for (; parm_table[*i].label; (*i)++) {
3575                         if (parm_table[*i].class == P_SEPARATOR)
3576                                 return &parm_table[(*i)++];
3577
3578                         if (parm_table[*i].class == P_LOCAL &&
3579                             parm_table[*i].ptr &&
3580                             (*parm_table[*i].label != '-') &&
3581                             ((*i) == 0 ||
3582                              (parm_table[*i].ptr !=
3583                               parm_table[(*i) - 1].ptr)))
3584                         {
3585                                 int pdiff =
3586                                         PTR_DIFF(parm_table[*i].ptr,
3587                                                  &sDefault);
3588
3589                                 if (allparameters ||
3590                                     !equal_parameter(parm_table[*i].type,
3591                                                      ((char *)pService) +
3592                                                      pdiff,
3593                                                      ((char *)&sDefault) +
3594                                                      pdiff))
3595                                 {
3596                                         return &parm_table[(*i)++];
3597                                 }
3598                         }
3599                 }
3600         }
3601
3602         return NULL;
3603 }
3604
3605
3606 #if 0
3607 /***************************************************************************
3608  Display the contents of a single copy structure.
3609 ***************************************************************************/
3610 static void dump_copy_map(BOOL *pcopymap)
3611 {
3612         int i;
3613         if (!pcopymap)
3614                 return;
3615
3616         printf("\n\tNon-Copied parameters:\n");
3617
3618         for (i = 0; parm_table[i].label; i++)
3619                 if (parm_table[i].class == P_LOCAL &&
3620                     parm_table[i].ptr && !pcopymap[i] &&
3621                     (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
3622                 {
3623                         printf("\t\t%s\n", parm_table[i].label);
3624                 }
3625 }
3626 #endif
3627
3628 /***************************************************************************
3629  Return TRUE if the passed service number is within range.
3630 ***************************************************************************/
3631
3632 BOOL lp_snum_ok(int iService)
3633 {
3634         return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
3635 }
3636
3637 /***************************************************************************
3638  Auto-load some home services.
3639 ***************************************************************************/
3640
3641 static void lp_add_auto_services(char *str)
3642 {
3643         char *s;
3644         char *p;
3645         int homes;
3646
3647         if (!str)
3648                 return;
3649
3650         s = strdup(str);
3651         if (!s)
3652                 return;
3653
3654         homes = lp_servicenumber(HOMES_NAME);
3655
3656         for (p = strtok(s, LIST_SEP); p; p = strtok(NULL, LIST_SEP)) {
3657                 char *home = get_user_home_dir(p);
3658
3659                 if (lp_servicenumber(p) >= 0)
3660                         continue;
3661
3662                 if (home && homes >= 0)
3663                         lp_add_home(p, homes, p, home);
3664         }
3665         SAFE_FREE(s);
3666 }
3667
3668 /***************************************************************************
3669  Auto-load one printer.
3670 ***************************************************************************/
3671
3672 void lp_add_one_printer(char *name, char *comment)
3673 {
3674         int printers = lp_servicenumber(PRINTERS_NAME);
3675         int i;
3676
3677         if (lp_servicenumber(name) < 0) {
3678                 lp_add_printer(name, printers);
3679                 if ((i = lp_servicenumber(name)) >= 0) {
3680                         string_set(&ServicePtrs[i]->comment, comment);
3681                         ServicePtrs[i]->autoloaded = True;
3682                 }
3683         }
3684 }
3685
3686 /***************************************************************************
3687  Announce ourselves as a print server.
3688 ***************************************************************************/
3689
3690 void update_server_announce_as_printserver(void)
3691 {
3692         default_server_announce |= SV_TYPE_PRINTQ_SERVER;       
3693 }
3694
3695 /***************************************************************************
3696  Have we loaded a services file yet?
3697 ***************************************************************************/
3698
3699 BOOL lp_loaded(void)
3700 {
3701         return (bLoaded);
3702 }
3703
3704 /***************************************************************************
3705  Unload unused services.
3706 ***************************************************************************/
3707
3708 void lp_killunused(BOOL (*snumused) (int))
3709 {
3710         int i;
3711         for (i = 0; i < iNumServices; i++) {
3712                 if (!VALID(i))
3713                         continue;
3714
3715                 if (!snumused || !snumused(i)) {
3716                         ServicePtrs[i]->valid = False;
3717                         free_service(ServicePtrs[i]);
3718                 }
3719         }
3720 }
3721
3722 /***************************************************************************
3723  Unload a service.
3724 ***************************************************************************/
3725
3726 void lp_killservice(int iServiceIn)
3727 {
3728         if (VALID(iServiceIn)) {
3729                 ServicePtrs[iServiceIn]->valid = False;
3730                 free_service(ServicePtrs[iServiceIn]);
3731         }
3732 }
3733
3734 /***************************************************************************
3735  Save the curent values of all global and sDefault parameters into the 
3736  defaults union. This allows swat and testparm to show only the
3737  changed (ie. non-default) parameters.
3738 ***************************************************************************/
3739
3740 static void lp_save_defaults(void)
3741 {
3742         int i;
3743         for (i = 0; parm_table[i].label; i++) {
3744                 if (i > 0 && parm_table[i].ptr == parm_table[i - 1].ptr)
3745                         continue;
3746                 switch (parm_table[i].type) {
3747                         case P_LIST:
3748                                 str_list_copy(&(parm_table[i].def.lvalue),
3749                                             *(const char ***)parm_table[i].ptr);
3750                                 break;
3751                         case P_STRING:
3752                         case P_USTRING:
3753                                 if (parm_table[i].ptr) {
3754                                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
3755                                 } else {
3756                                         parm_table[i].def.svalue = NULL;
3757                                 }
3758                                 break;
3759                         case P_GSTRING:
3760                         case P_UGSTRING:
3761                                 if (parm_table[i].ptr) {
3762                                         parm_table[i].def.svalue = strdup((char *)parm_table[i].ptr);
3763                                 } else {
3764                                         parm_table[i].def.svalue = NULL;
3765                                 }
3766                                 break;
3767                         case P_BOOL:
3768                         case P_BOOLREV:
3769                                 parm_table[i].def.bvalue =
3770                                         *(BOOL *)parm_table[i].ptr;
3771                                 break;
3772                         case P_CHAR:
3773                                 parm_table[i].def.cvalue =
3774                                         *(char *)parm_table[i].ptr;
3775                                 break;
3776                         case P_INTEGER:
3777                         case P_OCTAL:
3778                         case P_ENUM:
3779                                 parm_table[i].def.ivalue =
3780                                         *(int *)parm_table[i].ptr;
3781                                 break;
3782                         case P_SEP:
3783                                 break;
3784                 }
3785         }
3786         defaults_saved = True;
3787 }
3788
3789 /*******************************************************************
3790  Set the server type we will announce as via nmbd.
3791 ********************************************************************/
3792
3793 static void set_server_role(void)
3794 {
3795         server_role = ROLE_STANDALONE;
3796
3797         switch (lp_security()) {
3798                 case SEC_SHARE:
3799                         if (lp_domain_logons())
3800                                 DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
3801                         break;
3802                 case SEC_SERVER:
3803                         if (lp_domain_logons())
3804                                 DEBUG(0, ("Server's Role (logon server) conflicts with server-level security\n"));
3805                         server_role = ROLE_DOMAIN_MEMBER;
3806                         break;
3807                 case SEC_DOMAIN:
3808                         if (lp_domain_logons()) {
3809                                 DEBUG(1, ("Server's Role (logon server) NOT ADVISED with domain-level security\n"));
3810                                 server_role = ROLE_DOMAIN_BDC;
3811                                 break;
3812                         }
3813                         server_role = ROLE_DOMAIN_MEMBER;
3814                         break;
3815                 case SEC_ADS:
3816                         if (lp_domain_logons()) {
3817                                 server_role = ROLE_DOMAIN_PDC;
3818                                 break;
3819                         }
3820                         server_role = ROLE_DOMAIN_MEMBER;
3821                         break;
3822                 case SEC_USER:
3823                         if (lp_domain_logons()) {
3824
3825                                 if (Globals.bDomainMaster) /* auto or yes */ 
3826                                         server_role = ROLE_DOMAIN_PDC;
3827                                 else
3828                                         server_role = ROLE_DOMAIN_BDC;
3829                         }
3830                         break;
3831                 default:
3832                         DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
3833                         break;
3834         }
3835
3836         DEBUG(10, ("set_server_role: role = "));
3837
3838         switch(server_role) {
3839         case ROLE_STANDALONE:
3840                 DEBUGADD(10, ("ROLE_STANDALONE\n"));
3841                 break;
3842         case ROLE_DOMAIN_MEMBER:
3843                 DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
3844                 break;
3845         case ROLE_DOMAIN_BDC:
3846                 DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
3847                 break;
3848         case ROLE_DOMAIN_PDC:
3849                 DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
3850                 break;
3851         }
3852 }
3853
3854 /***************************************************************************
3855  Load the services array from the services file. Return True on success, 
3856  False on failure.
3857 ***************************************************************************/
3858
3859 BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
3860              BOOL add_ipc)
3861 {
3862         pstring n2;
3863         BOOL bRetval;
3864         param_opt_struct *data, *pdata;
3865
3866         pstrcpy(n2, pszFname);
3867         standard_sub_basic(current_user_info.smb_name, n2,sizeof(n2));
3868
3869         add_to_file_list(pszFname, n2);
3870
3871         bRetval = False;
3872
3873         DEBUG(3, ("lp_load: refreshing parameters\n"));
3874         
3875         bInGlobalSection = True;
3876         bGlobalOnly = global_only;
3877
3878         init_globals();
3879         debug_init();
3880
3881         if (save_defaults)
3882         {
3883                 init_locals();
3884                 lp_save_defaults();
3885         }
3886
3887         if (Globals.param_opt != NULL) {
3888                 data = Globals.param_opt;
3889                 while (data) {
3890                         string_free(&data->key);
3891                         string_free(&data->value);
3892                         pdata = data->next;
3893                         SAFE_FREE(data);
3894                         data = pdata;
3895                 }
3896                 Globals.param_opt = NULL;
3897         }
3898         
3899         /* We get sections first, so have to start 'behind' to make up */
3900         iServiceIndex = -1;
3901         bRetval = pm_process(n2, do_section, do_parameter);
3902
3903         /* finish up the last section */
3904         DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3905         if (bRetval)
3906                 if (iServiceIndex >= 0)
3907                         bRetval = service_ok(iServiceIndex);
3908
3909         lp_add_auto_services(lp_auto_services());
3910
3911         if (add_ipc) {
3912                 /* When 'restrict anonymous = 2' guest connections to ipc$
3913                    are denied */
3914                 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
3915                 lp_add_ipc("ADMIN$", False);
3916         }
3917
3918         set_server_role();
3919         set_default_server_announce_type();
3920
3921         bLoaded = True;
3922
3923         /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
3924         /* if bWINSsupport is true and we are in the client            */
3925         if (in_client && Globals.bWINSsupport) {
3926                 lp_do_parameter(-1, "wins server", "127.0.0.1");
3927         }
3928
3929         init_iconv();
3930
3931         return (bRetval);
3932 }
3933
3934 /***************************************************************************
3935  Reset the max number of services.
3936 ***************************************************************************/
3937
3938 void lp_resetnumservices(void)
3939 {
3940         iNumServices = 0;
3941 }
3942
3943 /***************************************************************************
3944  Return the max number of services.
3945 ***************************************************************************/
3946
3947 int lp_numservices(void)
3948 {
3949         return (iNumServices);
3950 }
3951
3952 /***************************************************************************
3953 Display the contents of the services array in human-readable form.
3954 ***************************************************************************/
3955
3956 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
3957 {
3958         int iService;
3959
3960         if (show_defaults)
3961                 defaults_saved = False;
3962
3963         dump_globals(f);
3964
3965         dump_a_service(&sDefault, f);
3966
3967         for (iService = 0; iService < maxtoprint; iService++)
3968                 lp_dump_one(f, show_defaults, iService);
3969 }
3970
3971 /***************************************************************************
3972 Display the contents of one service in human-readable form.
3973 ***************************************************************************/
3974
3975 void lp_dump_one(FILE * f, BOOL show_defaults, int snum)
3976 {
3977         if (VALID(snum)) {
3978                 if (ServicePtrs[snum]->szService[0] == '\0')
3979                         return;
3980                 dump_a_service(ServicePtrs[snum], f);
3981         }
3982 }
3983
3984 /***************************************************************************
3985 Return the number of the service with the given name, or -1 if it doesn't
3986 exist. Note that this is a DIFFERENT ANIMAL from the internal function
3987 getservicebyname()! This works ONLY if all services have been loaded, and
3988 does not copy the found service.
3989 ***************************************************************************/
3990
3991 int lp_servicenumber(const char *pszServiceName)
3992 {
3993         int iService;
3994         fstring serviceName;
3995  
3996  
3997         for (iService = iNumServices - 1; iService >= 0; iService--) {
3998                 if (VALID(iService) && ServicePtrs[iService]->szService) {
3999                         /*
4000                          * The substitution here is used to support %U is
4001                          * service names
4002                          */
4003                         fstrcpy(serviceName, ServicePtrs[iService]->szService);
4004                         standard_sub_basic(current_user_info.smb_name, serviceName,sizeof(serviceName));
4005                         if (strequal(serviceName, pszServiceName))
4006                                 break;
4007                 }
4008         }
4009
4010         if (iService < 0)
4011                 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
4012
4013         return (iService);
4014 }
4015
4016 /*******************************************************************
4017  A useful volume label function. 
4018 ********************************************************************/
4019
4020 char *volume_label(int snum)
4021 {
4022         char *ret = lp_volume(snum);
4023         if (!*ret)
4024                 return lp_servicename(snum);
4025         return (ret);
4026 }
4027
4028
4029 /*******************************************************************
4030  Set the server type we will announce as via nmbd.
4031 ********************************************************************/
4032
4033 static void set_default_server_announce_type(void)
4034 {
4035         default_server_announce = 0;
4036         default_server_announce |= SV_TYPE_WORKSTATION;
4037         default_server_announce |= SV_TYPE_SERVER;
4038         default_server_announce |= SV_TYPE_SERVER_UNIX;
4039
4040         switch (lp_announce_as()) {
4041                 case ANNOUNCE_AS_NT_SERVER:
4042                         default_server_announce |= SV_TYPE_SERVER_NT;
4043                         /* fall through... */
4044                 case ANNOUNCE_AS_NT_WORKSTATION:
4045                         default_server_announce |= SV_TYPE_NT;
4046                         break;
4047                 case ANNOUNCE_AS_WIN95:
4048                         default_server_announce |= SV_TYPE_WIN95_PLUS;
4049                         break;
4050                 case ANNOUNCE_AS_WFW:
4051                         default_server_announce |= SV_TYPE_WFW;
4052                         break;
4053                 default:
4054                         break;
4055         }
4056
4057         switch (lp_server_role()) {
4058                 case ROLE_DOMAIN_MEMBER:
4059                         default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
4060                         break;
4061                 case ROLE_DOMAIN_PDC:
4062                         default_server_announce |= SV_TYPE_DOMAIN_CTRL;
4063                         break;
4064                 case ROLE_DOMAIN_BDC:
4065                         default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
4066                         break;
4067                 case ROLE_STANDALONE:
4068                 default:
4069                         break;
4070         }
4071         if (lp_time_server())
4072                 default_server_announce |= SV_TYPE_TIME_SOURCE;
4073
4074         if (lp_host_msdfs())
4075                 default_server_announce |= SV_TYPE_DFS_SERVER;
4076 }
4077
4078 /***********************************************************
4079  returns role of Samba server
4080 ************************************************************/
4081
4082 int lp_server_role(void)
4083 {
4084         return server_role;
4085 }
4086
4087 /***********************************************************
4088  If we are PDC then prefer us as DMB
4089 ************************************************************/
4090
4091 BOOL lp_domain_master(void)
4092 {
4093         if (Globals.bDomainMaster == Auto)
4094                 return (lp_server_role() == ROLE_DOMAIN_PDC);
4095
4096         return Globals.bDomainMaster;
4097 }
4098
4099 /***********************************************************
4100  If we are DMB then prefer us as LMB
4101 ************************************************************/
4102
4103 BOOL lp_preferred_master(void)
4104 {
4105         if (Globals.bPreferredMaster == Auto)
4106                 return (lp_local_master() && lp_domain_master());
4107
4108         return Globals.bPreferredMaster;
4109 }
4110
4111 /*******************************************************************
4112  Remove a service.
4113 ********************************************************************/
4114
4115 void lp_remove_service(int snum)
4116 {
4117         ServicePtrs[snum]->valid = False;
4118 }
4119
4120 /*******************************************************************
4121  Copy a service.
4122 ********************************************************************/
4123
4124 void lp_copy_service(int snum, const char *new_name)
4125 {
4126         char *oldname = lp_servicename(snum);
4127         do_section(new_name);
4128         if (snum >= 0) {
4129                 snum = lp_servicenumber(new_name);
4130                 if (snum >= 0)
4131                         lp_do_parameter(snum, "copy", oldname);
4132         }
4133 }
4134
4135
4136 /*******************************************************************
4137  Get the default server type we will announce as via nmbd.
4138 ********************************************************************/
4139
4140 int lp_default_server_announce(void)
4141 {
4142         return default_server_announce;
4143 }
4144
4145 /*******************************************************************
4146  Split the announce version into major and minor numbers.
4147 ********************************************************************/
4148
4149 int lp_major_announce_version(void)
4150 {
4151         static BOOL got_major = False;
4152         static int major_version = DEFAULT_MAJOR_VERSION;
4153         char *vers;
4154         char *p;
4155
4156         if (got_major)
4157                 return major_version;
4158
4159         got_major = True;
4160         if ((vers = lp_announce_version()) == NULL)
4161                 return major_version;
4162
4163         if ((p = strchr_m(vers, '.')) == 0)
4164                 return major_version;
4165
4166         *p = '\0';
4167         major_version = atoi(vers);
4168         return major_version;
4169 }
4170
4171 int lp_minor_announce_version(void)
4172 {
4173         static BOOL got_minor = False;
4174         static int minor_version = DEFAULT_MINOR_VERSION;
4175         char *vers;
4176         char *p;
4177
4178         if (got_minor)
4179                 return minor_version;
4180
4181         got_minor = True;
4182         if ((vers = lp_announce_version()) == NULL)
4183                 return minor_version;
4184
4185         if ((p = strchr_m(vers, '.')) == 0)
4186                 return minor_version;
4187
4188         p++;
4189         minor_version = atoi(p);
4190         return minor_version;
4191 }
4192
4193 /***********************************************************
4194  Set the global name resolution order (used in smbclient).
4195 ************************************************************/
4196
4197 void lp_set_name_resolve_order(char *new_order)
4198 {
4199         Globals.szNameResolveOrder = new_order;
4200 }
4201
4202 const char *lp_printername(int snum)
4203 {
4204         const char *ret = _lp_printername(snum);
4205         if (ret == NULL || (ret != NULL && *ret == '\0'))
4206                 ret = lp_const_servicename(snum);
4207
4208         return ret;
4209 }
4210
4211
4212 /****************************************************************
4213  Compatibility fn. for 2.2.2 code.....
4214 *****************************************************************/
4215
4216 void get_private_directory(pstring privdir)
4217 {
4218         pstrcpy (privdir, lp_private_dir());
4219 }
4220
4221 /***********************************************************
4222  Allow daemons such as winbindd to fix their logfile name.
4223 ************************************************************/
4224
4225 void lp_set_logfile(const char *name)
4226 {
4227         extern pstring debugf;
4228         string_set(&Globals.szLogFile, name);
4229         pstrcpy(debugf, name);
4230 }
4231
4232 /*******************************************************************
4233  Return the NetBIOS called name.
4234 ********************************************************************/
4235
4236 const char *get_called_name(void)
4237 {
4238         extern fstring local_machine;
4239         static fstring called_name;
4240
4241         if (! *local_machine)
4242                 return global_myname();
4243
4244         /*
4245          * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV"
4246          * arrggg!!! but we've already rewritten the client's
4247          * netbios name at this point...
4248          */
4249
4250         if (*local_machine) {
4251                 if (!StrCaseCmp(local_machine, "_SMBSERVER") || !StrCaseCmp(local_machine, "_SMBSERV")) {
4252                         fstrcpy(called_name, get_my_primary_ip());
4253                         DEBUG(8,("get_called_name: assuming that client used IP address [%s] as called name.\n",
4254                                 called_name));
4255                         return called_name;
4256                 }
4257         }
4258
4259         return local_machine;
4260 }
4261
4262 /*******************************************************************
4263  Return the max print jobs per queue.
4264 ********************************************************************/
4265
4266 int lp_maxprintjobs(int snum)
4267 {
4268         int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
4269         if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
4270                 maxjobs = PRINT_MAX_JOBID - 1;
4271
4272         return maxjobs;
4273 }