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