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