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