first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[ira/wip.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    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /*
25  *  Load parameters.
26  *
27  *  This module provides suitable callback functions for the params
28  *  module. It builds the internal table of service details which is
29  *  then used by the rest of the server.
30  *
31  * To add a parameter:
32  *
33  * 1) add it to the global or service structure definition
34  * 2) add it to the parm_table
35  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
36  * 4) If it's a global then initialise it in init_globals. If a local
37  *    (ie. service) parameter then initialise it in the sDefault structure
38  *  
39  *
40  * Notes:
41  *   The configuration file is processed sequentially for speed. It is NOT
42  *   accessed randomly as happens in 'real' Windows. For this reason, there
43  *   is a fair bit of sequence-dependent code here - ie., code which assumes
44  *   that certain things happen before others. In particular, the code which
45  *   happens at the boundary between sections is delicately poised, so be
46  *   careful!
47  *
48  */
49
50 #include "includes.h"
51
52 /* Set default coding system for KANJI if none specified in Makefile. */
53 /* 
54  * We treat KANJI specially due to historical precedent (it was the
55  * first non-english codepage added to Samba). With the new dynamic
56  * codepage support this is not needed anymore.
57  *
58  * The define 'KANJI' is being overloaded to mean 'use kanji codepage
59  * by default' and also 'this is the filename-to-disk conversion 
60  * method to use'. This really should be removed and all control
61  * over this left in the smb.conf parameters 'client codepage'
62  * and 'coding system'.
63  */
64 #ifndef KANJI
65 #define KANJI "sbcs"
66 #endif /* KANJI */
67
68 BOOL in_client = False;   /* Not in the client by default */
69 BOOL bLoaded = False;
70
71 extern int DEBUGLEVEL;
72 extern pstring user_socket_options;
73 extern pstring global_myname;
74
75 #ifndef GLOBAL_NAME
76 #define GLOBAL_NAME "global"
77 #endif
78
79 #ifndef PRINTERS_NAME
80 #define PRINTERS_NAME "printers"
81 #endif
82
83 #ifndef HOMES_NAME
84 #define HOMES_NAME "homes"
85 #endif
86
87 /* some helpful bits */
88 #define pSERVICE(i) ServicePtrs[i]
89 #define iSERVICE(i) (*pSERVICE(i))
90 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
91 #define VALID(i) iSERVICE(i).valid
92
93 int keepalive=DEFAULT_KEEPALIVE;
94 extern BOOL use_getwd_cache;
95
96 extern int extra_time_offset;
97
98 static BOOL defaults_saved=False;
99
100 /* 
101  * This structure describes global (ie., server-wide) parameters.
102  */
103 typedef struct
104 {
105   char *szPrintcapname;
106   char *szLockDir;
107   char *szRootdir;
108   char *szDefaultService;
109   char *szDfree;
110   char *szMsgCommand;
111   char *szHostsEquiv;
112   char *szServerString;
113   char *szAutoServices;
114   char *szPasswdProgram;
115   char *szPasswdChat;
116   char *szLogFile;
117   char *szConfigFile;
118   char *szSMBPasswdFile;
119   char *szPasswordServer;
120   char *szSocketOptions;
121   char *szValidChars;
122   char *szWorkGroup;
123   char *szDomainAdminGroup;
124   char *szDomainGuestGroup;
125   char *szDomainAdminUsers;
126   char *szDomainGuestUsers;
127   char *szDomainHostsallow; 
128   char *szDomainHostsdeny;
129   char *szUsernameMap;
130 #ifdef USING_GROUPNAME_MAP
131   char *szGroupnameMap;
132 #endif /* USING_GROUPNAME_MAP */
133   char *szCharacterSet;
134   char *szLogonScript;
135   char *szLogonPath;
136   char *szLogonDrive;
137   char *szLogonHome;
138   char *szSmbrun;
139   char *szWINSserver;
140   char *szCodingSystem;
141   char *szInterfaces;
142   char *szRemoteAnnounce;
143   char *szRemoteBrowseSync;
144   char *szSocketAddress;
145   char *szNISHomeMapName;
146   char *szAnnounceVersion; /* This is initialised in init_globals */
147   char *szNetbiosAliases;
148   char *szDomainOtherSIDs;
149   char *szDomainGroups;
150   char *szDriverFile;
151   char *szNameResolveOrder;
152   char *szLdapServer;
153   char *szLdapSuffix;
154   char *szLdapFilter;
155   char *szLdapRoot;
156   char *szLdapRootPassword; 
157   char *szPanicAction;
158   char *szAddUserScript;
159   char *szDelUserScript;
160   char *szWINSHook;
161   int max_log_size;
162   int mangled_stack;
163   int max_xmit;
164   int max_mux;
165   int max_open_files;
166   int max_packet;
167   int pwordlevel;
168   int unamelevel;
169   int deadtime;
170   int maxprotocol;
171   int security;
172   int maxdisksize;
173   int lpqcachetime;
174   int syslog;
175   int os_level;
176   int max_ttl;
177   int max_wins_ttl;
178   int min_wins_ttl;
179   int ReadSize;
180   int lm_announce;
181   int lm_interval;
182   int shmem_size;
183   int client_code_page;
184   int announce_as;   /* This is initialised in init_globals */
185   int machine_password_timeout;
186   int change_notify_timeout;
187   int stat_cache_size;
188   int map_to_guest;
189   int min_passwd_length;
190   int oplock_break_wait_time;
191 #ifdef WITH_LDAP
192   int ldap_port;
193 #endif /* WITH_LDAP */
194 #ifdef WITH_SSL
195   int sslVersion;
196   char *sslHostsRequire;
197   char *sslHostsResign;
198   char *sslCaCertDir;
199   char *sslCaCertFile;
200   char *sslCert;
201   char *sslPrivKey;
202   char *sslClientCert;
203   char *sslClientPrivKey;
204   char *sslCiphers;
205   BOOL sslEnabled;
206   BOOL sslReqClientCert;
207   BOOL sslReqServerCert;
208   BOOL sslCompatibility;
209 #endif /* WITH_SSL */
210   BOOL bDNSproxy;
211   BOOL bWINSsupport;
212   BOOL bWINSproxy;
213   BOOL bLocalMaster;
214   BOOL bPreferredMaster;
215   BOOL bDomainMaster;
216   BOOL bDomainLogons;
217   BOOL bEncryptPasswords;
218   BOOL bUpdateEncrypt;
219   BOOL bStripDot;
220   BOOL bNullPasswords;
221   BOOL bLoadPrinters;
222   BOOL bUseRhosts;
223   BOOL bReadRaw;
224   BOOL bWriteRaw;
225   BOOL bReadPrediction;
226   BOOL bReadbmpx;
227   BOOL bSyslogOnly;
228   BOOL bBrowseList;
229   BOOL bUnixRealname;
230   BOOL bNISHomeMap;
231   BOOL bTimeServer;
232   BOOL bBindInterfacesOnly;
233   BOOL bUnixPasswdSync;
234   BOOL bPasswdChatDebug;
235   BOOL bOleLockingCompat;
236   BOOL bTimestampLogs;
237   BOOL bNTSmbSupport;
238   BOOL bNTPipeSupport;
239   BOOL bNTAclSupport;
240   BOOL bStatCache;
241   BOOL bKernelOplocks;
242   BOOL bAllowTrustedDomains;
243   BOOL bRestrictAnonymous;
244   BOOL bDebugHiresTimestamp;
245   BOOL bDebugPid;
246   BOOL bDebugUid;
247 } global;
248
249 static global Globals;
250
251
252
253 /* 
254  * This structure describes a single service. 
255  */
256 typedef struct
257 {
258   BOOL valid;
259   char *szService;
260   char *szPath;
261   char *szUsername;
262   char *szGuestaccount;
263   char *szInvalidUsers;
264   char *szValidUsers;
265   char *szAdminUsers;
266   char *szCopy;
267   char *szInclude;
268   char *szPreExec;
269   char *szPostExec;
270   char *szRootPreExec;
271   char *szRootPostExec;
272   char *szPrintcommand;
273   char *szLpqcommand;
274   char *szLprmcommand;
275   char *szLppausecommand;
276   char *szLpresumecommand;
277   char *szQueuepausecommand;
278   char *szQueueresumecommand;
279   char *szPrintername;
280   char *szPrinterDriver;
281   char *szPrinterDriverLocation;
282   char *szDontdescend;
283   char *szHostsallow;
284   char *szHostsdeny;
285   char *szMagicScript;
286   char *szMagicOutput;
287   char *szMangledMap;
288   char *szVetoFiles;
289   char *szHideFiles;
290   char *szVetoOplockFiles;
291   char *comment;
292   char *force_user;
293   char *force_group;
294   char *readlist;
295   char *writelist;
296   char *volume;
297   char *fstype;
298   int  iMinPrintSpace;
299   int  iWriteCacheSize;
300   int  iCreate_mask;
301   int  iCreate_force_mode;
302   int  iSecurity_mask;
303   int  iSecurity_force_mode;
304   int  iDir_mask;
305   int  iDir_force_mode;
306   int  iDir_Security_mask;
307   int  iDir_Security_force_mode;
308   int  iMaxConnections;
309   int  iDefaultCase;
310   int  iPrinting;
311   int  iOplockContentionLimit;
312   BOOL bAlternatePerm;
313   BOOL bPreexecClose;
314   BOOL bRootpreexecClose;
315   BOOL bRevalidate;
316   BOOL bCaseSensitive;
317   BOOL bCasePreserve;
318   BOOL bShortCasePreserve;
319   BOOL bCaseMangle;
320   BOOL status;
321   BOOL bHideDotFiles;
322   BOOL bBrowseable;
323   BOOL bAvailable;
324   BOOL bRead_only;
325   BOOL bNo_set_dir;
326   BOOL bGuest_only;
327   BOOL bGuest_ok;
328   BOOL bPrint_ok;
329   BOOL bPostscript;
330   BOOL bMap_system;
331   BOOL bMap_hidden;
332   BOOL bMap_archive;
333   BOOL bLocking;
334   BOOL bStrictLocking;
335   BOOL bShareModes;
336   BOOL bOpLocks;
337   BOOL bLevel2OpLocks;
338   BOOL bOnlyUser;
339   BOOL bMangledNames;
340   BOOL bWidelinks;
341   BOOL bSymlinks;
342   BOOL bSyncAlways;
343   BOOL bStrictSync;
344   char magic_char;
345   BOOL *copymap;
346   BOOL bDeleteReadonly;
347   BOOL bFakeOplocks;
348   BOOL bDeleteVetoFiles;
349   BOOL bDosFiletimes;
350   BOOL bDosFiletimeResolution;
351   BOOL bFakeDirCreateTimes;
352   BOOL bBlockingLocks;
353   char dummy[3]; /* for alignment */
354 } service;
355
356
357 /* This is a default service used to prime a services structure */
358 static service sDefault = 
359 {
360   True,   /* valid */
361   NULL,    /* szService */
362   NULL,    /* szPath */
363   NULL,    /* szUsername */
364   NULL,    /* szGuestAccount  - this is set in init_globals() */
365   NULL,    /* szInvalidUsers */
366   NULL,    /* szValidUsers */
367   NULL,    /* szAdminUsers */
368   NULL,    /* szCopy */
369   NULL,    /* szInclude */
370   NULL,    /* szPreExec */
371   NULL,    /* szPostExec */
372   NULL,    /* szRootPreExec */
373   NULL,    /* szRootPostExec */
374   NULL,    /* szPrintcommand */
375   NULL,    /* szLpqcommand */
376   NULL,    /* szLprmcommand */
377   NULL,    /* szLppausecommand */
378   NULL,    /* szLpresumecommand */
379   NULL,    /* szQueuepausecommand */
380   NULL,    /* szQueueresumecommand */
381   NULL,    /* szPrintername */
382   NULL,    /* szPrinterDriver - this is set in init_globals() */
383   NULL,    /* szPrinterDriverLocation */
384   NULL,    /* szDontdescend */
385   NULL,    /* szHostsallow */
386   NULL,    /* szHostsdeny */
387   NULL,    /* szMagicScript */
388   NULL,    /* szMagicOutput */
389   NULL,    /* szMangledMap */
390   NULL,    /* szVetoFiles */
391   NULL,    /* szHideFiles */
392   NULL,    /* szVetoOplockFiles */
393   NULL,    /* comment */
394   NULL,    /* force user */
395   NULL,    /* force group */
396   NULL,    /* readlist */
397   NULL,    /* writelist */
398   NULL,    /* volume */
399   NULL,    /* fstype */
400   0,       /* iMinPrintSpace */
401   0,       /* iWriteCacheSize */
402   0744,    /* iCreate_mask */
403   0000,    /* iCreate_force_mode */
404   -1,      /* iSecurity_mask */
405   -1,      /* iSecurity_force_mode */
406   0755,    /* iDir_mask */
407   0000,    /* iDir_force_mode */
408   -1,      /* iDir_Security_mask */
409   -1,      /* iDir_Security_force_mode */
410   0,       /* iMaxConnections */
411   CASE_LOWER, /* iDefaultCase */
412   DEFAULT_PRINTING, /* iPrinting */
413   2,       /* iOplockContentionLimit */
414   False,   /* bAlternatePerm */
415   False,   /* bPreexecClose */
416   False,   /* bRootpreexecClose */
417   False,   /* revalidate */
418   False,   /* case sensitive */
419   True,   /* case preserve */
420   True,   /* short case preserve */
421   False,  /* case mangle */
422   True,  /* status */
423   True,  /* bHideDotFiles */
424   True,  /* bBrowseable */
425   True,  /* bAvailable */
426   True,  /* bRead_only */
427   True,  /* bNo_set_dir */
428   False, /* bGuest_only */
429   False, /* bGuest_ok */
430   False, /* bPrint_ok */
431   False, /* bPostscript */
432   False, /* bMap_system */
433   False, /* bMap_hidden */
434   True,  /* bMap_archive */
435   True,  /* bLocking */
436   False,  /* bStrictLocking */
437   True,  /* bShareModes */
438   True,  /* bOpLocks */
439   True, /* bLevel2OpLocks */
440   False, /* bOnlyUser */
441   True,  /* bMangledNames */
442   True,  /* bWidelinks */
443   True,  /* bSymlinks */
444   False, /* bSyncAlways */
445   False, /* bStrictSync */
446   '~',   /* magic char */
447   NULL,  /* copymap */
448   False, /* bDeleteReadonly */
449   False, /* bFakeOplocks */
450   False, /* bDeleteVetoFiles */
451   False, /* bDosFiletimes */
452   False, /* bDosFiletimeResolution */
453   False, /* bFakeDirCreateTimes */
454   True,  /* bBlockingLocks */
455   ""     /* dummy */
456 };
457
458
459
460 /* local variables */
461 static service **ServicePtrs = NULL;
462 static int iNumServices = 0;
463 static int iServiceIndex = 0;
464 static BOOL bInGlobalSection = True;
465 static BOOL bGlobalOnly = False;
466 static int default_server_announce;
467
468 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
469
470 /* prototypes for the special type handlers */
471 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
472 static BOOL handle_include(char *pszParmValue, char **ptr);
473 static BOOL handle_copy(char *pszParmValue, char **ptr);
474 static BOOL handle_character_set(char *pszParmValue,char **ptr);
475 static BOOL handle_coding_system(char *pszParmValue,char **ptr);
476 static BOOL handle_client_code_page(char *pszParmValue,char **ptr);
477
478 static void set_default_server_announce_type(void);
479
480 static struct enum_list enum_protocol[] = {{PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"}, 
481                                            {PROTOCOL_LANMAN1, "LANMAN1"}, {PROTOCOL_CORE,"CORE"}, 
482                                            {PROTOCOL_COREPLUS, "COREPLUS"}, 
483                                            {PROTOCOL_COREPLUS, "CORE+"}, {-1, NULL}};
484
485 static struct enum_list enum_security[] = {{SEC_SHARE, "SHARE"},  {SEC_USER, "USER"}, 
486                                            {SEC_SERVER, "SERVER"}, {SEC_DOMAIN, "DOMAIN"},
487                                            {-1, NULL}};
488
489 static struct enum_list enum_printing[] = {{PRINT_SYSV, "sysv"}, {PRINT_AIX, "aix"}, 
490                                            {PRINT_HPUX, "hpux"}, {PRINT_BSD, "bsd"},
491                                            {PRINT_QNX, "qnx"},   {PRINT_PLP, "plp"},
492                                            {PRINT_LPRNG, "lprng"}, {PRINT_SOFTQ, "softq"},
493                                            {PRINT_CUPS, "cups"}, {-1, NULL}};
494
495 /* Types of machine we can announce as. */
496 #define ANNOUNCE_AS_NT_SERVER 1
497 #define ANNOUNCE_AS_WIN95 2
498 #define ANNOUNCE_AS_WFW 3
499 #define ANNOUNCE_AS_NT_WORKSTATION 4
500
501 static struct enum_list enum_announce_as[] = {{ANNOUNCE_AS_NT_SERVER, "NT"}, {ANNOUNCE_AS_NT_SERVER, "NT Server"}, {ANNOUNCE_AS_NT_WORKSTATION, "NT Workstation"}, {ANNOUNCE_AS_WIN95, "win95"}, {ANNOUNCE_AS_WFW, "WfW"}, {-1, NULL}};
502
503 static struct enum_list enum_case[] = {{CASE_LOWER, "lower"}, {CASE_UPPER, "upper"}, {-1, NULL}};
504
505 static struct enum_list enum_lm_announce[] = {{0, "False"}, {1, "True"}, {2, "Auto"}, {-1, NULL}};
506
507 /* 
508    Do you want session setups at user level security with a invalid
509    password to be rejected or allowed in as guest? WinNT rejects them
510    but it can be a pain as it means "net view" needs to use a password
511
512    You have 3 choices in the setting of map_to_guest:
513
514    "Never" means session setups with an invalid password
515    are rejected. This is the default.
516
517    "Bad User" means session setups with an invalid password
518    are rejected, unless the username does not exist, in which case it
519    is treated as a guest login
520
521    "Bad Password" means session setups with an invalid password
522    are treated as a guest login
523
524    Note that map_to_guest only has an effect in user or server
525    level security.
526 */
527
528 static struct enum_list enum_map_to_guest[] = {{NEVER_MAP_TO_GUEST, "Never"}, {MAP_TO_GUEST_ON_BAD_USER, "Bad User"}, {MAP_TO_GUEST_ON_BAD_PASSWORD, "Bad Password"}, {-1, NULL}};
529
530 #ifdef WITH_SSL
531 static struct enum_list enum_ssl_version[] = {{SMB_SSL_V2, "ssl2"}, {SMB_SSL_V3, "ssl3"},
532   {SMB_SSL_V23, "ssl2or3"}, {SMB_SSL_TLS1, "tls1"}, {-1, NULL}};
533 #endif
534
535 /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
536 static struct parm_struct parm_table[] =
537 {
538   {"Base Options", P_SEP, P_SEPARATOR},
539   {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,          NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT|FLAG_DOS_STRING},
540   {"path",             P_STRING,  P_LOCAL,  &sDefault.szPath,           NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT|FLAG_DOS_STRING},
541   {"directory",        P_STRING,  P_LOCAL,  &sDefault.szPath,           NULL,   NULL,  FLAG_DOS_STRING},
542   {"workgroup",        P_USTRING, P_GLOBAL, &Globals.szWorkGroup,       NULL,   NULL,  FLAG_BASIC|FLAG_DOS_STRING},
543   {"netbios name",     P_UGSTRING,P_GLOBAL, global_myname,                     NULL,   NULL,  FLAG_BASIC|FLAG_DOS_STRING},
544   {"netbios aliases",  P_STRING,  P_GLOBAL, &Globals.szNetbiosAliases,  NULL,   NULL,  FLAG_DOS_STRING},
545   {"server string",    P_STRING,  P_GLOBAL, &Globals.szServerString,    NULL,   NULL,  FLAG_BASIC|FLAG_DOS_STRING},
546   {"interfaces",       P_STRING,  P_GLOBAL, &Globals.szInterfaces,      NULL,   NULL,  FLAG_BASIC},
547   {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL,   NULL,  0},
548
549   {"Security Options", P_SEP, P_SEPARATOR},
550   {"security",         P_ENUM,    P_GLOBAL, &Globals.security,          NULL,   enum_security, FLAG_BASIC},
551   {"encrypt passwords",P_BOOL,    P_GLOBAL, &Globals.bEncryptPasswords, NULL,   NULL,  FLAG_BASIC},
552   {"update encrypted", P_BOOL,    P_GLOBAL, &Globals.bUpdateEncrypt,    NULL,   NULL,  FLAG_BASIC},
553   {"allow trusted domains",P_BOOL,P_GLOBAL, &Globals.bAllowTrustedDomains,NULL, NULL,  0},
554   {"alternate permissions",P_BOOL,P_LOCAL,  &sDefault.bAlternatePerm,   NULL,   NULL,  FLAG_GLOBAL|FLAG_DEPRECATED},
555   {"hosts equiv",      P_STRING,  P_GLOBAL, &Globals.szHostsEquiv,      NULL,   NULL,  0},
556   {"min passwd length",     P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL,   NULL,  0},
557   {"min password length",   P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL,   NULL,  0},
558   {"map to guest",     P_ENUM,    P_GLOBAL, &Globals.map_to_guest,      NULL,   enum_map_to_guest, 0},
559   {"null passwords",   P_BOOL,    P_GLOBAL, &Globals.bNullPasswords,    NULL,   NULL,  0},
560   {"password server",  P_STRING,  P_GLOBAL, &Globals.szPasswordServer,  NULL,   NULL,  0},
561   {"smb passwd file",  P_STRING,  P_GLOBAL, &Globals.szSMBPasswdFile,   NULL,   NULL,  0},
562   {"root directory",   P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
563   {"root dir",         P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
564   {"root",             P_STRING,  P_GLOBAL, &Globals.szRootdir,         NULL,   NULL,  0},
565   {"passwd program",   P_STRING,  P_GLOBAL, &Globals.szPasswdProgram,   NULL,   NULL,  0},
566   {"passwd chat",      P_STRING,  P_GLOBAL, &Globals.szPasswdChat,      NULL,   NULL,  0},
567   {"passwd chat debug",P_BOOL,    P_GLOBAL, &Globals.bPasswdChatDebug,  NULL,   NULL,  0},
568   {"username map",     P_STRING,  P_GLOBAL, &Globals.szUsernameMap,     NULL,   NULL,  0},
569   {"password level",   P_INTEGER, P_GLOBAL, &Globals.pwordlevel,        NULL,   NULL,  0},
570   {"username level",   P_INTEGER, P_GLOBAL, &Globals.unamelevel,        NULL,   NULL,  0},
571   {"unix password sync", P_BOOL,  P_GLOBAL, &Globals.bUnixPasswdSync,   NULL,   NULL,  0},
572   {"restrict anonymous", P_BOOL,  P_GLOBAL, &Globals.bRestrictAnonymous,NULL,   NULL,  0},
573   {"revalidate",       P_BOOL,    P_LOCAL,  &sDefault.bRevalidate,      NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
574   {"use rhosts",       P_BOOL,    P_GLOBAL, &Globals.bUseRhosts,        NULL,   NULL,  0},
575   {"username",         P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
576   {"user",             P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  0},
577   {"users",            P_STRING,  P_LOCAL,  &sDefault.szUsername,       NULL,   NULL,  0},
578   {"guest account",    P_STRING,  P_LOCAL,  &sDefault.szGuestaccount,   NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT|FLAG_GLOBAL},
579   {"invalid users",    P_STRING,  P_LOCAL,  &sDefault.szInvalidUsers,   NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
580   {"valid users",      P_STRING,  P_LOCAL,  &sDefault.szValidUsers,     NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
581   {"admin users",      P_STRING,  P_LOCAL,  &sDefault.szAdminUsers,     NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
582   {"read list",        P_STRING,  P_LOCAL,  &sDefault.readlist,         NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
583   {"write list",       P_STRING,  P_LOCAL,  &sDefault.writelist,        NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
584   {"force user",       P_STRING,  P_LOCAL,  &sDefault.force_user,       NULL,   NULL,  FLAG_SHARE},
585   {"force group",      P_STRING,  P_LOCAL,  &sDefault.force_group,      NULL,   NULL,  FLAG_SHARE},
586   {"group",            P_STRING,  P_LOCAL,  &sDefault.force_group,      NULL,   NULL,  0},
587   {"read only",        P_BOOL,    P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  FLAG_BASIC|FLAG_SHARE},
588   {"write ok",         P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
589   {"writeable",        P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
590   {"writable",         P_BOOLREV, P_LOCAL,  &sDefault.bRead_only,       NULL,   NULL,  0},
591   {"create mask",      P_OCTAL,   P_LOCAL,  &sDefault.iCreate_mask,     NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
592   {"create mode",      P_OCTAL,   P_LOCAL,  &sDefault.iCreate_mask,     NULL,   NULL,  FLAG_GLOBAL},
593   {"force create mode",P_OCTAL,   P_LOCAL,  &sDefault.iCreate_force_mode,     NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
594   {"security mask",    P_OCTAL,   P_LOCAL,  &sDefault.iSecurity_mask,   NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
595   {"force security mode",P_OCTAL, P_LOCAL,  &sDefault.iSecurity_force_mode,NULL,NULL,  FLAG_GLOBAL|FLAG_SHARE},
596   {"directory mask",   P_OCTAL,   P_LOCAL,  &sDefault.iDir_mask,        NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
597   {"directory mode",   P_OCTAL,   P_LOCAL,  &sDefault.iDir_mask,        NULL,   NULL,  FLAG_GLOBAL},
598   {"force directory mode",   P_OCTAL,P_LOCAL,&sDefault.iDir_force_mode, NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE},
599   {"directory security mask",P_OCTAL,P_LOCAL,&sDefault.iDir_Security_mask,NULL, NULL,  FLAG_GLOBAL|FLAG_SHARE},
600   {"force directory security mode",P_OCTAL, P_LOCAL,  &sDefault.iDir_Security_force_mode,NULL,NULL,FLAG_GLOBAL|FLAG_SHARE},
601   {"guest only",       P_BOOL,    P_LOCAL,  &sDefault.bGuest_only,      NULL,   NULL,  FLAG_SHARE},
602   {"only guest",       P_BOOL,    P_LOCAL,  &sDefault.bGuest_only,      NULL,   NULL,  0},
603   {"guest ok",         P_BOOL,    P_LOCAL,  &sDefault.bGuest_ok,        NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT},
604   {"public",           P_BOOL,    P_LOCAL,  &sDefault.bGuest_ok,        NULL,   NULL,  0},
605   {"only user",        P_BOOL,    P_LOCAL,  &sDefault.bOnlyUser,        NULL,   NULL,  FLAG_SHARE},
606   {"hosts allow",      P_STRING,  P_LOCAL,  &sDefault.szHostsallow,     NULL,   NULL,  FLAG_GLOBAL|FLAG_BASIC|FLAG_SHARE|FLAG_PRINT},
607   {"allow hosts",      P_STRING,  P_LOCAL,  &sDefault.szHostsallow,     NULL,   NULL,  0},
608   {"hosts deny",       P_STRING,  P_LOCAL,  &sDefault.szHostsdeny,      NULL,   NULL,  FLAG_GLOBAL|FLAG_BASIC|FLAG_SHARE|FLAG_PRINT},
609   {"deny hosts",       P_STRING,  P_LOCAL,  &sDefault.szHostsdeny,      NULL,   NULL,  0},
610
611 #ifdef WITH_SSL
612   {"Secure Socket Layer Options", P_SEP, P_SEPARATOR},
613   {"ssl",              P_BOOL,    P_GLOBAL, &Globals.sslEnabled,        NULL,   NULL,  0 },
614   {"ssl hosts",        P_STRING,  P_GLOBAL, &Globals.sslHostsRequire,   NULL,   NULL,  0 },
615   {"ssl hosts resign", P_STRING,  P_GLOBAL, &Globals.sslHostsResign,   NULL,   NULL,  0} ,
616   {"ssl CA certDir",   P_STRING,  P_GLOBAL, &Globals.sslCaCertDir,      NULL,   NULL,  0 },
617   {"ssl CA certFile",  P_STRING,  P_GLOBAL, &Globals.sslCaCertFile,     NULL,   NULL,  0 },
618   {"ssl server cert",  P_STRING,  P_GLOBAL, &Globals.sslCert,           NULL,   NULL,  0 },
619   {"ssl server key",   P_STRING,  P_GLOBAL, &Globals.sslPrivKey,        NULL,   NULL,  0 },
620   {"ssl client cert",  P_STRING,  P_GLOBAL, &Globals.sslClientCert,     NULL,   NULL,  0 },
621   {"ssl client key",   P_STRING,  P_GLOBAL, &Globals.sslClientPrivKey,  NULL,   NULL,  0 },
622   {"ssl require clientcert",  P_BOOL,  P_GLOBAL, &Globals.sslReqClientCert, NULL,   NULL ,  0},
623   {"ssl require servercert",  P_BOOL,  P_GLOBAL, &Globals.sslReqServerCert, NULL,   NULL ,  0},
624   {"ssl ciphers",      P_STRING,  P_GLOBAL, &Globals.sslCiphers,        NULL,   NULL,  0 },
625   {"ssl version",      P_ENUM,    P_GLOBAL, &Globals.sslVersion,        NULL,   enum_ssl_version, 0},
626   {"ssl compatibility", P_BOOL,    P_GLOBAL, &Globals.sslCompatibility, NULL,   NULL,  0 },
627 #endif        /* WITH_SSL */
628
629   {"Logging Options", P_SEP, P_SEPARATOR},
630   {"log level",        P_INTEGER, P_GLOBAL, &DEBUGLEVEL,                NULL,   NULL,  FLAG_BASIC},
631   {"debuglevel",       P_INTEGER, P_GLOBAL, &DEBUGLEVEL,                NULL,   NULL,  0},
632   {"syslog",           P_INTEGER, P_GLOBAL, &Globals.syslog,            NULL,   NULL,  0},
633   {"syslog only",      P_BOOL,    P_GLOBAL, &Globals.bSyslogOnly,       NULL,   NULL,  0},
634   {"log file",         P_STRING,  P_GLOBAL, &Globals.szLogFile,         NULL,   NULL,  0},
635   {"max log size",     P_INTEGER, P_GLOBAL, &Globals.max_log_size,      NULL,   NULL,  0},
636   {"timestamp logs",   P_BOOL,    P_GLOBAL, &Globals.bTimestampLogs,    NULL,   NULL,  0},
637   {"debug timestamp",  P_BOOL,    P_GLOBAL, &Globals.bTimestampLogs,    NULL,   NULL,  0},
638   {"debug hires timestamp",  P_BOOL,    P_GLOBAL, &Globals.bDebugHiresTimestamp,    NULL,   NULL,  0},
639   {"debug pid",        P_BOOL,    P_GLOBAL, &Globals.bDebugPid,         NULL,   NULL,  0},
640   {"debug uid",        P_BOOL,    P_GLOBAL, &Globals.bDebugUid,         NULL,   NULL,  0},
641   {"status",           P_BOOL,    P_LOCAL,  &sDefault.status,           NULL,   NULL,  FLAG_GLOBAL|FLAG_SHARE|FLAG_PRINT},
642
643   {"Protocol Options", P_SEP, P_SEPARATOR},
644   {"protocol",         P_ENUM,    P_GLOBAL, &Globals.maxprotocol,       NULL,   enum_protocol, 0},
645   {"read bmpx",        P_BOOL,    P_GLOBAL, &Globals.bReadbmpx,         NULL,   NULL,  0},
646   {"read raw",         P_BOOL,    P_GLOBAL, &Globals.bReadRaw,          NULL,   NULL,  0},
647   {"write raw",        P_BOOL,    P_GLOBAL, &Globals.bWriteRaw,         NULL,   NULL,  0},
648   {"nt smb support",   P_BOOL,    P_GLOBAL, &Globals.bNTSmbSupport,     NULL,   NULL,  0},
649   {"nt pipe support",  P_BOOL,    P_GLOBAL, &Globals.bNTPipeSupport,    NULL,   NULL,  0},
650   {"nt acl support",   P_BOOL,    P_GLOBAL, &Globals.bNTAclSupport,     NULL,   NULL,  0},
651   {"announce version", P_STRING,  P_GLOBAL, &Globals.szAnnounceVersion, NULL,   NULL,  0},
652   {"announce as",      P_ENUM,    P_GLOBAL, &Globals.announce_as,       NULL,   enum_announce_as, 0},
653   {"max mux",          P_INTEGER, P_GLOBAL, &Globals.max_mux,           NULL,   NULL,  0},
654   {"max xmit",         P_INTEGER, P_GLOBAL, &Globals.max_xmit,          NULL,   NULL,  0},
655   {"name resolve order",P_STRING, P_GLOBAL, &Globals.szNameResolveOrder,NULL,   NULL, 0},
656   {"max packet",       P_INTEGER, P_GLOBAL, &Globals.max_packet,        NULL,   NULL,  0},
657   {"packet size",      P_INTEGER, P_GLOBAL, &Globals.max_packet,        NULL,   NULL,  0},
658   {"max ttl",          P_INTEGER, P_GLOBAL, &Globals.max_ttl,           NULL,   NULL,  0},
659   {"max wins ttl",     P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl,      NULL,   NULL,  0},
660   {"min wins ttl",     P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl,      NULL,   NULL,  0},
661   {"time server",      P_BOOL,    P_GLOBAL, &Globals.bTimeServer,           NULL,   NULL,  0},
662
663   {"Tuning Options", P_SEP, P_SEPARATOR},
664   {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL,   NULL,  0},
665   {"deadtime",         P_INTEGER, P_GLOBAL, &Globals.deadtime,          NULL,   NULL,  0},
666   {"getwd cache",      P_BOOL,    P_GLOBAL, &use_getwd_cache,           NULL,   NULL,  0},
667   {"keepalive",        P_INTEGER, P_GLOBAL, &keepalive,                 NULL,   NULL,  0},
668   {"lpq cache time",   P_INTEGER, P_GLOBAL, &Globals.lpqcachetime,      NULL,   NULL,  0},
669   {"max connections",  P_INTEGER, P_LOCAL,  &sDefault.iMaxConnections,  NULL,   NULL,  FLAG_SHARE},
670   {"max disk size",    P_INTEGER, P_GLOBAL, &Globals.maxdisksize,       NULL,   NULL,  0},
671   {"max open files",   P_INTEGER, P_GLOBAL, &Globals.max_open_files,    NULL,   NULL,  0},
672   {"min print space",  P_INTEGER, P_LOCAL,  &sDefault.iMinPrintSpace,   NULL,   NULL,  FLAG_PRINT},
673   {"read prediction",  P_BOOL,    P_GLOBAL, &Globals.bReadPrediction,   NULL,   NULL,  0},
674   {"read size",        P_INTEGER, P_GLOBAL, &Globals.ReadSize,          NULL,   NULL,  0},
675   {"shared mem size",  P_INTEGER, P_GLOBAL, &Globals.shmem_size,        NULL,   NULL,  0},
676   {"socket options",   P_GSTRING, P_GLOBAL, user_socket_options,        NULL,   NULL,  0},
677   {"stat cache size",  P_INTEGER, P_GLOBAL, &Globals.stat_cache_size,   NULL,   NULL,  0},
678   {"strict sync",      P_BOOL,    P_LOCAL,  &sDefault.bStrictSync,      NULL,   NULL,  FLAG_SHARE},
679   {"sync always",      P_BOOL,    P_LOCAL,  &sDefault.bSyncAlways,      NULL,   NULL,  FLAG_SHARE},
680   {"write cache size", P_INTEGER, P_LOCAL,  &sDefault.iWriteCacheSize,  NULL,   NULL,  FLAG_SHARE},
681
682   {"Printing Options", P_SEP, P_SEPARATOR},
683   {"load printers",    P_BOOL,    P_GLOBAL, &Globals.bLoadPrinters,     NULL,   NULL,  FLAG_PRINT},
684   {"printcap name",    P_STRING,  P_GLOBAL, &Globals.szPrintcapname,    NULL,   NULL,  FLAG_PRINT},
685   {"printcap",         P_STRING,  P_GLOBAL, &Globals.szPrintcapname,    NULL,   NULL,  0},
686   {"printer driver file", P_STRING,  P_GLOBAL, &Globals.szDriverFile,   NULL,   NULL,  FLAG_PRINT},
687   {"print ok",         P_BOOL,    P_LOCAL,  &sDefault.bPrint_ok,        NULL,   NULL,  FLAG_PRINT},
688   {"printable",        P_BOOL,    P_LOCAL,  &sDefault.bPrint_ok,        NULL,   NULL,  0},
689   {"postscript",       P_BOOL,    P_LOCAL,  &sDefault.bPostscript,      NULL,   NULL,  FLAG_PRINT},
690   {"printing",         P_ENUM,    P_LOCAL,  &sDefault.iPrinting,        NULL,   enum_printing, FLAG_PRINT|FLAG_GLOBAL},
691   {"print command",    P_STRING,  P_LOCAL,  &sDefault.szPrintcommand,   NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
692   {"lpq command",      P_STRING,  P_LOCAL,  &sDefault.szLpqcommand,     NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
693   {"lprm command",     P_STRING,  P_LOCAL,  &sDefault.szLprmcommand,    NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
694   {"lppause command",  P_STRING,  P_LOCAL,  &sDefault.szLppausecommand, NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
695   {"lpresume command", P_STRING,  P_LOCAL,  &sDefault.szLpresumecommand,NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
696   {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT|FLAG_GLOBAL},
697   {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT|FLAG_GLOBAL},
698
699   {"printer name",     P_STRING,  P_LOCAL,  &sDefault.szPrintername,    NULL,   NULL,  FLAG_PRINT},
700   {"printer",          P_STRING,  P_LOCAL,  &sDefault.szPrintername,    NULL,   NULL,  0},
701   {"printer driver",   P_STRING,  P_LOCAL,  &sDefault.szPrinterDriver,  NULL,   NULL,  FLAG_PRINT},
702   {"printer driver location",   P_STRING,  P_LOCAL,  &sDefault.szPrinterDriverLocation,  NULL,   NULL,  FLAG_PRINT|FLAG_GLOBAL},
703
704
705   {"Filename Handling", P_SEP, P_SEPARATOR},
706   {"strip dot",        P_BOOL,    P_GLOBAL, &Globals.bStripDot,         NULL,   NULL,  0},
707   {"character set",    P_STRING,  P_GLOBAL, &Globals.szCharacterSet,    handle_character_set, NULL,  0},
708   {"mangled stack",    P_INTEGER, P_GLOBAL, &Globals.mangled_stack,     NULL,   NULL,  0},
709   {"coding system",    P_STRING,  P_GLOBAL, &Globals.szCodingSystem,    handle_coding_system, NULL,  0},
710   {"client code page", P_INTEGER, P_GLOBAL, &Globals.client_code_page,  handle_client_code_page,   NULL,  0},
711   {"default case",     P_ENUM, P_LOCAL,  &sDefault.iDefaultCase,        NULL,   enum_case, FLAG_SHARE},
712   {"case sensitive",   P_BOOL,    P_LOCAL,  &sDefault.bCaseSensitive,   NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
713   {"casesignames",     P_BOOL,    P_LOCAL,  &sDefault.bCaseSensitive,   NULL,   NULL,  0},
714   {"preserve case",    P_BOOL,    P_LOCAL,  &sDefault.bCasePreserve,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
715   {"short preserve case",P_BOOL,  P_LOCAL,  &sDefault.bShortCasePreserve,NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
716   {"mangle case",      P_BOOL,    P_LOCAL,  &sDefault.bCaseMangle,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
717   {"mangling char",    P_CHAR,    P_LOCAL,  &sDefault.magic_char,       NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
718   {"hide dot files",   P_BOOL,    P_LOCAL,  &sDefault.bHideDotFiles,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
719   {"delete veto files",P_BOOL,    P_LOCAL,  &sDefault.bDeleteVetoFiles, NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
720   {"veto files",       P_STRING,  P_LOCAL,  &sDefault.szVetoFiles,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL|FLAG_DOS_STRING},
721   {"hide files",       P_STRING,  P_LOCAL,  &sDefault.szHideFiles,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL|FLAG_DOS_STRING},
722   {"veto oplock files",P_STRING,  P_LOCAL,  &sDefault.szVetoOplockFiles,NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL|FLAG_DOS_STRING},
723   {"map system",       P_BOOL,    P_LOCAL,  &sDefault.bMap_system,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
724   {"map hidden",       P_BOOL,    P_LOCAL,  &sDefault.bMap_hidden,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
725   {"map archive",      P_BOOL,    P_LOCAL,  &sDefault.bMap_archive,     NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
726   {"mangled names",    P_BOOL,    P_LOCAL,  &sDefault.bMangledNames,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
727   {"mangled map",      P_STRING,  P_LOCAL,  &sDefault.szMangledMap,     NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
728   {"stat cache",       P_BOOL,    P_GLOBAL, &Globals.bStatCache,        NULL,   NULL,  0},
729
730   {"Domain Options", P_SEP, P_SEPARATOR},
731   {"domain groups",    P_STRING,  P_GLOBAL, &Globals.szDomainGroups,    NULL,   NULL,  0},
732   {"domain admin group",P_STRING, P_GLOBAL, &Globals.szDomainAdminGroup, NULL,   NULL,  0},
733   {"domain guest group",P_STRING, P_GLOBAL, &Globals.szDomainGuestGroup, NULL,   NULL,  0},
734   {"domain admin users",P_STRING, P_GLOBAL, &Globals.szDomainAdminUsers, NULL,   NULL,  0},
735   {"domain guest users",P_STRING, P_GLOBAL, &Globals.szDomainGuestUsers, NULL,   NULL,  0},
736 #ifdef USING_GROUPNAME_MAP
737   {"groupname map",     P_STRING, P_GLOBAL, &Globals.szGroupnameMap,     NULL,   NULL,  0},
738 #endif /* USING_GROUPNAME_MAP */
739   {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout,  NULL,   NULL,  0},
740
741   {"Logon Options", P_SEP, P_SEPARATOR},
742   {"add user script",  P_STRING,  P_GLOBAL, &Globals.szAddUserScript,   NULL,   NULL,  0},
743   {"delete user script",P_STRING, P_GLOBAL, &Globals.szDelUserScript,   NULL,   NULL,  0},
744   {"logon script",     P_STRING,  P_GLOBAL, &Globals.szLogonScript,     NULL,   NULL,  FLAG_DOS_STRING},
745   {"logon path",       P_STRING,  P_GLOBAL, &Globals.szLogonPath,       NULL,   NULL,  FLAG_DOS_STRING},
746   {"logon drive",      P_STRING,  P_GLOBAL, &Globals.szLogonDrive,      NULL,   NULL,  0},
747   {"logon home",       P_STRING,  P_GLOBAL, &Globals.szLogonHome,       NULL,   NULL,  FLAG_DOS_STRING},
748   {"domain logons",    P_BOOL,    P_GLOBAL, &Globals.bDomainLogons,     NULL,   NULL,  0},
749
750   {"Browse Options", P_SEP, P_SEPARATOR},
751   {"os level",         P_INTEGER, P_GLOBAL, &Globals.os_level,          NULL,   NULL,  FLAG_BASIC},
752   {"lm announce",      P_ENUM,    P_GLOBAL, &Globals.lm_announce,       NULL,   enum_lm_announce, 0},
753   {"lm interval",      P_INTEGER, P_GLOBAL, &Globals.lm_interval,       NULL,   NULL,  0},
754   {"preferred master", P_BOOL,    P_GLOBAL, &Globals.bPreferredMaster,  NULL,   NULL,  FLAG_BASIC},
755   {"prefered master",  P_BOOL,    P_GLOBAL, &Globals.bPreferredMaster,  NULL,   NULL,  0},
756   {"local master",     P_BOOL,    P_GLOBAL, &Globals.bLocalMaster,      NULL,   NULL,  FLAG_BASIC},
757   {"domain master",    P_BOOL,    P_GLOBAL, &Globals.bDomainMaster,     NULL,   NULL,  FLAG_BASIC},
758   {"browse list",      P_BOOL,    P_GLOBAL, &Globals.bBrowseList,       NULL,   NULL,  0},
759   {"browseable",       P_BOOL,    P_LOCAL,  &sDefault.bBrowseable,      NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT},
760   {"browsable",        P_BOOL,    P_LOCAL,  &sDefault.bBrowseable,      NULL,   NULL,  0},
761
762   {"WINS Options", P_SEP, P_SEPARATOR},
763   {"dns proxy",        P_BOOL,    P_GLOBAL, &Globals.bDNSproxy,         NULL,   NULL,  0},
764   {"wins proxy",       P_BOOL,    P_GLOBAL, &Globals.bWINSproxy,        NULL,   NULL,  0},
765   {"wins server",      P_STRING,  P_GLOBAL, &Globals.szWINSserver,      NULL,   NULL,  FLAG_BASIC},
766   {"wins support",     P_BOOL,    P_GLOBAL, &Globals.bWINSsupport,      NULL,   NULL,  FLAG_BASIC},
767   {"wins hook",        P_STRING,  P_GLOBAL, &Globals.szWINSHook, NULL,   NULL,  0},
768
769   {"Locking Options", P_SEP, P_SEPARATOR},
770   {"blocking locks",   P_BOOL,    P_LOCAL,  &sDefault.bBlockingLocks,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
771   {"fake oplocks",     P_BOOL,    P_LOCAL,  &sDefault.bFakeOplocks,     NULL,   NULL,  FLAG_SHARE},
772   {"kernel oplocks",   P_BOOL,    P_GLOBAL, &Globals.bKernelOplocks,    NULL,   NULL,  FLAG_GLOBAL},
773   {"locking",          P_BOOL,    P_LOCAL,  &sDefault.bLocking,         NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
774   {"ole locking compatibility",   P_BOOL,    P_GLOBAL,  &Globals.bOleLockingCompat,   NULL,   NULL,  FLAG_GLOBAL},
775   {"oplocks",          P_BOOL,    P_LOCAL,  &sDefault.bOpLocks,         NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
776   {"level2 oplocks",   P_BOOL,    P_LOCAL,  &sDefault.bLevel2OpLocks,   NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
777   {"oplock break wait time",P_INTEGER,P_GLOBAL,&Globals.oplock_break_wait_time,NULL,NULL,FLAG_GLOBAL},
778   {"oplock contention limit",P_INTEGER,P_LOCAL,&sDefault.iOplockContentionLimit,NULL,NULL,FLAG_SHARE|FLAG_GLOBAL},
779   {"strict locking",   P_BOOL,    P_LOCAL,  &sDefault.bStrictLocking,   NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
780   {"share modes",      P_BOOL,    P_LOCAL,  &sDefault.bShareModes,      NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
781
782 #ifdef WITH_LDAP
783   {"Ldap Options", P_SEP, P_SEPARATOR},
784   {"ldap server",      P_STRING,  P_GLOBAL, &Globals.szLdapServer,      NULL,   NULL,  0},
785   {"ldap port",        P_INTEGER, P_GLOBAL, &Globals.ldap_port,         NULL,   NULL,  0},
786   {"ldap suffix",      P_STRING,  P_GLOBAL, &Globals.szLdapSuffix,      NULL,   NULL,  0},
787   {"ldap filter",      P_STRING,  P_GLOBAL, &Globals.szLdapFilter,      NULL,   NULL,  0},
788   {"ldap root",        P_STRING,  P_GLOBAL, &Globals.szLdapRoot,        NULL,   NULL,  0},
789   {"ldap root passwd", P_STRING,  P_GLOBAL, &Globals.szLdapRootPassword,NULL,   NULL,  0},
790 #endif /* WITH_LDAP */
791
792
793   {"Miscellaneous Options", P_SEP, P_SEPARATOR},
794   {"smbrun",           P_STRING,  P_GLOBAL, &Globals.szSmbrun,          NULL,   NULL,  0},
795   {"config file",      P_STRING,  P_GLOBAL, &Globals.szConfigFile,      NULL,   NULL,  FLAG_HIDE},
796   {"preload",          P_STRING,  P_GLOBAL, &Globals.szAutoServices,    NULL,   NULL,  0},
797   {"auto services",    P_STRING,  P_GLOBAL, &Globals.szAutoServices,    NULL,   NULL,  0},
798   {"lock dir",         P_STRING,  P_GLOBAL, &Globals.szLockDir,         NULL,   NULL,  0},
799   {"lock directory",   P_STRING,  P_GLOBAL, &Globals.szLockDir,         NULL,   NULL,  0},
800   {"default service",  P_STRING,  P_GLOBAL, &Globals.szDefaultService,  NULL,   NULL,  0},
801   {"default",          P_STRING,  P_GLOBAL, &Globals.szDefaultService,  NULL,   NULL,  0},
802   {"message command",  P_STRING,  P_GLOBAL, &Globals.szMsgCommand,      NULL,   NULL,  0},
803   {"dfree command",    P_STRING,  P_GLOBAL, &Globals.szDfree,           NULL,   NULL,  0},
804   {"valid chars",      P_STRING,  P_GLOBAL, &Globals.szValidChars,      handle_valid_chars, NULL,  0},
805   {"remote announce",  P_STRING,  P_GLOBAL, &Globals.szRemoteAnnounce,  NULL,   NULL,  0},
806   {"remote browse sync",P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync,NULL,   NULL,  0},
807   {"socket address",   P_STRING,  P_GLOBAL, &Globals.szSocketAddress,   NULL,   NULL,  0},
808   {"homedir map",      P_STRING,  P_GLOBAL, &Globals.szNISHomeMapName,  NULL,   NULL,  0},
809   {"time offset",      P_INTEGER, P_GLOBAL, &extra_time_offset,         NULL,   NULL,  0},
810   {"unix realname",    P_BOOL,    P_GLOBAL, &Globals.bUnixRealname,     NULL,   NULL,  0},
811   {"NIS homedir",      P_BOOL,    P_GLOBAL, &Globals.bNISHomeMap,       NULL,   NULL,  0},
812   {"-valid",           P_BOOL,    P_LOCAL,  &sDefault.valid,            NULL,   NULL,  FLAG_HIDE},
813   {"copy",             P_STRING,  P_LOCAL,  &sDefault.szCopy,           handle_copy, NULL,  FLAG_HIDE},
814   {"include",          P_STRING,  P_LOCAL,  &sDefault.szInclude,        handle_include, NULL,  FLAG_HIDE},
815   {"exec",             P_STRING,  P_LOCAL,  &sDefault.szPreExec,        NULL,   NULL,  FLAG_SHARE|FLAG_PRINT},
816   {"preexec",          P_STRING,  P_LOCAL,  &sDefault.szPreExec,        NULL,   NULL,  0},
817   {"preexec close",    P_BOOL,    P_LOCAL,  &sDefault.bPreexecClose,    NULL,   NULL,  0},
818   {"postexec",         P_STRING,  P_LOCAL,  &sDefault.szPostExec,       NULL,   NULL,  FLAG_SHARE|FLAG_PRINT},
819   {"root preexec",     P_STRING,  P_LOCAL,  &sDefault.szRootPreExec,    NULL,   NULL,  FLAG_SHARE|FLAG_PRINT},
820   {"root preexec close", P_BOOL,  P_LOCAL,  &sDefault.bRootpreexecClose,NULL,   NULL,  0},
821   {"root postexec",    P_STRING,  P_LOCAL,  &sDefault.szRootPostExec,   NULL,   NULL,  FLAG_SHARE|FLAG_PRINT},
822   {"available",        P_BOOL,    P_LOCAL,  &sDefault.bAvailable,       NULL,   NULL,  FLAG_BASIC|FLAG_SHARE|FLAG_PRINT},
823   {"volume",           P_STRING,  P_LOCAL,  &sDefault.volume,           NULL,   NULL,  FLAG_SHARE},
824   {"fstype",           P_STRING,  P_LOCAL,  &sDefault.fstype,           NULL,   NULL,  FLAG_SHARE},
825   {"set directory",    P_BOOLREV, P_LOCAL,  &sDefault.bNo_set_dir,      NULL,   NULL,  FLAG_SHARE},
826   {"wide links",       P_BOOL,    P_LOCAL,  &sDefault.bWidelinks,       NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
827   {"follow symlinks",  P_BOOL,    P_LOCAL,  &sDefault.bSymlinks,        NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
828   {"dont descend",     P_STRING,  P_LOCAL,  &sDefault.szDontdescend,    NULL,   NULL,  FLAG_SHARE},
829   {"magic script",     P_STRING,  P_LOCAL,  &sDefault.szMagicScript,    NULL,   NULL,  FLAG_SHARE},
830   {"magic output",     P_STRING,  P_LOCAL,  &sDefault.szMagicOutput,    NULL,   NULL,  FLAG_SHARE},
831   {"delete readonly",  P_BOOL,    P_LOCAL,  &sDefault.bDeleteReadonly,  NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
832   {"dos filetimes",    P_BOOL,    P_LOCAL,  &sDefault.bDosFiletimes,    NULL,   NULL,  FLAG_SHARE|FLAG_GLOBAL},
833   {"dos filetime resolution",P_BOOL,P_LOCAL,&sDefault.bDosFiletimeResolution,   NULL,  NULL,  FLAG_SHARE|FLAG_GLOBAL},
834   
835   {"fake directory create times", P_BOOL,P_LOCAL,  &sDefault.bFakeDirCreateTimes, NULL,   NULL, FLAG_SHARE|FLAG_GLOBAL},
836   {"panic action",     P_STRING,  P_GLOBAL, &Globals.szPanicAction,     NULL,   NULL,  0},
837
838   {NULL,               P_BOOL,    P_NONE,   NULL,                       NULL,   NULL, 0}
839 };
840
841
842
843 /***************************************************************************
844 Initialise the global parameter structure.
845 ***************************************************************************/
846 static void init_globals(void)
847 {
848   static BOOL done_init = False;
849   pstring s;
850
851   if (!done_init)
852     {
853       int i;
854       memset((void *)&Globals,'\0',sizeof(Globals));
855
856       for (i = 0; parm_table[i].label; i++) 
857         if ((parm_table[i].type == P_STRING ||
858              parm_table[i].type == P_USTRING) && 
859             parm_table[i].ptr)
860           string_init(parm_table[i].ptr,"");
861
862       string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
863       string_set(&sDefault.szPrinterDriver, "NULL");
864       string_set(&sDefault.fstype, FSTYPE_STRING);
865
866       done_init = True;
867     }
868
869
870   DEBUG(3,("Initialising global parameters\n"));
871
872   string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
873   /*
874    * Allow the default PASSWD_CHAT to be overridden in local.h.
875    */
876   string_set(&Globals.szPasswdChat,DEFAULT_PASSWD_CHAT);
877   string_set(&Globals.szWorkGroup, WORKGROUP);
878   string_set(&Globals.szPasswdProgram, PASSWD_PROGRAM);
879   string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
880   string_set(&Globals.szDriverFile, DRIVERFILE);
881   string_set(&Globals.szLockDir, LOCKDIR);
882   string_set(&Globals.szRootdir, "/");
883   string_set(&Globals.szSmbrun, SMBRUN);
884   string_set(&Globals.szSocketAddress, "0.0.0.0");
885   pstrcpy(s, "Samba ");
886   pstrcat(s, VERSION);
887   string_set(&Globals.szServerString,s);
888   slprintf(s,sizeof(s)-1, "%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION);
889   string_set(&Globals.szAnnounceVersion,s);
890
891   pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
892
893   string_set(&Globals.szLogonDrive, "");
894   /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
895   string_set(&Globals.szLogonHome, "\\\\%N\\%U");
896   string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
897
898   string_set(&Globals.szNameResolveOrder, "lmhosts host wins bcast");
899
900   Globals.bLoadPrinters = True;
901   Globals.bUseRhosts = False;
902   Globals.max_packet = 65535;
903   Globals.mangled_stack = 50;
904   Globals.max_xmit = 65535;
905   Globals.max_mux = 50; /* This is *needed* for profile support. */
906   Globals.lpqcachetime = 10;
907   Globals.pwordlevel = 0;
908   Globals.unamelevel = 0;
909   Globals.deadtime = 0;
910   Globals.max_log_size = 5000;
911   Globals.max_open_files = MAX_OPEN_FILES;
912   Globals.maxprotocol = PROTOCOL_NT1;
913   Globals.security = SEC_USER;
914   Globals.bEncryptPasswords = False;
915   Globals.bUpdateEncrypt = False;
916   Globals.bReadRaw = True;
917   Globals.bWriteRaw = True;
918   Globals.bReadPrediction = False;
919   Globals.bReadbmpx = False;
920   Globals.bNullPasswords = False;
921   Globals.bStripDot = False;
922   Globals.syslog = 1;
923   Globals.bSyslogOnly = False;
924   Globals.bTimestampLogs = True;
925   Globals.bDebugHiresTimestamp = False;
926   Globals.bDebugPid = False;
927   Globals.bDebugUid = False;
928   Globals.max_ttl = 60*60*24*3; /* 3 days default. */
929   Globals.max_wins_ttl = 60*60*24*6; /* 6 days default. */
930   Globals.min_wins_ttl = 60*60*6; /* 6 hours default. */
931   Globals.machine_password_timeout = 60*60*24*7; /* 7 days default. */
932   Globals.change_notify_timeout = 60; /* 1 minute default. */
933   Globals.ReadSize = 16*1024;
934   Globals.lm_announce = 2;   /* = Auto: send only if LM clients found */
935   Globals.lm_interval = 60;
936   Globals.shmem_size = SHMEM_SIZE;
937   Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */
938   Globals.announce_as = ANNOUNCE_AS_NT_SERVER;
939   Globals.bUnixRealname = False;
940 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
941   Globals.bNISHomeMap = False;
942 #ifdef WITH_NISPLUS_HOME
943   string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
944 #else
945   string_set(&Globals.szNISHomeMapName, "auto.home");
946 #endif
947 #endif
948   Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE;
949   Globals.bTimeServer = False;
950   Globals.bBindInterfacesOnly = False;
951   Globals.bUnixPasswdSync = False;
952   Globals.bPasswdChatDebug = False;
953   Globals.bOleLockingCompat = True;
954   Globals.bNTSmbSupport = True; /* Do NT SMB's by default. */
955   Globals.bNTPipeSupport = True; /* Do NT pipes by default. */
956   Globals.bNTAclSupport = True; /* Use NT ACLs by default. */
957   Globals.bStatCache = True; /* use stat cache by default */
958   Globals.bRestrictAnonymous = False;
959   Globals.map_to_guest = 0; /* By Default, "Never" */
960   Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */
961   Globals.oplock_break_wait_time = 10; /* By Default, 10 msecs. */
962
963 #ifdef WITH_LDAP
964   /* default values for ldap */
965   string_set(&Globals.szLdapServer, "localhost");
966   Globals.ldap_port=389;
967 #endif /* WITH_LDAP */
968
969 #ifdef WITH_SSL
970   Globals.sslVersion = SMB_SSL_V23;
971   string_set(&Globals.sslHostsRequire, "");
972   string_set(&Globals.sslHostsResign, "");
973   string_set(&Globals.sslCaCertDir, "");
974   string_set(&Globals.sslCaCertFile, "");
975   string_set(&Globals.sslCert, "");
976   string_set(&Globals.sslPrivKey, "");
977   string_set(&Globals.sslClientCert, "");
978   string_set(&Globals.sslClientPrivKey, "");
979   string_set(&Globals.sslCiphers, "");
980   Globals.sslEnabled = False;
981   Globals.sslReqClientCert = False;
982   Globals.sslReqServerCert = False;
983   Globals.sslCompatibility = False;
984 #endif        /* WITH_SSL */
985
986 /* these parameters are set to defaults that are more appropriate
987    for the increasing samba install base:
988
989    as a member of the workgroup, that will possibly become a
990    _local_ master browser (lm = True).  this is opposed to a forced
991    local master browser startup (pm = True).
992
993    doesn't provide WINS server service by default (wsupp = False),
994    and doesn't provide domain master browser services by default, either.
995
996 */
997
998   Globals.os_level = 20;
999   Globals.bPreferredMaster = False;
1000   Globals.bLocalMaster = True;
1001   Globals.bDomainMaster = False;
1002   Globals.bDomainLogons = False;
1003   Globals.bBrowseList = True;
1004   Globals.bWINSsupport = False;
1005   Globals.bWINSproxy = False;
1006
1007   Globals.bDNSproxy = True;
1008
1009   /*
1010    * smbd will check at runtime to see if this value
1011    * will really be used or not.
1012    */
1013   Globals.bKernelOplocks = True;
1014
1015   Globals.bAllowTrustedDomains = True;
1016
1017   /*
1018    * This must be done last as it checks the value in 
1019    * client_code_page.
1020    */
1021
1022   interpret_coding_system(KANJI);
1023 }
1024
1025 /***************************************************************************
1026 check if a string is initialised and if not then initialise it
1027 ***************************************************************************/
1028 static void string_initial(char **s,char *v)
1029 {
1030   if (!*s || !**s)
1031     string_init(s,v);
1032 }
1033
1034
1035 /***************************************************************************
1036 Initialise the sDefault parameter structure.
1037 ***************************************************************************/
1038 static void init_locals(void)
1039 {
1040   /* choose defaults depending on the type of printing */
1041   switch (sDefault.iPrinting)
1042     {
1043     case PRINT_BSD:
1044     case PRINT_AIX:
1045     case PRINT_LPRNG:
1046     case PRINT_PLP:
1047       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
1048       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
1049       string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
1050       break;
1051
1052     case PRINT_CUPS:
1053       string_initial(&sDefault.szLpqcommand,"/usr/bin/lpstat -o%p");
1054       string_initial(&sDefault.szLprmcommand,"/usr/bin/cancel %p-%j");
1055       string_initial(&sDefault.szPrintcommand,"/usr/bin/lp -d%p -oraw %s; rm %s");
1056       string_initial(&sDefault.szQueuepausecommand, "/usr/bin/disable %p");
1057       string_initial(&sDefault.szQueueresumecommand, "/usr/bin/enable %p");
1058       break;
1059
1060     case PRINT_SYSV:
1061     case PRINT_HPUX:
1062       string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
1063       string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
1064       string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
1065 #ifdef HPUX
1066       string_initial(&sDefault.szQueuepausecommand, "disable %p");
1067       string_initial(&sDefault.szQueueresumecommand, "enable %p");
1068 #else /* SYSV */
1069       string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
1070       string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
1071       string_initial(&sDefault.szQueuepausecommand, "lpc stop %p");
1072       string_initial(&sDefault.szQueueresumecommand, "lpc start %p");
1073 #endif /* SYSV */
1074       break;
1075
1076     case PRINT_QNX:
1077       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
1078       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
1079       string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
1080       break;
1081
1082     case PRINT_SOFTQ:
1083       string_initial(&sDefault.szLpqcommand,"qstat -l -d%p");
1084       string_initial(&sDefault.szLprmcommand,"qstat -s -j%j -c");
1085       string_initial(&sDefault.szPrintcommand,"lp -d%p -s %s; rm %s");
1086       string_initial(&sDefault.szLppausecommand,"qstat -s -j%j -h");
1087       string_initial(&sDefault.szLpresumecommand,"qstat -s -j%j -r");
1088       break;
1089       
1090     }
1091 }
1092
1093
1094 /******************************************************************* a
1095 convenience routine to grab string parameters into a rotating buffer,
1096 and run standard_sub_basic on them. The buffers can be written to by
1097 callers without affecting the source string.
1098 ********************************************************************/
1099 static char *lp_string(const char *s)
1100 {
1101   static char *bufs[10];
1102   static size_t buflen[10];
1103   static int next = -1;  
1104   char *ret;
1105   int i;
1106   size_t len = s?strlen(s):0;
1107
1108   if (next == -1) {
1109     /* initialisation */
1110     for (i=0;i<10;i++) {
1111       bufs[i] = NULL;
1112       buflen[i] = 0;
1113     }
1114     next = 0;
1115   }
1116
1117   len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
1118                                          substitution room */
1119
1120   if (buflen[next] != len) {
1121     buflen[next] = len;
1122     if (bufs[next])
1123       free(bufs[next]);
1124     bufs[next] = (char *)malloc(len);
1125     if (!bufs[next]) {
1126       DEBUG(0,("out of memory in lp_string()"));
1127       exit(1);
1128     }
1129   } 
1130
1131   ret = &bufs[next][0];
1132   next = (next+1)%10;
1133
1134   if (!s) 
1135     *ret = 0;
1136   else
1137     StrnCpy(ret,s,len-1);
1138
1139   trim_string(ret, "\"", "\"");
1140
1141   standard_sub_basic(ret);
1142   return(ret);
1143 }
1144
1145
1146 /*
1147    In this section all the functions that are used to access the 
1148    parameters from the rest of the program are defined 
1149 */
1150
1151 #define FN_GLOBAL_STRING(fn_name,ptr) \
1152  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1153 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1154  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1155 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1156  char fn_name(void) {return(*(char *)(ptr));}
1157 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1158  int fn_name(void) {return(*(int *)(ptr));}
1159
1160 #define FN_LOCAL_STRING(fn_name,val) \
1161  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
1162 #define FN_LOCAL_BOOL(fn_name,val) \
1163  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1164 #define FN_LOCAL_CHAR(fn_name,val) \
1165  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1166 #define FN_LOCAL_INTEGER(fn_name,val) \
1167  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1168
1169 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
1170 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
1171 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
1172 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
1173 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
1174 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
1175 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
1176 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
1177 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
1178 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
1179 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
1180 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
1181 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
1182 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
1183 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
1184 FN_GLOBAL_STRING(lp_name_resolve_order,&Globals.szNameResolveOrder)
1185 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
1186 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
1187 #ifdef USING_GROUPNAME_MAP
1188 FN_GLOBAL_STRING(lp_groupname_map,&Globals.szGroupnameMap)
1189 #endif /* USING_GROUPNAME_MAP */
1190 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) 
1191 FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) 
1192 FN_GLOBAL_STRING(lp_logon_drive,&Globals.szLogonDrive) 
1193 FN_GLOBAL_STRING(lp_logon_home,&Globals.szLogonHome) 
1194 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) 
1195 FN_GLOBAL_STRING(lp_remote_browse_sync,&Globals.szRemoteBrowseSync) 
1196 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
1197 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
1198 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
1199 FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName)
1200 static FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion)
1201 FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases)
1202 FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile)
1203 FN_GLOBAL_STRING(lp_panic_action,&Globals.szPanicAction)
1204 FN_GLOBAL_STRING(lp_adduser_script,&Globals.szAddUserScript)
1205 FN_GLOBAL_STRING(lp_deluser_script,&Globals.szDelUserScript)
1206 FN_GLOBAL_STRING(lp_wins_hook,&Globals.szWINSHook)
1207
1208 FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups)
1209 FN_GLOBAL_STRING(lp_domain_admin_group,&Globals.szDomainAdminGroup)
1210 FN_GLOBAL_STRING(lp_domain_guest_group,&Globals.szDomainGuestGroup)
1211 FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers)
1212 FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers)
1213
1214 #ifdef WITH_LDAP
1215 FN_GLOBAL_STRING(lp_ldap_server,&Globals.szLdapServer);
1216 FN_GLOBAL_STRING(lp_ldap_suffix,&Globals.szLdapSuffix);
1217 FN_GLOBAL_STRING(lp_ldap_filter,&Globals.szLdapFilter);
1218 FN_GLOBAL_STRING(lp_ldap_root,&Globals.szLdapRoot);
1219 FN_GLOBAL_STRING(lp_ldap_rootpasswd,&Globals.szLdapRootPassword);
1220 #endif /* WITH_LDAP */
1221
1222 #ifdef WITH_SSL
1223 FN_GLOBAL_INTEGER(lp_ssl_version,&Globals.sslVersion);
1224 FN_GLOBAL_STRING(lp_ssl_hosts,&Globals.sslHostsRequire);
1225 FN_GLOBAL_STRING(lp_ssl_hosts_resign,&Globals.sslHostsResign);
1226 FN_GLOBAL_STRING(lp_ssl_cacertdir,&Globals.sslCaCertDir);
1227 FN_GLOBAL_STRING(lp_ssl_cacertfile,&Globals.sslCaCertFile);
1228 FN_GLOBAL_STRING(lp_ssl_cert,&Globals.sslCert);
1229 FN_GLOBAL_STRING(lp_ssl_privkey,&Globals.sslPrivKey);
1230 FN_GLOBAL_STRING(lp_ssl_client_cert,&Globals.sslClientCert);
1231 FN_GLOBAL_STRING(lp_ssl_client_privkey,&Globals.sslClientPrivKey);
1232 FN_GLOBAL_STRING(lp_ssl_ciphers,&Globals.sslCiphers);
1233 FN_GLOBAL_BOOL(lp_ssl_enabled,&Globals.sslEnabled);
1234 FN_GLOBAL_BOOL(lp_ssl_reqClientCert,&Globals.sslReqClientCert);
1235 FN_GLOBAL_BOOL(lp_ssl_reqServerCert,&Globals.sslReqServerCert);
1236 FN_GLOBAL_BOOL(lp_ssl_compatibility,&Globals.sslCompatibility);
1237 #endif        /* WITH_SSL */
1238
1239 FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
1240 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
1241 FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport)
1242 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
1243 FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
1244 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
1245 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
1246 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
1247 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
1248 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
1249 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
1250 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
1251 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
1252 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
1253 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
1254 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
1255 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
1256 FN_GLOBAL_BOOL(lp_update_encrypted,&Globals.bUpdateEncrypt)
1257 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
1258 FN_GLOBAL_BOOL(lp_timestamp_logs,&Globals.bTimestampLogs)
1259 FN_GLOBAL_BOOL(lp_debug_hires_timestamp,&Globals.bDebugHiresTimestamp)
1260 FN_GLOBAL_BOOL(lp_debug_pid,&Globals.bDebugPid)
1261 FN_GLOBAL_BOOL(lp_debug_uid,&Globals.bDebugUid)
1262 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
1263 FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
1264 FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
1265 static FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
1266 FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
1267 FN_GLOBAL_BOOL(lp_unix_password_sync,&Globals.bUnixPasswdSync)
1268 FN_GLOBAL_BOOL(lp_passwd_chat_debug,&Globals.bPasswdChatDebug)
1269 FN_GLOBAL_BOOL(lp_ole_locking_compat,&Globals.bOleLockingCompat)
1270 FN_GLOBAL_BOOL(lp_nt_smb_support,&Globals.bNTSmbSupport)
1271 FN_GLOBAL_BOOL(lp_nt_pipe_support,&Globals.bNTPipeSupport)
1272 FN_GLOBAL_BOOL(lp_nt_acl_support,&Globals.bNTAclSupport)
1273 FN_GLOBAL_BOOL(lp_stat_cache,&Globals.bStatCache)
1274 FN_GLOBAL_BOOL(lp_allow_trusted_domains,&Globals.bAllowTrustedDomains)
1275 FN_GLOBAL_BOOL(lp_restrict_anonymous,&Globals.bRestrictAnonymous)
1276
1277 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
1278 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
1279 FN_GLOBAL_INTEGER(lp_max_wins_ttl,&Globals.max_wins_ttl)
1280 FN_GLOBAL_INTEGER(lp_min_wins_ttl,&Globals.max_wins_ttl)
1281 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
1282 FN_GLOBAL_INTEGER(lp_max_open_files,&Globals.max_open_files)
1283 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
1284 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
1285 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
1286 FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel)
1287 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
1288 FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
1289 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
1290 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
1291 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
1292 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
1293 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
1294 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
1295 FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
1296 static FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
1297 FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
1298 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
1299 FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
1300 FN_GLOBAL_INTEGER(lp_change_notify_timeout,&Globals.change_notify_timeout)
1301 FN_GLOBAL_INTEGER(lp_stat_cache_size,&Globals.stat_cache_size)
1302 FN_GLOBAL_INTEGER(lp_map_to_guest,&Globals.map_to_guest)
1303 FN_GLOBAL_INTEGER(lp_min_passwd_length,&Globals.min_passwd_length)
1304 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time,&Globals.oplock_break_wait_time)
1305
1306 #ifdef WITH_LDAP
1307 FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)
1308 #endif /* WITH_LDAP */
1309
1310 FN_LOCAL_STRING(lp_preexec,szPreExec)
1311 FN_LOCAL_STRING(lp_postexec,szPostExec)
1312 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
1313 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
1314 FN_LOCAL_STRING(lp_servicename,szService)
1315 FN_LOCAL_STRING(lp_pathname,szPath)
1316 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
1317 FN_LOCAL_STRING(lp_username,szUsername)
1318 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
1319 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
1320 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
1321 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
1322 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
1323 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
1324 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
1325 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
1326 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
1327 FN_LOCAL_STRING(lp_queuepausecommand,szQueuepausecommand)
1328 FN_LOCAL_STRING(lp_queueresumecommand,szQueueresumecommand)
1329 FN_LOCAL_STRING(lp_printername,szPrintername)
1330 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
1331 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
1332 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
1333 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
1334 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
1335 FN_LOCAL_STRING(lp_comment,comment)
1336 FN_LOCAL_STRING(lp_force_user,force_user)
1337 FN_LOCAL_STRING(lp_force_group,force_group)
1338 FN_LOCAL_STRING(lp_readlist,readlist)
1339 FN_LOCAL_STRING(lp_writelist,writelist)
1340 FN_LOCAL_STRING(lp_fstype,fstype)
1341 static FN_LOCAL_STRING(lp_volume,volume)
1342 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
1343 FN_LOCAL_STRING(lp_veto_files,szVetoFiles)
1344 FN_LOCAL_STRING(lp_hide_files,szHideFiles)
1345 FN_LOCAL_STRING(lp_veto_oplocks,szVetoOplockFiles)
1346 FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
1347
1348 FN_LOCAL_BOOL(lp_preexec_close,bPreexecClose)
1349 FN_LOCAL_BOOL(lp_rootpreexec_close,bRootpreexecClose)
1350 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
1351 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
1352 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
1353 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
1354 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
1355 FN_LOCAL_BOOL(lp_status,status)
1356 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
1357 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
1358 FN_LOCAL_BOOL(lp_readonly,bRead_only)
1359 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
1360 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
1361 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
1362 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
1363 FN_LOCAL_BOOL(lp_postscript,bPostscript)
1364 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
1365 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
1366 FN_LOCAL_BOOL(lp_locking,bLocking)
1367 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
1368 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
1369 FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
1370 FN_LOCAL_BOOL(lp_level2_oplocks,bLevel2OpLocks)
1371 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
1372 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
1373 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
1374 FN_LOCAL_BOOL(lp_symlinks,bSymlinks)
1375 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
1376 FN_LOCAL_BOOL(lp_strict_sync,bStrictSync)
1377 FN_LOCAL_BOOL(lp_map_system,bMap_system)
1378 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
1379 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
1380 FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
1381 FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
1382 FN_LOCAL_BOOL(lp_dos_filetime_resolution,bDosFiletimeResolution)
1383 FN_LOCAL_BOOL(lp_fake_dir_create_times,bFakeDirCreateTimes)
1384 FN_LOCAL_BOOL(lp_blocking_locks,bBlockingLocks)
1385
1386 FN_LOCAL_INTEGER(lp_create_mask,iCreate_mask)
1387 FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)
1388 FN_LOCAL_INTEGER(_lp_security_mask,iSecurity_mask)
1389 FN_LOCAL_INTEGER(_lp_force_security_mode,iSecurity_force_mode)
1390 FN_LOCAL_INTEGER(lp_dir_mask,iDir_mask)
1391 FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode)
1392 FN_LOCAL_INTEGER(_lp_dir_security_mask,iDir_Security_mask)
1393 FN_LOCAL_INTEGER(_lp_force_dir_security_mode,iDir_Security_force_mode)
1394 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
1395 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
1396 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
1397 FN_LOCAL_INTEGER(lp_printing,iPrinting)
1398 FN_LOCAL_INTEGER(lp_oplock_contention_limit,iOplockContentionLimit)
1399 FN_LOCAL_INTEGER(lp_write_cache_size,iWriteCacheSize)
1400
1401 FN_LOCAL_CHAR(lp_magicchar,magic_char)
1402
1403
1404
1405 /* local prototypes */
1406 static int    strwicmp( char *psz1, char *psz2 );
1407 static int    map_parameter( char *pszParmName);
1408 static BOOL   set_boolean( BOOL *pb, char *pszParmValue );
1409 static int    getservicebyname(char *pszServiceName, service *pserviceDest);
1410 static void   copy_service( service *pserviceDest, 
1411                             service *pserviceSource,
1412                             BOOL *pcopymapDest );
1413 static BOOL   service_ok(int iService);
1414 static BOOL   do_parameter(char *pszParmName, char *pszParmValue);
1415 static BOOL   do_section(char *pszSectionName);
1416 static void init_copymap(service *pservice);
1417
1418
1419 /***************************************************************************
1420 initialise a service to the defaults
1421 ***************************************************************************/
1422 static void init_service(service *pservice)
1423 {
1424   memset((char *)pservice,'\0',sizeof(service));
1425   copy_service(pservice,&sDefault,NULL);
1426 }
1427
1428
1429 /***************************************************************************
1430 free the dynamically allocated parts of a service struct
1431 ***************************************************************************/
1432 static void free_service(service *pservice)
1433 {
1434   int i;
1435   if (!pservice)
1436      return;
1437
1438   if(pservice->szService)
1439     DEBUG(5,("free_service: Freeing service %s\n", pservice->szService));
1440
1441   string_free(&pservice->szService);
1442   if (pservice->copymap)
1443   {
1444     free(pservice->copymap);
1445     pservice->copymap = NULL;
1446   }
1447  
1448   for (i=0;parm_table[i].label;i++)
1449     if ((parm_table[i].type == P_STRING ||
1450          parm_table[i].type == P_USTRING) &&
1451         parm_table[i].class == P_LOCAL)
1452       string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
1453 }
1454
1455 /***************************************************************************
1456 add a new service to the services array initialising it with the given 
1457 service
1458 ***************************************************************************/
1459 static int add_a_service(service *pservice, char *name)
1460 {
1461   int i;
1462   service tservice;
1463   int num_to_alloc = iNumServices+1;
1464
1465   tservice = *pservice;
1466
1467   /* it might already exist */
1468   if (name) 
1469     {
1470       i = getservicebyname(name,NULL);
1471       if (i >= 0)
1472         return(i);
1473     }
1474
1475   /* find an invalid one */
1476   for (i=0;i<iNumServices;i++)
1477     if (!pSERVICE(i)->valid)
1478       break;
1479
1480   /* if not, then create one */
1481   if (i == iNumServices)
1482     {
1483       ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
1484       if (ServicePtrs)
1485         pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
1486
1487       if (!ServicePtrs || !pSERVICE(iNumServices))
1488         return(-1);
1489
1490       iNumServices++;
1491     }
1492   else
1493     free_service(pSERVICE(i));
1494
1495   pSERVICE(i)->valid = True;
1496
1497   init_service(pSERVICE(i));
1498   copy_service(pSERVICE(i),&tservice,NULL);
1499   if (name) {
1500     string_set(&iSERVICE(i).szService,name);  
1501     unix_to_dos(iSERVICE(i).szService, True);
1502   }
1503   return(i);
1504 }
1505
1506 /***************************************************************************
1507 add a new home service, with the specified home directory, defaults coming 
1508 from service ifrom
1509 ***************************************************************************/
1510 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
1511 {
1512   int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
1513
1514   if (i < 0)
1515     return(False);
1516
1517   if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
1518     string_set(&iSERVICE(i).szPath,pszHomedir);
1519   if (!(*(iSERVICE(i).comment)))
1520     {
1521       pstring comment;
1522       slprintf(comment,sizeof(comment)-1,
1523                "Home directory of %s",pszHomename);
1524       string_set(&iSERVICE(i).comment,comment);
1525     }
1526   iSERVICE(i).bAvailable = sDefault.bAvailable;
1527   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1528
1529   DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
1530
1531   return(True);
1532 }
1533
1534 /***************************************************************************
1535 add a new service, based on an old one
1536 ***************************************************************************/
1537 int lp_add_service(char *pszService, int iDefaultService)
1538 {
1539   return(add_a_service(pSERVICE(iDefaultService),pszService));
1540 }
1541
1542
1543 /***************************************************************************
1544 add the IPC service
1545 ***************************************************************************/
1546 static BOOL lp_add_ipc(void)
1547 {
1548   pstring comment;
1549   int i = add_a_service(&sDefault,"IPC$");
1550
1551   if (i < 0)
1552     return(False);
1553
1554   slprintf(comment,sizeof(comment)-1,
1555            "IPC Service (%s)", Globals.szServerString );
1556
1557   string_set(&iSERVICE(i).szPath,tmpdir());
1558   string_set(&iSERVICE(i).szUsername,"");
1559   string_set(&iSERVICE(i).comment,comment);
1560   string_set(&iSERVICE(i).fstype,"IPC");
1561   iSERVICE(i).status = False;
1562   iSERVICE(i).iMaxConnections = 0;
1563   iSERVICE(i).bAvailable = True;
1564   iSERVICE(i).bRead_only = True;
1565   iSERVICE(i).bGuest_only = False;
1566   iSERVICE(i).bGuest_ok = True;
1567   iSERVICE(i).bPrint_ok = False;
1568   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1569
1570   DEBUG(3,("adding IPC service\n"));
1571
1572   return(True);
1573 }
1574
1575
1576 /***************************************************************************
1577 add a new printer service, with defaults coming from service iFrom
1578 ***************************************************************************/
1579 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1580 {
1581   char *comment = "From Printcap";
1582   int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1583   
1584   if (i < 0)
1585     return(False);
1586   
1587   /* note that we do NOT default the availability flag to True - */
1588   /* we take it from the default service passed. This allows all */
1589   /* dynamic printers to be disabled by disabling the [printers] */
1590   /* entry (if/when the 'available' keyword is implemented!).    */
1591   
1592   /* the printer name is set to the service name. */
1593   string_set(&iSERVICE(i).szPrintername,pszPrintername);
1594   string_set(&iSERVICE(i).comment,comment);
1595   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1596   /* Printers cannot be read_only. */
1597   iSERVICE(i).bRead_only = False;
1598   /* No share modes on printer services. */
1599   iSERVICE(i).bShareModes = False;
1600   /* No oplocks on printer services. */
1601   iSERVICE(i).bOpLocks = False;
1602   /* Printer services must be printable. */
1603   iSERVICE(i).bPrint_ok = True;
1604   
1605   DEBUG(3,("adding printer service %s\n",pszPrintername));
1606   
1607   return(True);
1608 }
1609
1610
1611 /***************************************************************************
1612 Do a case-insensitive, whitespace-ignoring string compare.
1613 ***************************************************************************/
1614 static int strwicmp(char *psz1, char *psz2)
1615 {
1616    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1617    /* appropriate value. */
1618    if (psz1 == psz2)
1619       return (0);
1620    else
1621       if (psz1 == NULL)
1622          return (-1);
1623       else
1624           if (psz2 == NULL)
1625               return (1);
1626
1627    /* sync the strings on first non-whitespace */
1628    while (1)
1629    {
1630       while (isspace(*psz1))
1631          psz1++;
1632       while (isspace(*psz2))
1633          psz2++;
1634       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1635          break;
1636       psz1++;
1637       psz2++;
1638    }
1639    return (*psz1 - *psz2);
1640 }
1641
1642 /***************************************************************************
1643 Map a parameter's string representation to something we can use. 
1644 Returns False if the parameter string is not recognised, else TRUE.
1645 ***************************************************************************/
1646 static int map_parameter(char *pszParmName)
1647 {
1648    int iIndex;
1649
1650    if (*pszParmName == '-')
1651      return(-1);
1652
1653    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
1654       if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1655          return(iIndex);
1656
1657    DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1658    return(-1);
1659 }
1660
1661
1662 /***************************************************************************
1663 Set a boolean variable from the text value stored in the passed string.
1664 Returns True in success, False if the passed string does not correctly 
1665 represent a boolean.
1666 ***************************************************************************/
1667 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1668 {
1669    BOOL bRetval;
1670
1671    bRetval = True;
1672    if (strwicmp(pszParmValue, "yes") == 0 ||
1673        strwicmp(pszParmValue, "true") == 0 ||
1674        strwicmp(pszParmValue, "1") == 0)
1675       *pb = True;
1676    else
1677       if (strwicmp(pszParmValue, "no") == 0 ||
1678           strwicmp(pszParmValue, "False") == 0 ||
1679           strwicmp(pszParmValue, "0") == 0)
1680          *pb = False;
1681       else
1682       {
1683          DEBUG(0,("ERROR: Badly formed boolean in configuration file: \"%s\".\n",
1684                pszParmValue));
1685          bRetval = False;
1686       }
1687    return (bRetval);
1688 }
1689
1690 /***************************************************************************
1691 Find a service by name. Otherwise works like get_service.
1692 ***************************************************************************/
1693 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1694 {
1695    int iService;
1696
1697    for (iService = iNumServices - 1; iService >= 0; iService--)
1698       if (VALID(iService) &&
1699           strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) 
1700       {
1701          if (pserviceDest != NULL)
1702            copy_service(pserviceDest, pSERVICE(iService), NULL);
1703          break;
1704       }
1705
1706    return (iService);
1707 }
1708
1709
1710
1711 /***************************************************************************
1712 Copy a service structure to another
1713
1714 If pcopymapDest is NULL then copy all fields
1715 ***************************************************************************/
1716 static void copy_service(service *pserviceDest, 
1717                          service *pserviceSource,
1718                          BOOL *pcopymapDest)
1719 {
1720   int i;
1721   BOOL bcopyall = (pcopymapDest == NULL);
1722
1723   for (i=0;parm_table[i].label;i++)
1724     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && 
1725         (bcopyall || pcopymapDest[i]))
1726       {
1727         void *def_ptr = parm_table[i].ptr;
1728         void *src_ptr = 
1729           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1730         void *dest_ptr = 
1731           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1732
1733         switch (parm_table[i].type)
1734           {
1735           case P_BOOL:
1736           case P_BOOLREV:
1737             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1738             break;
1739
1740           case P_INTEGER:
1741           case P_ENUM:
1742           case P_OCTAL:
1743             *(int *)dest_ptr = *(int *)src_ptr;
1744             break;
1745
1746           case P_CHAR:
1747             *(char *)dest_ptr = *(char *)src_ptr;
1748             break;
1749
1750           case P_STRING:
1751             string_set(dest_ptr,*(char **)src_ptr);
1752             break;
1753
1754           case P_USTRING:
1755             string_set(dest_ptr,*(char **)src_ptr);
1756             strupper(*(char **)dest_ptr);
1757             break;
1758           default:
1759             break;
1760           }
1761       }
1762
1763   if (bcopyall)
1764     {
1765       init_copymap(pserviceDest);
1766       if (pserviceSource->copymap)
1767         memcpy((void *)pserviceDest->copymap,
1768                (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1769     }
1770 }
1771
1772 /***************************************************************************
1773 Check a service for consistency. Return False if the service is in any way
1774 incomplete or faulty, else True.
1775 ***************************************************************************/
1776 static BOOL service_ok(int iService)
1777 {
1778    BOOL bRetval;
1779
1780    bRetval = True;
1781    if (iSERVICE(iService).szService[0] == '\0')
1782    {
1783       DEBUG(0,( "The following message indicates an internal error:\n"));
1784       DEBUG(0,( "No service name in service entry.\n"));
1785       bRetval = False;
1786    }
1787
1788    /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1789    /* I can't see why you'd want a non-printable printer service...        */
1790    if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1791       if (!iSERVICE(iService).bPrint_ok)
1792       {
1793          DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1794                iSERVICE(iService).szService));
1795          iSERVICE(iService).bPrint_ok = True;
1796       }
1797
1798    if (iSERVICE(iService).szPath[0] == '\0' &&
1799        strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1800    {
1801       DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1802       string_set(&iSERVICE(iService).szPath,tmpdir());      
1803    }
1804
1805    /* If a service is flagged unavailable, log the fact at level 0. */
1806    if (!iSERVICE(iService).bAvailable) 
1807       DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1808             iSERVICE(iService).szService));
1809
1810    return (bRetval);
1811 }
1812
1813 static struct file_lists {
1814   struct file_lists *next;
1815   char *name;
1816   time_t modtime;
1817 } *file_lists = NULL;
1818
1819 /*******************************************************************
1820 keep a linked list of all config files so we know when one has changed 
1821 it's date and needs to be reloaded
1822 ********************************************************************/
1823 static void add_to_file_list(char *fname)
1824 {
1825   struct file_lists *f=file_lists;
1826
1827   while (f) {
1828     if (f->name && !strcmp(f->name,fname)) break;
1829     f = f->next;
1830   }
1831
1832   if (!f) {
1833     f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1834     if (!f) return;
1835     f->next = file_lists;
1836     f->name = strdup(fname);
1837     if (!f->name) {
1838       free(f);
1839       return;
1840     }
1841     file_lists = f;
1842   }
1843
1844   {
1845     pstring n2;
1846     pstrcpy(n2,fname);
1847     standard_sub_basic(n2);
1848     f->modtime = file_modtime(n2);
1849   }
1850
1851 }
1852
1853 /*******************************************************************
1854 check if a config file has changed date
1855 ********************************************************************/
1856 BOOL lp_file_list_changed(void)
1857 {
1858   struct file_lists *f = file_lists;
1859   DEBUG(6,("lp_file_list_changed()\n"));
1860
1861   while (f)
1862   {
1863     pstring n2;
1864     time_t mod_time;
1865
1866     pstrcpy(n2,f->name);
1867     standard_sub_basic(n2);
1868
1869     DEBUGADD( 6, ( "file %s -> %s  last mod_time: %s\n",
1870                    f->name, n2, ctime(&f->modtime) ) );
1871
1872     mod_time = file_modtime(n2);
1873
1874     if (f->modtime != mod_time) {
1875             DEBUGADD(6,("file %s modified: %s\n", n2, ctime(&mod_time)));
1876             f->modtime = mod_time;
1877             return(True);
1878     }
1879     f = f->next;
1880   }
1881   return(False);
1882 }
1883
1884 /***************************************************************************
1885   handle the interpretation of the coding system parameter
1886   *************************************************************************/
1887 static BOOL handle_coding_system(char *pszParmValue,char **ptr)
1888 {
1889         string_set(ptr,pszParmValue);
1890         interpret_coding_system(pszParmValue);
1891         return(True);
1892 }
1893
1894 /***************************************************************************
1895  Handle the interpretation of the character set system parameter.
1896 ***************************************************************************/
1897
1898 static char *saved_character_set = NULL;
1899
1900 static BOOL handle_character_set(char *pszParmValue,char **ptr)
1901 {
1902     /* A dependency here is that the parameter client code page should be
1903       set before this is called.
1904     */
1905         string_set(ptr,pszParmValue);
1906         strupper(*ptr);
1907         saved_character_set = strdup(*ptr);
1908         interpret_character_set(*ptr,lp_client_code_page());
1909         return(True);
1910 }
1911
1912 /***************************************************************************
1913  Handle the interpretation of the client code page parameter.
1914  We handle this separately so that we can reset the character set
1915  parameter in case this came before 'client code page' in the smb.conf.
1916 ***************************************************************************/
1917
1918 static BOOL handle_client_code_page(char *pszParmValue,char **ptr)
1919 {
1920         Globals.client_code_page = atoi(pszParmValue);
1921         if (saved_character_set != NULL)
1922                 interpret_character_set(saved_character_set,lp_client_code_page());     
1923         return(True);
1924 }
1925
1926 /***************************************************************************
1927 handle the valid chars lines
1928 ***************************************************************************/
1929
1930 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1931
1932   string_set(ptr,pszParmValue);
1933
1934   /* A dependency here is that the parameter client code page must be
1935      set before this is called - as calling codepage_initialise()
1936      would overwrite the valid char lines.
1937    */
1938   codepage_initialise(lp_client_code_page());
1939
1940   add_char_string(pszParmValue);
1941   return(True);
1942 }
1943
1944 /***************************************************************************
1945 handle the include operation
1946 ***************************************************************************/
1947
1948 static BOOL handle_include(char *pszParmValue,char **ptr)
1949
1950   pstring fname;
1951   pstrcpy(fname,pszParmValue);
1952
1953   add_to_file_list(fname);
1954
1955   standard_sub_basic(fname);
1956
1957   string_set(ptr,fname);
1958
1959   if (file_exist(fname,NULL))
1960     return(pm_process(fname, do_section, do_parameter));      
1961
1962   DEBUG(2,("Can't find include file %s\n",fname));
1963
1964   return(False);
1965 }
1966
1967
1968 /***************************************************************************
1969 handle the interpretation of the copy parameter
1970 ***************************************************************************/
1971 static BOOL handle_copy(char *pszParmValue,char **ptr)
1972 {
1973    BOOL bRetval;
1974    int iTemp;
1975    service serviceTemp;
1976
1977    string_set(ptr,pszParmValue);
1978
1979    init_service(&serviceTemp);
1980
1981    bRetval = False;
1982    
1983    DEBUG(3,("Copying service from service %s\n",pszParmValue));
1984
1985    if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1986      {
1987        if (iTemp == iServiceIndex)
1988          {
1989            DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1990                     pszParmValue));
1991          }
1992        else
1993          {
1994            copy_service(pSERVICE(iServiceIndex), 
1995                         &serviceTemp,
1996                         iSERVICE(iServiceIndex).copymap);
1997            bRetval = True;
1998          }
1999      }
2000    else
2001      {
2002        DEBUG(0,( "Unable to copy service - source not found: %s\n",
2003                 pszParmValue));
2004        bRetval = False;
2005      }
2006
2007    free_service(&serviceTemp);
2008    return (bRetval);
2009 }
2010
2011
2012 /***************************************************************************
2013 initialise a copymap
2014 ***************************************************************************/
2015 static void init_copymap(service *pservice)
2016 {
2017   int i;
2018   if (pservice->copymap) free(pservice->copymap);
2019   pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
2020   if (!pservice->copymap)
2021     DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",(int)NUMPARAMETERS));
2022   else
2023     for (i=0;i<NUMPARAMETERS;i++)
2024       pservice->copymap[i] = True;
2025 }
2026
2027
2028 /***************************************************************************
2029  return the local pointer to a parameter given the service number and the 
2030  pointer into the default structure
2031 ***************************************************************************/
2032 void *lp_local_ptr(int snum, void *ptr)
2033 {
2034         return (void *)(((char *)pSERVICE(snum)) + PTR_DIFF(ptr,&sDefault));
2035 }
2036
2037 /***************************************************************************
2038 Process a parameter for a particular service number. If snum < 0
2039 then assume we are in the globals
2040 ***************************************************************************/
2041 BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
2042 {
2043    int parmnum, i;
2044    void *parm_ptr=NULL; /* where we are going to store the result */
2045    void *def_ptr=NULL;
2046
2047    parmnum = map_parameter(pszParmName);
2048
2049    if (parmnum < 0)
2050      {
2051        DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
2052        return(True);
2053      }
2054
2055    if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
2056            DEBUG(1,("WARNING: The \"%s\"option is deprecated\n",
2057                     pszParmName));
2058    }
2059
2060    def_ptr = parm_table[parmnum].ptr;
2061
2062    /* we might point at a service, the default service or a global */
2063    if (snum < 0) {
2064      parm_ptr = def_ptr;
2065    } else {
2066        if (parm_table[parmnum].class == P_GLOBAL) {
2067            DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
2068            return(True);
2069          }
2070        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
2071    }
2072
2073    if (snum >= 0) {
2074            if (!iSERVICE(snum).copymap)
2075                    init_copymap(pSERVICE(snum));
2076            
2077            /* this handles the aliases - set the copymap for other entries with
2078               the same data pointer */
2079            for (i=0;parm_table[i].label;i++)
2080                    if (parm_table[i].ptr == parm_table[parmnum].ptr)
2081                            iSERVICE(snum).copymap[i] = False;
2082    }
2083
2084    /* if it is a special case then go ahead */
2085    if (parm_table[parmnum].special) {
2086            parm_table[parmnum].special(pszParmValue,(char **)parm_ptr);
2087            return(True);
2088    }
2089
2090    /* now switch on the type of variable it is */
2091    switch (parm_table[parmnum].type)
2092      {
2093      case P_BOOL:
2094        set_boolean(parm_ptr,pszParmValue);
2095        break;
2096
2097      case P_BOOLREV:
2098        set_boolean(parm_ptr,pszParmValue);
2099        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
2100        break;
2101
2102      case P_INTEGER:
2103        *(int *)parm_ptr = atoi(pszParmValue);
2104        break;
2105
2106      case P_CHAR:
2107        *(char *)parm_ptr = *pszParmValue;
2108        break;
2109
2110      case P_OCTAL:
2111        sscanf(pszParmValue,"%o",(int *)parm_ptr);
2112        break;
2113
2114      case P_STRING:
2115        string_set(parm_ptr,pszParmValue);
2116        if (parm_table[parmnum].flags & FLAG_DOS_STRING)
2117            unix_to_dos(*(char **)parm_ptr, True);
2118        break;
2119
2120      case P_USTRING:
2121        string_set(parm_ptr,pszParmValue);
2122        if (parm_table[parmnum].flags & FLAG_DOS_STRING)
2123            unix_to_dos(*(char **)parm_ptr, True);
2124        strupper(*(char **)parm_ptr);
2125        break;
2126
2127      case P_GSTRING:
2128        pstrcpy((char *)parm_ptr,pszParmValue);
2129        if (parm_table[parmnum].flags & FLAG_DOS_STRING)
2130            unix_to_dos((char *)parm_ptr, True);
2131        break;
2132
2133      case P_UGSTRING:
2134        pstrcpy((char *)parm_ptr,pszParmValue);
2135        if (parm_table[parmnum].flags & FLAG_DOS_STRING)
2136            unix_to_dos((char *)parm_ptr, True);
2137        strupper((char *)parm_ptr);
2138        break;
2139
2140      case P_ENUM:
2141              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
2142                      if (strequal(pszParmValue, parm_table[parmnum].enum_list[i].name)) {
2143                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
2144                              break;
2145                      }
2146              }
2147              break;
2148      case P_SEP:
2149              break;
2150      }
2151
2152    return(True);
2153 }
2154
2155 /***************************************************************************
2156 Process a parameter.
2157 ***************************************************************************/
2158 static BOOL do_parameter( char *pszParmName, char *pszParmValue )
2159 {
2160   if( !bInGlobalSection && bGlobalOnly )
2161     return(True);
2162
2163   DEBUGADD( 3, ( "doing parameter %s = %s\n", pszParmName, pszParmValue ) );
2164
2165   return( lp_do_parameter( bInGlobalSection ? -2 : iServiceIndex,
2166                            pszParmName,
2167                            pszParmValue ) );
2168 }
2169
2170
2171 /***************************************************************************
2172 print a parameter of the specified type
2173 ***************************************************************************/
2174 static void print_parameter(struct parm_struct *p,void *ptr, FILE *f)
2175 {
2176         int i;
2177         switch (p->type) {
2178         case P_ENUM:
2179                 for (i=0;p->enum_list[i].name;i++) {
2180                         if (*(int *)ptr == p->enum_list[i].value) {
2181                                 fprintf(f,"%s",p->enum_list[i].name);
2182                                 break;
2183                         }
2184                 }
2185                 break;
2186
2187         case P_BOOL:
2188                 fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr));
2189                 break;
2190       
2191         case P_BOOLREV:
2192                 fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr));
2193                 break;
2194       
2195         case P_INTEGER:
2196                 fprintf(f,"%d",*(int *)ptr);
2197                 break;
2198       
2199         case P_CHAR:
2200                 fprintf(f,"%c",*(char *)ptr);
2201                 break;
2202       
2203         case P_OCTAL:
2204                 fprintf(f,"%s",octal_string(*(int *)ptr));
2205                 break;
2206       
2207         case P_GSTRING:
2208         case P_UGSTRING:
2209                 if ((char *)ptr)
2210                         fprintf(f,"%s",(char *)ptr);
2211                 break;
2212                 
2213         case P_STRING:
2214         case P_USTRING:
2215                 if (*(char **)ptr)
2216                         fprintf(f,"%s",*(char **)ptr);
2217                 break;
2218         case P_SEP:
2219                 break;
2220         }
2221 }
2222
2223
2224 /***************************************************************************
2225 check if two parameters are equal
2226 ***************************************************************************/
2227 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
2228 {
2229   switch (type)
2230     {
2231     case P_BOOL:
2232     case P_BOOLREV:
2233       return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
2234
2235     case P_INTEGER:
2236     case P_ENUM:
2237     case P_OCTAL:
2238       return(*((int *)ptr1) == *((int *)ptr2));
2239       
2240     case P_CHAR:
2241       return(*((char *)ptr1) == *((char *)ptr2));
2242
2243     case P_GSTRING:
2244     case P_UGSTRING:
2245       {
2246         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
2247         if (p1 && !*p1) p1 = NULL;
2248         if (p2 && !*p2) p2 = NULL;
2249         return(p1==p2 || strequal(p1,p2));
2250       }
2251     case P_STRING:
2252     case P_USTRING:
2253       {
2254         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2255         if (p1 && !*p1) p1 = NULL;
2256         if (p2 && !*p2) p2 = NULL;
2257         return(p1==p2 || strequal(p1,p2));
2258       }
2259      case P_SEP:
2260              break;
2261     }
2262   return(False);
2263 }
2264
2265 /***************************************************************************
2266 Process a new section (service). At this stage all sections are services.
2267 Later we'll have special sections that permit server parameters to be set.
2268 Returns True on success, False on failure.
2269 ***************************************************************************/
2270 static BOOL do_section(char *pszSectionName)
2271 {
2272    BOOL bRetval;
2273    BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || 
2274                     (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2275    bRetval = False;
2276
2277    /* if we were in a global section then do the local inits */
2278    if (bInGlobalSection && !isglobal)
2279      init_locals();
2280
2281    /* if we've just struck a global section, note the fact. */
2282    bInGlobalSection = isglobal;   
2283
2284    /* check for multiple global sections */
2285    if (bInGlobalSection)
2286    {
2287      DEBUG( 3, ( "Processing section \"[%s]\"\n", pszSectionName ) );
2288      return(True);
2289    }
2290
2291    if (!bInGlobalSection && bGlobalOnly) return(True);
2292
2293    /* if we have a current service, tidy it up before moving on */
2294    bRetval = True;
2295
2296    if (iServiceIndex >= 0)
2297      bRetval = service_ok(iServiceIndex);
2298
2299    /* if all is still well, move to the next record in the services array */
2300    if (bRetval)
2301      {
2302        /* We put this here to avoid an odd message order if messages are */
2303        /* issued by the post-processing of a previous section. */
2304        DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
2305
2306        if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
2307          {
2308            DEBUG(0,("Failed to add a new service\n"));
2309            return(False);
2310          }
2311      }
2312
2313    return (bRetval);
2314 }
2315
2316
2317 /***************************************************************************
2318 determine if a partcular base parameter is currently set to the default value.
2319 ***************************************************************************/
2320 static BOOL is_default(int i)
2321 {
2322         if (!defaults_saved) return False;
2323         switch (parm_table[i].type) {
2324         case P_STRING:
2325         case P_USTRING:
2326                 return strequal(parm_table[i].def.svalue,*(char **)parm_table[i].ptr);
2327         case P_GSTRING:
2328         case P_UGSTRING:
2329                 return strequal(parm_table[i].def.svalue,(char *)parm_table[i].ptr);
2330         case P_BOOL:
2331         case P_BOOLREV:
2332                 return parm_table[i].def.bvalue == *(BOOL *)parm_table[i].ptr;
2333         case P_CHAR:
2334                 return parm_table[i].def.cvalue == *(char *)parm_table[i].ptr;
2335         case P_INTEGER:
2336         case P_OCTAL:
2337         case P_ENUM:
2338                 return parm_table[i].def.ivalue == *(int *)parm_table[i].ptr;
2339         case P_SEP:
2340                 break;
2341         }
2342         return False;
2343 }
2344
2345
2346 /***************************************************************************
2347 Display the contents of the global structure.
2348 ***************************************************************************/
2349 static void dump_globals(FILE *f)
2350 {
2351         int i;
2352         fprintf(f, "# Global parameters\n[global]\n");
2353         
2354         for (i=0;parm_table[i].label;i++)
2355                 if (parm_table[i].class == P_GLOBAL &&
2356                     parm_table[i].ptr &&
2357                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2358                         if (defaults_saved && is_default(i)) continue;
2359                         fprintf(f,"\t%s = ",parm_table[i].label);
2360                         print_parameter(&parm_table[i],parm_table[i].ptr, f);
2361                         fprintf(f,"\n");
2362                 }
2363 }
2364
2365 /***************************************************************************
2366 return True if a local parameter is currently set to the global default
2367 ***************************************************************************/
2368 BOOL lp_is_default(int snum, struct parm_struct *parm)
2369 {
2370         int pdiff = PTR_DIFF(parm->ptr,&sDefault);
2371                         
2372         return equal_parameter(parm->type,
2373                                ((char *)pSERVICE(snum)) + pdiff,
2374                                ((char *)&sDefault) + pdiff);
2375 }
2376
2377
2378 /***************************************************************************
2379 Display the contents of a single services record.
2380 ***************************************************************************/
2381 static void dump_a_service(service *pService, FILE *f)
2382 {
2383         int i;
2384         if (pService != &sDefault)
2385                 fprintf(f,"\n[%s]\n",pService->szService);
2386
2387         for (i=0;parm_table[i].label;i++)
2388                 if (parm_table[i].class == P_LOCAL &&
2389                     parm_table[i].ptr && 
2390                     (*parm_table[i].label != '-') &&
2391                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2392                         int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
2393                         
2394                         if (pService == &sDefault) {
2395                                 if (defaults_saved && is_default(i)) continue;
2396                         } else {
2397                                 if (equal_parameter(parm_table[i].type,
2398                                                     ((char *)pService) + pdiff,
2399                                                     ((char *)&sDefault) + pdiff)) 
2400                                         continue;
2401                         }
2402
2403                         fprintf(f,"\t%s = ",parm_table[i].label);
2404                         print_parameter(&parm_table[i],
2405                                         ((char *)pService) + pdiff, f);
2406                         fprintf(f,"\n");
2407                 }
2408 }
2409
2410
2411 /***************************************************************************
2412 return info about the next service  in a service. snum==-1 gives the globals
2413
2414 return NULL when out of parameters
2415 ***************************************************************************/
2416 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2417 {
2418         if (snum == -1) {
2419                 /* do the globals */
2420                 for (;parm_table[*i].label;(*i)++) {
2421                         if (parm_table[*i].class == P_SEPARATOR) 
2422                                 return &parm_table[(*i)++];
2423
2424                         if (!parm_table[*i].ptr || (*parm_table[*i].label == '-'))
2425                                 continue;
2426                         
2427                         if ((*i) > 0 && (parm_table[*i].ptr == parm_table[(*i)-1].ptr))
2428                                 continue;
2429
2430                         return &parm_table[(*i)++];
2431                 }
2432         } else {
2433                 service *pService = pSERVICE(snum);
2434
2435                 for (;parm_table[*i].label;(*i)++) {
2436                         if (parm_table[*i].class == P_SEPARATOR) 
2437                                 return &parm_table[(*i)++];
2438
2439                         if (parm_table[*i].class == P_LOCAL &&
2440                             parm_table[*i].ptr && 
2441                             (*parm_table[*i].label != '-') &&
2442                             ((*i) == 0 || 
2443                              (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
2444                                 int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault);
2445                                 
2446                                 if (allparameters ||
2447                                     !equal_parameter(parm_table[*i].type,
2448                                                      ((char *)pService) + pdiff,
2449                                                      ((char *)&sDefault) + pdiff)) {
2450                                         return &parm_table[(*i)++];
2451                                 }
2452                         }
2453                 }
2454         }
2455
2456         return NULL;
2457 }
2458
2459
2460 #if 0
2461 /***************************************************************************
2462 Display the contents of a single copy structure.
2463 ***************************************************************************/
2464 static void dump_copy_map(BOOL *pcopymap)
2465 {
2466   int i;
2467   if (!pcopymap) return;
2468
2469   printf("\n\tNon-Copied parameters:\n");
2470
2471   for (i=0;parm_table[i].label;i++)
2472     if (parm_table[i].class == P_LOCAL &&
2473         parm_table[i].ptr && !pcopymap[i] &&
2474         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
2475       {
2476         printf("\t\t%s\n",parm_table[i].label);
2477       }
2478 }
2479 #endif
2480
2481 /***************************************************************************
2482 Return TRUE if the passed service number is within range.
2483 ***************************************************************************/
2484 BOOL lp_snum_ok(int iService)
2485 {
2486    return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
2487 }
2488
2489
2490 /***************************************************************************
2491 auto-load some home services
2492 ***************************************************************************/
2493 static void lp_add_auto_services(char *str)
2494 {
2495         char *s;
2496         char *p;
2497         int homes;
2498
2499         if (!str) return;
2500
2501         s = strdup(str);
2502         if (!s) return;
2503
2504         homes = lp_servicenumber(HOMES_NAME);
2505         
2506         for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
2507                 char *home = get_user_home_dir(p);
2508                 
2509                 if (lp_servicenumber(p) >= 0) continue;
2510                 
2511                 if (home && homes >= 0) {
2512                         lp_add_home(p,homes,home);
2513                 }
2514         }
2515         free(s);
2516 }
2517
2518 /***************************************************************************
2519 auto-load one printer
2520 ***************************************************************************/
2521 void lp_add_one_printer(char *name,char *comment)
2522 {
2523         int printers = lp_servicenumber(PRINTERS_NAME);
2524         int i;
2525
2526         if (lp_servicenumber(name) < 0)  {
2527                 lp_add_printer(name,printers);
2528                 if ((i=lp_servicenumber(name)) >= 0)
2529                         string_set(&iSERVICE(i).comment,comment);
2530         }
2531 }
2532
2533 /***************************************************************************
2534 have we loaded a services file yet?
2535 ***************************************************************************/
2536 BOOL lp_loaded(void)
2537 {
2538   return(bLoaded);
2539 }
2540
2541 /***************************************************************************
2542 unload unused services
2543 ***************************************************************************/
2544 void lp_killunused(BOOL (*snumused)(int ))
2545 {
2546   int i;
2547   for (i=0;i<iNumServices;i++)
2548     if (VALID(i) && (!snumused || !snumused(i)))
2549       {
2550         iSERVICE(i).valid = False;
2551         free_service(pSERVICE(i));
2552       }
2553 }
2554
2555
2556 /***************************************************************************
2557 save the curent values of all global and sDefault parameters into the 
2558 defaults union. This allows swat and testparm to show only the
2559 changed (ie. non-default) parameters.
2560 ***************************************************************************/
2561 static void lp_save_defaults(void)
2562 {
2563         int i;
2564         for (i = 0; parm_table[i].label; i++) {
2565                 if (i>0 && parm_table[i].ptr == parm_table[i-1].ptr) continue;
2566                 switch (parm_table[i].type) {
2567                 case P_STRING:
2568                 case P_USTRING:
2569                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
2570                         break;
2571                 case P_GSTRING:
2572                 case P_UGSTRING:
2573                         parm_table[i].def.svalue = strdup((char *)parm_table[i].ptr);
2574                         break;
2575                 case P_BOOL:
2576                 case P_BOOLREV:
2577                         parm_table[i].def.bvalue = *(BOOL *)parm_table[i].ptr;
2578                         break;
2579                 case P_CHAR:
2580                         parm_table[i].def.cvalue = *(char *)parm_table[i].ptr;
2581                         break;
2582                 case P_INTEGER:
2583                 case P_OCTAL:
2584                 case P_ENUM:
2585                         parm_table[i].def.ivalue = *(int *)parm_table[i].ptr;
2586                         break;
2587                 case P_SEP:
2588                         break;
2589                 }
2590         }
2591         defaults_saved = True;
2592 }
2593
2594
2595 /***************************************************************************
2596 Load the services array from the services file. Return True on success, 
2597 False on failure.
2598 ***************************************************************************/
2599 BOOL lp_load(char *pszFname,BOOL global_only, BOOL save_defaults, BOOL add_ipc)
2600 {
2601   pstring n2;
2602   BOOL bRetval;
2603  
2604   add_to_file_list(pszFname);
2605
2606   bRetval = False;
2607
2608   bInGlobalSection = True;
2609   bGlobalOnly = global_only;
2610   
2611   init_globals();
2612
2613   if (save_defaults) {
2614           init_locals();
2615           lp_save_defaults();
2616   }
2617   
2618   pstrcpy(n2,pszFname);
2619   standard_sub_basic(n2);
2620
2621   /* We get sections first, so have to start 'behind' to make up */
2622   iServiceIndex = -1;
2623   bRetval = pm_process(n2, do_section, do_parameter);
2624   
2625   /* finish up the last section */
2626   DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
2627   if (bRetval)
2628     if (iServiceIndex >= 0)
2629       bRetval = service_ok(iServiceIndex);         
2630
2631   lp_add_auto_services(lp_auto_services());
2632
2633   if (add_ipc)
2634           lp_add_ipc();
2635
2636   set_default_server_announce_type();
2637
2638   bLoaded = True;
2639
2640   /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
2641   /* if bWINSsupport is true and we are in the client            */
2642
2643   if (in_client && Globals.bWINSsupport) {
2644
2645     string_set(&Globals.szWINSserver, "127.0.0.1");
2646
2647   }
2648
2649   return (bRetval);
2650 }
2651
2652
2653 /***************************************************************************
2654 reset the max number of services
2655 ***************************************************************************/
2656 void lp_resetnumservices(void)
2657 {
2658   iNumServices = 0;
2659 }
2660
2661 /***************************************************************************
2662 return the max number of services
2663 ***************************************************************************/
2664 int lp_numservices(void)
2665 {
2666   return(iNumServices);
2667 }
2668
2669 /***************************************************************************
2670 Display the contents of the services array in human-readable form.
2671 ***************************************************************************/
2672 void lp_dump(FILE *f, BOOL show_defaults, int maxtoprint)
2673 {
2674    int iService;
2675
2676    if (show_defaults) {
2677            defaults_saved = False;
2678    }
2679
2680    dump_globals(f);
2681    
2682    dump_a_service(&sDefault, f);
2683
2684    for (iService = 0; iService < maxtoprint; iService++)
2685      lp_dump_one(f, show_defaults, iService);
2686 }
2687
2688 /***************************************************************************
2689 Display the contents of one service in human-readable form.
2690 ***************************************************************************/
2691 void lp_dump_one(FILE *f, BOOL show_defaults, int snum)
2692 {
2693    if (VALID(snum))
2694      {
2695        if (iSERVICE(snum).szService[0] == '\0')
2696          return;
2697        dump_a_service(pSERVICE(snum), f);
2698      }
2699 }
2700
2701
2702 /***************************************************************************
2703 Return the number of the service with the given name, or -1 if it doesn't
2704 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2705 getservicebyname()! This works ONLY if all services have been loaded, and
2706 does not copy the found service.
2707 ***************************************************************************/
2708 int lp_servicenumber(char *pszServiceName)
2709 {
2710    int iService;
2711
2712    for (iService = iNumServices - 1; iService >= 0; iService--)
2713       if (VALID(iService) &&
2714           strequal(lp_servicename(iService), pszServiceName)) 
2715          break;
2716
2717    if (iService < 0)
2718      DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
2719    
2720    return (iService);
2721 }
2722
2723 /*******************************************************************
2724   a useful volume label function
2725   ******************************************************************/
2726 char *volume_label(int snum)
2727 {
2728   char *ret = lp_volume(snum);
2729   if (!*ret) return(lp_servicename(snum));
2730   return(ret);
2731 }
2732
2733
2734 /*******************************************************************
2735  Set the server type we will announce as via nmbd.
2736 ********************************************************************/
2737 static void set_default_server_announce_type(void)
2738 {
2739   default_server_announce = (SV_TYPE_WORKSTATION | SV_TYPE_SERVER |
2740                               SV_TYPE_SERVER_UNIX | SV_TYPE_PRINTQ_SERVER);
2741   if(lp_announce_as() == ANNOUNCE_AS_NT_SERVER)
2742     default_server_announce |= (SV_TYPE_SERVER_NT | SV_TYPE_NT);
2743   if(lp_announce_as() == ANNOUNCE_AS_NT_WORKSTATION)
2744     default_server_announce |= SV_TYPE_NT;
2745   else if(lp_announce_as() == ANNOUNCE_AS_WIN95)
2746     default_server_announce |= SV_TYPE_WIN95_PLUS;
2747   else if(lp_announce_as() == ANNOUNCE_AS_WFW)
2748     default_server_announce |= SV_TYPE_WFW;
2749   default_server_announce |= (lp_time_server() ? SV_TYPE_TIME_SOURCE : 0);
2750 }
2751
2752
2753 /*******************************************************************
2754 remove a service
2755 ********************************************************************/
2756 void lp_remove_service(int snum)
2757 {
2758         pSERVICE(snum)->valid = False;
2759 }
2760
2761 /*******************************************************************
2762 copy a service
2763 ********************************************************************/
2764 void lp_copy_service(int snum, char *new_name)
2765 {
2766         char *oldname = lp_servicename(snum);
2767         do_section(new_name);
2768         if (snum >= 0) {
2769                 snum = lp_servicenumber(new_name);
2770                 if (snum >= 0)
2771                         lp_do_parameter(snum, "copy", oldname);
2772         }
2773 }
2774
2775
2776 /*******************************************************************
2777  Get the default server type we will announce as via nmbd.
2778 ********************************************************************/
2779 int lp_default_server_announce(void)
2780 {
2781   return default_server_announce;
2782 }
2783
2784 /*******************************************************************
2785  Split the announce version into major and minor numbers.
2786 ********************************************************************/
2787 int lp_major_announce_version(void)
2788 {
2789   static BOOL got_major = False;
2790   static int major_version = DEFAULT_MAJOR_VERSION;
2791   char *vers;
2792   char *p;
2793
2794   if(got_major)
2795     return major_version;
2796
2797   got_major = True;
2798   if((vers = lp_announce_version()) == NULL)
2799     return major_version;
2800   
2801   if((p = strchr(vers, '.')) == 0)
2802     return major_version;
2803
2804   *p = '\0';
2805   major_version = atoi(vers);
2806   return major_version;
2807 }
2808
2809 int lp_minor_announce_version(void)
2810 {
2811   static BOOL got_minor = False;
2812   static int minor_version = DEFAULT_MINOR_VERSION;
2813   char *vers;
2814   char *p;
2815
2816   if(got_minor)
2817     return minor_version;
2818
2819   got_minor = True;
2820   if((vers = lp_announce_version()) == NULL)
2821     return minor_version;
2822   
2823   if((p = strchr(vers, '.')) == 0)              
2824     return minor_version;
2825     
2826   p++;
2827   minor_version = atoi(p);
2828   return minor_version;
2829 }  
2830
2831 /***********************************************************
2832  Set the global name resolution order (used in smbclient).
2833 ************************************************************/
2834
2835 void lp_set_name_resolve_order(char *new_order)
2836
2837   Globals.szNameResolveOrder = new_order;
2838 }
2839
2840 /***********************************************************
2841  Set the flag that says if kernel oplocks are available 
2842  (called by smbd).
2843 ************************************************************/
2844
2845 static BOOL kernel_oplocks_available = False;
2846
2847 void lp_set_kernel_oplocks(BOOL val)
2848 {
2849   /*
2850    * Only set this to True if kerenl
2851    * oplocks are really available and were
2852    * turned on in the smb.conf file.
2853    */
2854
2855   if(Globals.bKernelOplocks && val)
2856     kernel_oplocks_available = True;
2857   else
2858     kernel_oplocks_available = False;
2859 }
2860
2861 /***********************************************************
2862  Return True if kernel oplocks are available and were turned
2863  on in smb.conf.
2864 ************************************************************/
2865
2866 BOOL lp_kernel_oplocks(void)
2867 {
2868   return kernel_oplocks_available;
2869 }
2870
2871 /***********************************************************
2872  Functions to return the current security masks/modes. If
2873  set to -1 then return the create mask/mode instead.
2874 ************************************************************/
2875
2876 int lp_security_mask(int snum)
2877 {
2878   int val = _lp_security_mask(snum);
2879   if(val == -1)
2880     return lp_create_mask(snum);
2881   return val;
2882 }
2883
2884 int lp_force_security_mode(int snum)
2885 {
2886   int val = _lp_force_security_mode(snum);
2887   if(val == -1)
2888     return lp_force_create_mode(snum);
2889   return val;
2890 }
2891
2892 int lp_dir_security_mask(int snum)
2893 {
2894   int val = _lp_dir_security_mask(snum);
2895   if(val == -1)
2896     return lp_dir_mask(snum);
2897   return val;
2898 }
2899
2900 int lp_force_dir_security_mode(int snum)
2901 {
2902   int val = _lp_force_dir_security_mode(snum);
2903   if(val == -1)
2904     return lp_force_dir_mode(snum);
2905   return val;
2906 }