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