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