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