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