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