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