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