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