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