added a per-share parameter "fstype" that allows you to select the
[kai/samba.git] / source / param / loadparm.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Parameter loading functions
5    Copyright (C) Karl Auer 1993-1998
6
7    Largely re-written by Andrew Tridgell, September 1994
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 /*
25  *  Load parameters.
26  *
27  *  This module provides suitable callback functions for the params
28  *  module. It builds the internal table of service details which is
29  *  then used by the rest of the server.
30  *
31  * To add a parameter:
32  *
33  * 1) add it to the global or service structure definition
34  * 2) add it to the parm_table
35  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
36  * 4) If it's a global then initialise it in init_globals. If a local
37  *    (ie. service) parameter then initialise it in the sDefault structure
38  *  
39  *
40  * Notes:
41  *   The configuration file is processed sequentially for speed. It is NOT
42  *   accessed randomly as happens in 'real' Windows. For this reason, there
43  *   is a fair bit of sequence-dependent code here - ie., code which assumes
44  *   that certain things happen before others. In particular, the code which
45  *   happens at the boundary between sections is delicately poised, so be
46  *   careful!
47  *
48  */
49
50 #include "includes.h"
51
52 /* Set default coding system for KANJI if none specified in Makefile. */
53 /* 
54  * We treat KANJI specially due to historical precedent (it was the
55  * first non-english codepage added to Samba). With the new dynamic
56  * codepage support this is not needed anymore.
57  *
58  * The define 'KANJI' is being overloaded to mean 'use kanji codepage
59  * by default' and also 'this is the filename-to-disk conversion 
60  * method to use'. This really should be removed and all control
61  * over this left in the smb.conf parameters 'client codepage'
62  * and 'coding system'.
63  */
64 #ifndef KANJI
65 #define KANJI "sbcs"
66 #endif /* KANJI */
67
68 BOOL 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
813   string_set(&Globals.szNameResolveOrder, "lmhosts host wins bcast");
814
815   Globals.bLoadPrinters = True;
816   Globals.bUseRhosts = False;
817   Globals.max_packet = 65535;
818   Globals.mangled_stack = 50;
819   Globals.max_xmit = 65535;
820   Globals.max_mux = 50; /* This is *needed* for profile support. */
821   Globals.lpqcachetime = 10;
822   Globals.pwordlevel = 0;
823   Globals.unamelevel = 0;
824   Globals.deadtime = 0;
825   Globals.max_log_size = 5000;
826   Globals.maxprotocol = PROTOCOL_NT1;
827   Globals.security = SEC_USER;
828   Globals.bEncryptPasswords = False;
829   Globals.bUpdateEncrypt = False;
830   Globals.bReadRaw = True;
831   Globals.bWriteRaw = True;
832   Globals.bReadPrediction = False;
833   Globals.bReadbmpx = True;
834   Globals.bNullPasswords = False;
835   Globals.bStripDot = False;
836   Globals.syslog = 1;
837   Globals.bSyslogOnly = False;
838   Globals.bTimestampLogs = True;
839   Globals.os_level = 0;
840   Globals.max_ttl = 60*60*24*3; /* 3 days default. */
841   Globals.max_wins_ttl = 60*60*24*6; /* 6 days default. */
842   Globals.min_wins_ttl = 60*60*6; /* 6 hours default. */
843   Globals.machine_password_timeout = 60*60*24*7; /* 7 days default. */
844   Globals.change_notify_timeout = 60; /* 1 minute default. */
845   Globals.ReadSize = 16*1024;
846   Globals.lm_announce = 2;   /* = Auto: send only if LM clients found */
847   Globals.lm_interval = 60;
848   Globals.shmem_size = SHMEM_SIZE;
849   Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */
850   Globals.announce_as = ANNOUNCE_AS_NT;
851   Globals.bUnixRealname = False;
852 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
853   Globals.bNISHomeMap = False;
854 #ifdef WITH_NISPLUS_HOME
855   string_set(&Globals.szNISHomeMapName, "auto_home.org_dir");
856 #else
857   string_set(&Globals.szNISHomeMapName, "auto.home");
858 #endif
859 #endif
860   Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE;
861   Globals.bTimeServer = False;
862   Globals.bBindInterfacesOnly = False;
863   Globals.bNetWkstaUserLogon = False; /* This is now set to false by default as
864                                          the code in password.c protects us from this bug. */
865   Globals.bUnixPasswdSync = False;
866   Globals.bPasswdChatDebug = False;
867   Globals.bOleLockingCompat = True;
868   Globals.bNTSmbSupport = True; /* Do NT SMB's by default. */
869   Globals.bStatCache = True; /* use stat cache by default */
870
871 #ifdef WITH_LDAP
872   /* default values for ldap */
873   string_set(&Globals.szLdapServer, "localhost");
874   Globals.ldap_port=389;
875 #endif /* WITH_LDAP */
876
877 #ifdef WITH_SSL
878   Globals.sslVersion = SMB_SSL_V23;
879   Globals.sslHostsRequire = NULL;
880   Globals.sslHostsResign = NULL;
881   Globals.sslCaCertDir = NULL;
882   Globals.sslCaCertFile = NULL;
883   Globals.sslCert = NULL;
884   Globals.sslPrivKey = NULL;
885   Globals.sslClientCert = NULL;
886   Globals.sslClientPrivKey = NULL;
887   Globals.sslCiphers = NULL;
888   Globals.sslEnabled = False;
889   Globals.sslReqClientCert = False;
890   Globals.sslReqServerCert = False;
891   Globals.sslCompatibility = False;
892 #endif        /* WITH_SSL */
893
894 /* these parameters are set to defaults that are more appropriate
895    for the increasing samba install base:
896
897    as a member of the workgroup, that will possibly become a
898    _local_ master browser (lm = True).  this is opposed to a forced
899    local master browser startup (pm = True).
900
901    doesn't provide WINS server service by default (wsupp = False),
902    and doesn't provide domain master browser services by default, either.
903
904 */
905
906   Globals.bPreferredMaster = False;
907   Globals.bLocalMaster = True;
908   Globals.bDomainMaster = False;
909   Globals.bDomainLogons = False;
910   Globals.bBrowseList = True;
911   Globals.bWINSsupport = False;
912   Globals.bWINSproxy = False;
913
914   Globals.bDNSproxy = True;
915
916   /*
917    * smbd will check after starting to see if this value
918    * should be set to "true" or not.
919    */
920   Globals.bKernelOplocks = False;
921
922   /*
923    * This must be done last as it checks the value in 
924    * client_code_page.
925    */
926
927   interpret_coding_system(KANJI);
928 }
929
930 /***************************************************************************
931 check if a string is initialised and if not then initialise it
932 ***************************************************************************/
933 static void string_initial(char **s,char *v)
934 {
935   if (!*s || !**s)
936     string_init(s,v);
937 }
938
939
940 /***************************************************************************
941 Initialise the sDefault parameter structure.
942 ***************************************************************************/
943 static void init_locals(void)
944 {
945   /* choose defaults depending on the type of printing */
946   switch (sDefault.iPrinting)
947     {
948     case PRINT_BSD:
949     case PRINT_AIX:
950     case PRINT_LPRNG:
951     case PRINT_PLP:
952       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
953       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
954       string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
955       break;
956
957     case PRINT_SYSV:
958     case PRINT_HPUX:
959       string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
960       string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
961       string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
962 #ifdef SYSV
963       string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
964       string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
965       string_initial(&sDefault.szQueuepausecommand, "lpc stop %p");
966       string_initial(&sDefault.szQueueresumecommand, "lpc start %p");
967 #else /* SYSV */
968       string_initial(&sDefault.szQueuepausecommand, "disable %p");
969       string_initial(&sDefault.szQueueresumecommand, "enable %p");
970 #endif /* SYSV */
971       break;
972
973     case PRINT_QNX:
974       string_initial(&sDefault.szLpqcommand,"lpq -P%p");
975       string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
976       string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
977       break;
978
979     case PRINT_SOFTQ:
980       string_initial(&sDefault.szLpqcommand,"qstat -l -d%p");
981       string_initial(&sDefault.szLprmcommand,"qstat -s -j%j -c");
982       string_initial(&sDefault.szPrintcommand,"lp -d%p -s %s; rm %s");
983       string_initial(&sDefault.szLppausecommand,"qstat -s -j%j -h");
984       string_initial(&sDefault.szLpresumecommand,"qstat -s -j%j -r");
985       break;
986       
987     }
988 }
989
990
991 /******************************************************************* a
992 convenience routine to grab string parameters into a rotating buffer,
993 and run standard_sub_basic on them. The buffers can be written to by
994 callers without affecting the source string.
995 ********************************************************************/
996 static char *lp_string(char *s)
997 {
998   static char *bufs[10];
999   static int buflen[10];
1000   static int next = -1;  
1001   char *ret;
1002   int i;
1003   int len = s?strlen(s):0;
1004
1005   if (next == -1) {
1006     /* initialisation */
1007     for (i=0;i<10;i++) {
1008       bufs[i] = NULL;
1009       buflen[i] = 0;
1010     }
1011     next = 0;
1012   }
1013
1014   len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
1015                                          substitution room */
1016
1017   if (buflen[next] != len) {
1018     buflen[next] = len;
1019     if (bufs[next]) free(bufs[next]);
1020     bufs[next] = (char *)malloc(len);
1021     if (!bufs[next]) {
1022       DEBUG(0,("out of memory in lp_string()"));
1023       exit(1);
1024     }
1025   } 
1026
1027   ret = &bufs[next][0];
1028   next = (next+1)%10;
1029
1030   if (!s) 
1031     *ret = 0;
1032   else
1033     StrCpy(ret,s);
1034
1035   trim_string(ret, "\"", "\"");
1036
1037   standard_sub_basic(ret);
1038   return(ret);
1039 }
1040
1041
1042 /*
1043    In this section all the functions that are used to access the 
1044    parameters from the rest of the program are defined 
1045 */
1046
1047 #define FN_GLOBAL_STRING(fn_name,ptr) \
1048  char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
1049 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1050  BOOL fn_name(void) {return(*(BOOL *)(ptr));}
1051 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1052  char fn_name(void) {return(*(char *)(ptr));}
1053 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1054  int fn_name(void) {return(*(int *)(ptr));}
1055
1056 #define FN_LOCAL_STRING(fn_name,val) \
1057  char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
1058 #define FN_LOCAL_BOOL(fn_name,val) \
1059  BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1060 #define FN_LOCAL_CHAR(fn_name,val) \
1061  char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1062 #define FN_LOCAL_INTEGER(fn_name,val) \
1063  int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
1064
1065 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
1066 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
1067 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
1068 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
1069 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
1070 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
1071 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
1072 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
1073 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
1074 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
1075 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
1076 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
1077 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
1078 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
1079 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
1080 FN_GLOBAL_STRING(lp_name_resolve_order,&Globals.szNameResolveOrder)
1081 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
1082 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
1083 #ifdef USING_GROUPNAME_MAP
1084 FN_GLOBAL_STRING(lp_groupname_map,&Globals.szGroupnameMap)
1085 #endif /* USING_GROUPNAME_MAP */
1086 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) 
1087 FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) 
1088 FN_GLOBAL_STRING(lp_logon_drive,&Globals.szLogonDrive) 
1089 FN_GLOBAL_STRING(lp_logon_home,&Globals.szLogonHome) 
1090 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) 
1091 FN_GLOBAL_STRING(lp_remote_browse_sync,&Globals.szRemoteBrowseSync) 
1092 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
1093 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
1094 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
1095 FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName)
1096 static FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion)
1097 FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases)
1098 FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile)
1099 FN_GLOBAL_STRING(lp_panic_action,&Globals.szPanicAction)
1100
1101 FN_GLOBAL_STRING(lp_domain_sid,&Globals.szDomainSID)
1102 FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups)
1103 FN_GLOBAL_STRING(lp_domain_admin_group,&Globals.szDomainAdminGroup)
1104 FN_GLOBAL_STRING(lp_domain_guest_group,&Globals.szDomainGuestGroup)
1105 FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers)
1106 FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers)
1107
1108 #ifdef WITH_LDAP
1109 FN_GLOBAL_STRING(lp_ldap_server,&Globals.szLdapServer);
1110 FN_GLOBAL_STRING(lp_ldap_suffix,&Globals.szLdapSuffix);
1111 FN_GLOBAL_STRING(lp_ldap_filter,&Globals.szLdapFilter);
1112 FN_GLOBAL_STRING(lp_ldap_root,&Globals.szLdapRoot);
1113 FN_GLOBAL_STRING(lp_ldap_rootpasswd,&Globals.szLdapRootPassword);
1114 #endif /* WITH_LDAP */
1115
1116 #ifdef WITH_SSL
1117 FN_GLOBAL_INTEGER(lp_ssl_version,&Globals.sslVersion);
1118 FN_GLOBAL_STRING(lp_ssl_hosts,&Globals.sslHostsRequire);
1119 FN_GLOBAL_STRING(lp_ssl_hosts_resign,&Globals.sslHostsResign);
1120 FN_GLOBAL_STRING(lp_ssl_cacertdir,&Globals.sslCaCertDir);
1121 FN_GLOBAL_STRING(lp_ssl_cacertfile,&Globals.sslCaCertFile);
1122 FN_GLOBAL_STRING(lp_ssl_cert,&Globals.sslCert);
1123 FN_GLOBAL_STRING(lp_ssl_privkey,&Globals.sslPrivKey);
1124 FN_GLOBAL_STRING(lp_ssl_client_cert,&Globals.sslClientCert);
1125 FN_GLOBAL_STRING(lp_ssl_client_privkey,&Globals.sslClientPrivKey);
1126 FN_GLOBAL_STRING(lp_ssl_ciphers,&Globals.sslCiphers);
1127 FN_GLOBAL_BOOL(lp_ssl_enabled,&Globals.sslEnabled);
1128 FN_GLOBAL_BOOL(lp_ssl_reqClientCert,&Globals.sslReqClientCert);
1129 FN_GLOBAL_BOOL(lp_ssl_reqServerCert,&Globals.sslReqServerCert);
1130 FN_GLOBAL_BOOL(lp_ssl_compatibility,&Globals.sslCompatibility);
1131 #endif        /* WITH_SSL */
1132
1133 FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
1134 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
1135 FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport)
1136 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
1137 FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
1138 FN_GLOBAL_BOOL(lp_domain_controller,&Globals.bDomainController)
1139 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
1140 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
1141 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
1142 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
1143 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
1144 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
1145 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
1146 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
1147 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
1148 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
1149 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
1150 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
1151 FN_GLOBAL_BOOL(lp_update_encrypted,&Globals.bUpdateEncrypt)
1152 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
1153 FN_GLOBAL_BOOL(lp_timestamp_logs,&Globals.bTimestampLogs)
1154 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
1155 FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
1156 FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
1157 static FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
1158 FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
1159 FN_GLOBAL_BOOL(lp_net_wksta_user_logon,&Globals.bNetWkstaUserLogon)
1160 FN_GLOBAL_BOOL(lp_unix_password_sync,&Globals.bUnixPasswdSync)
1161 FN_GLOBAL_BOOL(lp_passwd_chat_debug,&Globals.bPasswdChatDebug)
1162 FN_GLOBAL_BOOL(lp_ole_locking_compat,&Globals.bOleLockingCompat)
1163 FN_GLOBAL_BOOL(lp_nt_smb_support,&Globals.bNTSmbSupport)
1164 FN_GLOBAL_BOOL(lp_stat_cache,&Globals.bStatCache)
1165 FN_GLOBAL_BOOL(lp_kernel_oplocks,&Globals.bKernelOplocks)
1166
1167 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
1168 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
1169 FN_GLOBAL_INTEGER(lp_max_wins_ttl,&Globals.max_wins_ttl)
1170 FN_GLOBAL_INTEGER(lp_min_wins_ttl,&Globals.max_wins_ttl)
1171 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
1172 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
1173 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
1174 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
1175 FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel)
1176 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
1177 FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
1178 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
1179 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
1180 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
1181 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
1182 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
1183 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
1184 FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
1185 static FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
1186 FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
1187 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
1188 FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
1189 FN_GLOBAL_INTEGER(lp_change_notify_timeout,&Globals.change_notify_timeout)
1190 FN_GLOBAL_INTEGER(lp_stat_cache_size,&Globals.stat_cache_size)
1191
1192 #ifdef WITH_LDAP
1193 FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)
1194 #endif /* WITH_LDAP */
1195
1196 FN_LOCAL_STRING(lp_preexec,szPreExec)
1197 FN_LOCAL_STRING(lp_postexec,szPostExec)
1198 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
1199 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
1200 FN_LOCAL_STRING(lp_servicename,szService)
1201 FN_LOCAL_STRING(lp_pathname,szPath)
1202 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
1203 FN_LOCAL_STRING(lp_username,szUsername)
1204 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
1205 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
1206 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
1207 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
1208 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
1209 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
1210 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
1211 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
1212 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
1213 FN_LOCAL_STRING(lp_queuepausecommand,szQueuepausecommand)
1214 FN_LOCAL_STRING(lp_queueresumecommand,szQueueresumecommand)
1215 FN_LOCAL_STRING(lp_printername,szPrintername)
1216 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
1217 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
1218 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
1219 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
1220 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
1221 FN_LOCAL_STRING(lp_comment,comment)
1222 FN_LOCAL_STRING(lp_force_user,force_user)
1223 FN_LOCAL_STRING(lp_force_group,force_group)
1224 FN_LOCAL_STRING(lp_readlist,readlist)
1225 FN_LOCAL_STRING(lp_writelist,writelist)
1226 FN_LOCAL_STRING(lp_fstype,fstype)
1227 static FN_LOCAL_STRING(lp_volume,volume)
1228 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
1229 FN_LOCAL_STRING(lp_veto_files,szVetoFiles)
1230 FN_LOCAL_STRING(lp_hide_files,szHideFiles)
1231 FN_LOCAL_STRING(lp_veto_oplocks,szVetoOplockFiles)
1232 FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
1233
1234 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
1235 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
1236 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
1237 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
1238 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
1239 FN_LOCAL_BOOL(lp_status,status)
1240 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
1241 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
1242 FN_LOCAL_BOOL(lp_readonly,bRead_only)
1243 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
1244 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
1245 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
1246 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
1247 FN_LOCAL_BOOL(lp_postscript,bPostscript)
1248 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
1249 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
1250 FN_LOCAL_BOOL(lp_locking,bLocking)
1251 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
1252 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
1253 FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
1254 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
1255 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
1256 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
1257 FN_LOCAL_BOOL(lp_symlinks,bSymlinks)
1258 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
1259 FN_LOCAL_BOOL(lp_strict_sync,bStrictSync)
1260 FN_LOCAL_BOOL(lp_map_system,bMap_system)
1261 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
1262 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
1263 FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
1264 FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
1265 FN_LOCAL_BOOL(lp_dos_filetime_resolution,bDosFiletimeResolution)
1266 FN_LOCAL_BOOL(lp_fake_dir_create_times,bFakeDirCreateTimes)
1267 FN_LOCAL_BOOL(lp_blocking_locks,bBlockingLocks)
1268
1269 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask)
1270 FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)
1271 FN_LOCAL_INTEGER(lp_dir_mode,iDir_mask)
1272 FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode)
1273 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
1274 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
1275 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
1276 FN_LOCAL_INTEGER(lp_printing,iPrinting)
1277
1278 FN_LOCAL_CHAR(lp_magicchar,magic_char)
1279
1280
1281
1282 /* local prototypes */
1283 static int    strwicmp( char *psz1, char *psz2 );
1284 static int    map_parameter( char *pszParmName);
1285 static BOOL   set_boolean( BOOL *pb, char *pszParmValue );
1286 static int    getservicebyname(char *pszServiceName, service *pserviceDest);
1287 static void   copy_service( service *pserviceDest, 
1288                             service *pserviceSource,
1289                             BOOL *pcopymapDest );
1290 static BOOL   service_ok(int iService);
1291 static BOOL   do_parameter(char *pszParmName, char *pszParmValue);
1292 static BOOL   do_section(char *pszSectionName);
1293 static void init_copymap(service *pservice);
1294
1295
1296 /***************************************************************************
1297 initialise a service to the defaults
1298 ***************************************************************************/
1299 static void init_service(service *pservice)
1300 {
1301   bzero((char *)pservice,sizeof(service));
1302   copy_service(pservice,&sDefault,NULL);
1303 }
1304
1305
1306 /***************************************************************************
1307 free the dynamically allocated parts of a service struct
1308 ***************************************************************************/
1309 static void free_service(service *pservice)
1310 {
1311   int i;
1312   if (!pservice)
1313      return;
1314
1315   if(pservice->szService)
1316     DEBUG(5,("free_service: Freeing service %s\n", pservice->szService));
1317
1318   string_free(&pservice->szService);
1319   if (pservice->copymap)
1320   {
1321     free(pservice->copymap);
1322     pservice->copymap = NULL;
1323   }
1324  
1325   for (i=0;parm_table[i].label;i++)
1326     if ((parm_table[i].type == P_STRING ||
1327          parm_table[i].type == P_USTRING) &&
1328         parm_table[i].class == P_LOCAL)
1329       string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
1330 }
1331
1332 /***************************************************************************
1333 add a new service to the services array initialising it with the given 
1334 service
1335 ***************************************************************************/
1336 static int add_a_service(service *pservice, char *name)
1337 {
1338   int i;
1339   service tservice;
1340   int num_to_alloc = iNumServices+1;
1341
1342   tservice = *pservice;
1343
1344   /* it might already exist */
1345   if (name) 
1346     {
1347       i = getservicebyname(name,NULL);
1348       if (i >= 0)
1349         return(i);
1350     }
1351
1352   /* find an invalid one */
1353   for (i=0;i<iNumServices;i++)
1354     if (!pSERVICE(i)->valid)
1355       break;
1356
1357   /* if not, then create one */
1358   if (i == iNumServices)
1359     {
1360       ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
1361       if (ServicePtrs)
1362         pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
1363
1364       if (!ServicePtrs || !pSERVICE(iNumServices))
1365         return(-1);
1366
1367       iNumServices++;
1368     }
1369   else
1370     free_service(pSERVICE(i));
1371
1372   pSERVICE(i)->valid = True;
1373
1374   init_service(pSERVICE(i));
1375   copy_service(pSERVICE(i),&tservice,NULL);
1376   if (name)
1377     string_set(&iSERVICE(i).szService,name);  
1378
1379   return(i);
1380 }
1381
1382 /***************************************************************************
1383 add a new home service, with the specified home directory, defaults coming 
1384 from service ifrom
1385 ***************************************************************************/
1386 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
1387 {
1388   int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
1389
1390   if (i < 0)
1391     return(False);
1392
1393   if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
1394     string_set(&iSERVICE(i).szPath,pszHomedir);
1395   if (!(*(iSERVICE(i).comment)))
1396     {
1397       pstring comment;
1398       slprintf(comment,sizeof(comment)-1,
1399                "Home directory of %s",pszHomename);
1400       string_set(&iSERVICE(i).comment,comment);
1401     }
1402   iSERVICE(i).bAvailable = sDefault.bAvailable;
1403   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1404
1405   DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
1406
1407   return(True);
1408 }
1409
1410 /***************************************************************************
1411 add a new service, based on an old one
1412 ***************************************************************************/
1413 int lp_add_service(char *pszService, int iDefaultService)
1414 {
1415   return(add_a_service(pSERVICE(iDefaultService),pszService));
1416 }
1417
1418
1419 /***************************************************************************
1420 add the IPC service
1421 ***************************************************************************/
1422 static BOOL lp_add_ipc(void)
1423 {
1424   pstring comment;
1425   int i = add_a_service(&sDefault,"IPC$");
1426
1427   if (i < 0)
1428     return(False);
1429
1430   slprintf(comment,sizeof(comment)-1,
1431            "IPC Service (%s)", Globals.szServerString );
1432
1433   string_set(&iSERVICE(i).szPath,tmpdir());
1434   string_set(&iSERVICE(i).szUsername,"");
1435   string_set(&iSERVICE(i).comment,comment);
1436   iSERVICE(i).status = False;
1437   iSERVICE(i).iMaxConnections = 0;
1438   iSERVICE(i).bAvailable = True;
1439   iSERVICE(i).bRead_only = True;
1440   iSERVICE(i).bGuest_only = False;
1441   iSERVICE(i).bGuest_ok = True;
1442   iSERVICE(i).bPrint_ok = False;
1443   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1444
1445   DEBUG(3,("adding IPC service\n"));
1446
1447   return(True);
1448 }
1449
1450
1451 /***************************************************************************
1452 add a new printer service, with defaults coming from service iFrom
1453 ***************************************************************************/
1454 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1455 {
1456   char *comment = "From Printcap";
1457   int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1458   
1459   if (i < 0)
1460     return(False);
1461   
1462   /* note that we do NOT default the availability flag to True - */
1463   /* we take it from the default service passed. This allows all */
1464   /* dynamic printers to be disabled by disabling the [printers] */
1465   /* entry (if/when the 'available' keyword is implemented!).    */
1466   
1467   /* the printer name is set to the service name. */
1468   string_set(&iSERVICE(i).szPrintername,pszPrintername);
1469   string_set(&iSERVICE(i).comment,comment);
1470   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1471   /* Printers cannot be read_only. */
1472   iSERVICE(i).bRead_only = False;
1473   /* No share modes on printer services. */
1474   iSERVICE(i).bShareModes = False;
1475   /* No oplocks on printer services. */
1476   iSERVICE(i).bOpLocks = False;
1477   /* Printer services must be printable. */
1478   iSERVICE(i).bPrint_ok = True;
1479   
1480   DEBUG(3,("adding printer service %s\n",pszPrintername));
1481   
1482   return(True);
1483 }
1484
1485
1486 /***************************************************************************
1487 Do a case-insensitive, whitespace-ignoring string compare.
1488 ***************************************************************************/
1489 static int strwicmp(char *psz1, char *psz2)
1490 {
1491    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1492    /* appropriate value. */
1493    if (psz1 == psz2)
1494       return (0);
1495    else
1496       if (psz1 == NULL)
1497          return (-1);
1498       else
1499           if (psz2 == NULL)
1500               return (1);
1501
1502    /* sync the strings on first non-whitespace */
1503    while (1)
1504    {
1505       while (isspace(*psz1))
1506          psz1++;
1507       while (isspace(*psz2))
1508          psz2++;
1509       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1510          break;
1511       psz1++;
1512       psz2++;
1513    }
1514    return (*psz1 - *psz2);
1515 }
1516
1517 /***************************************************************************
1518 Map a parameter's string representation to something we can use. 
1519 Returns False if the parameter string is not recognised, else TRUE.
1520 ***************************************************************************/
1521 static int map_parameter(char *pszParmName)
1522 {
1523    int iIndex;
1524
1525    if (*pszParmName == '-')
1526      return(-1);
1527
1528    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
1529       if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1530          return(iIndex);
1531
1532    DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1533    return(-1);
1534 }
1535
1536
1537 /***************************************************************************
1538 Set a boolean variable from the text value stored in the passed string.
1539 Returns True in success, False if the passed string does not correctly 
1540 represent a boolean.
1541 ***************************************************************************/
1542 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1543 {
1544    BOOL bRetval;
1545
1546    bRetval = True;
1547    if (strwicmp(pszParmValue, "yes") == 0 ||
1548        strwicmp(pszParmValue, "true") == 0 ||
1549        strwicmp(pszParmValue, "1") == 0)
1550       *pb = True;
1551    else
1552       if (strwicmp(pszParmValue, "no") == 0 ||
1553           strwicmp(pszParmValue, "False") == 0 ||
1554           strwicmp(pszParmValue, "0") == 0)
1555          *pb = False;
1556       else
1557       {
1558          DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1559                pszParmValue));
1560          bRetval = False;
1561       }
1562    return (bRetval);
1563 }
1564
1565 /***************************************************************************
1566 Find a service by name. Otherwise works like get_service.
1567 ***************************************************************************/
1568 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1569 {
1570    int iService;
1571
1572    for (iService = iNumServices - 1; iService >= 0; iService--)
1573       if (VALID(iService) &&
1574           strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) 
1575       {
1576          if (pserviceDest != NULL)
1577            copy_service(pserviceDest, pSERVICE(iService), NULL);
1578          break;
1579       }
1580
1581    return (iService);
1582 }
1583
1584
1585
1586 /***************************************************************************
1587 Copy a service structure to another
1588
1589 If pcopymapDest is NULL then copy all fields
1590 ***************************************************************************/
1591 static void copy_service(service *pserviceDest, 
1592                          service *pserviceSource,
1593                          BOOL *pcopymapDest)
1594 {
1595   int i;
1596   BOOL bcopyall = (pcopymapDest == NULL);
1597
1598   for (i=0;parm_table[i].label;i++)
1599     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && 
1600         (bcopyall || pcopymapDest[i]))
1601       {
1602         void *def_ptr = parm_table[i].ptr;
1603         void *src_ptr = 
1604           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1605         void *dest_ptr = 
1606           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1607
1608         switch (parm_table[i].type)
1609           {
1610           case P_BOOL:
1611           case P_BOOLREV:
1612             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1613             break;
1614
1615           case P_INTEGER:
1616           case P_ENUM:
1617           case P_OCTAL:
1618             *(int *)dest_ptr = *(int *)src_ptr;
1619             break;
1620
1621           case P_CHAR:
1622             *(char *)dest_ptr = *(char *)src_ptr;
1623             break;
1624
1625           case P_STRING:
1626             string_set(dest_ptr,*(char **)src_ptr);
1627             break;
1628
1629           case P_USTRING:
1630             string_set(dest_ptr,*(char **)src_ptr);
1631             strupper(*(char **)dest_ptr);
1632             break;
1633           default:
1634             break;
1635           }
1636       }
1637
1638   if (bcopyall)
1639     {
1640       init_copymap(pserviceDest);
1641       if (pserviceSource->copymap)
1642         memcpy((void *)pserviceDest->copymap,
1643                (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1644     }
1645 }
1646
1647 /***************************************************************************
1648 Check a service for consistency. Return False if the service is in any way
1649 incomplete or faulty, else True.
1650 ***************************************************************************/
1651 static BOOL service_ok(int iService)
1652 {
1653    BOOL bRetval;
1654
1655    bRetval = True;
1656    if (iSERVICE(iService).szService[0] == '\0')
1657    {
1658       DEBUG(0,( "The following message indicates an internal error:\n"));
1659       DEBUG(0,( "No service name in service entry.\n"));
1660       bRetval = False;
1661    }
1662
1663    /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1664    /* I can't see why you'd want a non-printable printer service...        */
1665    if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1666       if (!iSERVICE(iService).bPrint_ok)
1667       {
1668          DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1669                iSERVICE(iService).szService));
1670          iSERVICE(iService).bPrint_ok = True;
1671       }
1672
1673    if (iSERVICE(iService).szPath[0] == '\0' &&
1674        strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1675    {
1676       DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1677       string_set(&iSERVICE(iService).szPath,tmpdir());      
1678    }
1679
1680    /* If a service is flagged unavailable, log the fact at level 0. */
1681    if (!iSERVICE(iService).bAvailable) 
1682       DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1683             iSERVICE(iService).szService));
1684
1685    return (bRetval);
1686 }
1687
1688 static struct file_lists {
1689   struct file_lists *next;
1690   char *name;
1691   time_t modtime;
1692 } *file_lists = NULL;
1693
1694 /*******************************************************************
1695 keep a linked list of all config files so we know when one has changed 
1696 it's date and needs to be reloaded
1697 ********************************************************************/
1698 static void add_to_file_list(char *fname)
1699 {
1700   struct file_lists *f=file_lists;
1701
1702   while (f) {
1703     if (f->name && !strcmp(f->name,fname)) break;
1704     f = f->next;
1705   }
1706
1707   if (!f) {
1708     f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1709     if (!f) return;
1710     f->next = file_lists;
1711     f->name = strdup(fname);
1712     if (!f->name) {
1713       free(f);
1714       return;
1715     }
1716     file_lists = f;
1717   }
1718
1719   {
1720     pstring n2;
1721     pstrcpy(n2,fname);
1722     standard_sub_basic(n2);
1723     f->modtime = file_modtime(n2);
1724   }
1725
1726 }
1727
1728 /*******************************************************************
1729 check if a config file has changed date
1730 ********************************************************************/
1731 BOOL lp_file_list_changed(void)
1732 {
1733   struct file_lists *f = file_lists;
1734   DEBUG(6,("lp_file_list_changed()\n"));
1735
1736   while (f)
1737   {
1738     pstring n2;
1739     time_t mod_time;
1740
1741     pstrcpy(n2,f->name);
1742     standard_sub_basic(n2);
1743
1744     DEBUGADD( 6, ( "file %s -> %s  last mod_time: %s\n",
1745                    f->name, n2, ctime(&f->modtime) ) );
1746
1747     mod_time = file_modtime(n2);
1748
1749     if (f->modtime != mod_time) {
1750             DEBUGADD(6,("file %s modified: %s\n", n2, ctime(&mod_time)));
1751             f->modtime = mod_time;
1752             return(True);
1753     }
1754     f = f->next;
1755   }
1756   return(False);
1757 }
1758
1759 /***************************************************************************
1760   handle the interpretation of the coding system parameter
1761   *************************************************************************/
1762 static BOOL handle_coding_system(char *pszParmValue,char **ptr)
1763 {
1764         string_set(ptr,pszParmValue);
1765         interpret_coding_system(pszParmValue);
1766         return(True);
1767 }
1768
1769 /***************************************************************************
1770 handle the interpretation of the character set system parameter
1771 ***************************************************************************/
1772 static BOOL handle_character_set(char *pszParmValue,char **ptr)
1773 {
1774         string_set(ptr,pszParmValue);
1775         interpret_character_set(pszParmValue);
1776         return(True);
1777 }
1778
1779
1780 /***************************************************************************
1781 handle the valid chars lines
1782 ***************************************************************************/
1783 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1784
1785   string_set(ptr,pszParmValue);
1786
1787   /* A dependency here is that the parameter client code page must be
1788      set before this is called - as calling codepage_initialise()
1789      would overwrite the valid char lines.
1790    */
1791   codepage_initialise(lp_client_code_page());
1792
1793   add_char_string(pszParmValue);
1794   return(True);
1795 }
1796
1797
1798 /***************************************************************************
1799 handle the include operation
1800 ***************************************************************************/
1801 static BOOL handle_include(char *pszParmValue,char **ptr)
1802
1803   pstring fname;
1804   pstrcpy(fname,pszParmValue);
1805
1806   add_to_file_list(fname);
1807
1808   standard_sub_basic(fname);
1809
1810   string_set(ptr,fname);
1811
1812   if (file_exist(fname,NULL))
1813     return(pm_process(fname, do_section, do_parameter));      
1814
1815   DEBUG(2,("Can't find include file %s\n",fname));
1816
1817   return(False);
1818 }
1819
1820
1821 /***************************************************************************
1822 handle the interpretation of the copy parameter
1823 ***************************************************************************/
1824 static BOOL handle_copy(char *pszParmValue,char **ptr)
1825 {
1826    BOOL bRetval;
1827    int iTemp;
1828    service serviceTemp;
1829
1830    string_set(ptr,pszParmValue);
1831
1832    init_service(&serviceTemp);
1833
1834    bRetval = False;
1835    
1836    DEBUG(3,("Copying service from service %s\n",pszParmValue));
1837
1838    if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1839      {
1840        if (iTemp == iServiceIndex)
1841          {
1842            DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1843                     pszParmValue));
1844          }
1845        else
1846          {
1847            copy_service(pSERVICE(iServiceIndex), 
1848                         &serviceTemp,
1849                         iSERVICE(iServiceIndex).copymap);
1850            bRetval = True;
1851          }
1852      }
1853    else
1854      {
1855        DEBUG(0,( "Unable to copy service - source not found: %s\n",
1856                 pszParmValue));
1857        bRetval = False;
1858      }
1859
1860    free_service(&serviceTemp);
1861    return (bRetval);
1862 }
1863
1864
1865 /***************************************************************************
1866 initialise a copymap
1867 ***************************************************************************/
1868 static void init_copymap(service *pservice)
1869 {
1870   int i;
1871   if (pservice->copymap) free(pservice->copymap);
1872   pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1873   if (!pservice->copymap)
1874     DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1875
1876   for (i=0;i<NUMPARAMETERS;i++)
1877     pservice->copymap[i] = True;
1878 }
1879
1880
1881 /***************************************************************************
1882  return the local pointer to a parameter given the service number and the 
1883  pointer into the default structure
1884 ***************************************************************************/
1885 void *lp_local_ptr(int snum, void *ptr)
1886 {
1887         return (void *)(((char *)pSERVICE(snum)) + PTR_DIFF(ptr,&sDefault));
1888 }
1889
1890 /***************************************************************************
1891 Process a parameter for a particular service number. If snum < 0
1892 then assume we are in the globals
1893 ***************************************************************************/
1894 BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
1895 {
1896    int parmnum, i;
1897    void *parm_ptr=NULL; /* where we are going to store the result */
1898    void *def_ptr=NULL;
1899
1900    parmnum = map_parameter(pszParmName);
1901
1902    if (parmnum < 0)
1903      {
1904        DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1905        return(True);
1906      }
1907
1908    if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1909            DEBUG(1,("WARNING: The \"%s\"option is deprecated\n",
1910                     pszParmName));
1911    }
1912
1913    def_ptr = parm_table[parmnum].ptr;
1914
1915    /* we might point at a service, the default service or a global */
1916    if (snum < 0) {
1917      parm_ptr = def_ptr;
1918    } else {
1919        if (parm_table[parmnum].class == P_GLOBAL) {
1920            DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1921            return(True);
1922          }
1923        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
1924    }
1925
1926    if (snum >= 0) {
1927            if (!iSERVICE(snum).copymap)
1928                    init_copymap(pSERVICE(snum));
1929            
1930            /* this handles the aliases - set the copymap for other entries with
1931               the same data pointer */
1932            for (i=0;parm_table[i].label;i++)
1933                    if (parm_table[i].ptr == parm_table[parmnum].ptr)
1934                            iSERVICE(snum).copymap[i] = False;
1935    }
1936
1937    /* if it is a special case then go ahead */
1938    if (parm_table[parmnum].special) {
1939            parm_table[parmnum].special(pszParmValue,(char **)parm_ptr);
1940            return(True);
1941    }
1942
1943    /* now switch on the type of variable it is */
1944    switch (parm_table[parmnum].type)
1945      {
1946      case P_BOOL:
1947        set_boolean(parm_ptr,pszParmValue);
1948        break;
1949
1950      case P_BOOLREV:
1951        set_boolean(parm_ptr,pszParmValue);
1952        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1953        break;
1954
1955      case P_INTEGER:
1956        *(int *)parm_ptr = atoi(pszParmValue);
1957        break;
1958
1959      case P_CHAR:
1960        *(char *)parm_ptr = *pszParmValue;
1961        break;
1962
1963      case P_OCTAL:
1964        sscanf(pszParmValue,"%o",(int *)parm_ptr);
1965        break;
1966
1967      case P_STRING:
1968        string_set(parm_ptr,pszParmValue);
1969        break;
1970
1971      case P_USTRING:
1972        string_set(parm_ptr,pszParmValue);
1973        strupper(*(char **)parm_ptr);
1974        break;
1975
1976      case P_GSTRING:
1977        pstrcpy((char *)parm_ptr,pszParmValue);
1978        break;
1979
1980      case P_UGSTRING:
1981        pstrcpy((char *)parm_ptr,pszParmValue);
1982        strupper((char *)parm_ptr);
1983        break;
1984
1985      case P_ENUM:
1986              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
1987                      if (strequal(pszParmValue, parm_table[parmnum].enum_list[i].name)) {
1988                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
1989                              break;
1990                      }
1991              }
1992              break;
1993      case P_SEP:
1994              break;
1995      }
1996
1997    return(True);
1998 }
1999
2000 /***************************************************************************
2001 Process a parameter.
2002 ***************************************************************************/
2003 static BOOL do_parameter( char *pszParmName, char *pszParmValue )
2004 {
2005   if( !bInGlobalSection && bGlobalOnly )
2006     return(True);
2007
2008   DEBUGADD( 3, ( "doing parameter %s = %s\n", pszParmName, pszParmValue ) );
2009
2010   return( lp_do_parameter( bInGlobalSection ? -2 : iServiceIndex,
2011                            pszParmName,
2012                            pszParmValue ) );
2013 }
2014
2015
2016 /***************************************************************************
2017 print a parameter of the specified type
2018 ***************************************************************************/
2019 static void print_parameter(struct parm_struct *p,void *ptr, FILE *f)
2020 {
2021         int i;
2022         switch (p->type) {
2023         case P_ENUM:
2024                 for (i=0;p->enum_list[i].name;i++) {
2025                         if (*(int *)ptr == p->enum_list[i].value) {
2026                                 fprintf(f,"%s",p->enum_list[i].name);
2027                                 break;
2028                         }
2029                 }
2030                 break;
2031
2032         case P_BOOL:
2033                 fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr));
2034                 break;
2035       
2036         case P_BOOLREV:
2037                 fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr));
2038                 break;
2039       
2040         case P_INTEGER:
2041                 fprintf(f,"%d",*(int *)ptr);
2042                 break;
2043       
2044         case P_CHAR:
2045                 fprintf(f,"%c",*(char *)ptr);
2046                 break;
2047       
2048         case P_OCTAL:
2049                 fprintf(f,"0%o",*(int *)ptr);
2050                 break;
2051       
2052         case P_GSTRING:
2053         case P_UGSTRING:
2054                 if ((char *)ptr)
2055                         fprintf(f,"%s",(char *)ptr);
2056                 break;
2057                 
2058         case P_STRING:
2059         case P_USTRING:
2060                 if (*(char **)ptr)
2061                         fprintf(f,"%s",*(char **)ptr);
2062                 break;
2063         case P_SEP:
2064                 break;
2065         }
2066 }
2067
2068
2069 /***************************************************************************
2070 check if two parameters are equal
2071 ***************************************************************************/
2072 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
2073 {
2074   switch (type)
2075     {
2076     case P_BOOL:
2077     case P_BOOLREV:
2078       return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
2079
2080     case P_INTEGER:
2081     case P_ENUM:
2082     case P_OCTAL:
2083       return(*((int *)ptr1) == *((int *)ptr2));
2084       
2085     case P_CHAR:
2086       return(*((char *)ptr1) == *((char *)ptr2));
2087
2088     case P_GSTRING:
2089     case P_UGSTRING:
2090       {
2091         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
2092         if (p1 && !*p1) p1 = NULL;
2093         if (p2 && !*p2) p2 = NULL;
2094         return(p1==p2 || strequal(p1,p2));
2095       }
2096     case P_STRING:
2097     case P_USTRING:
2098       {
2099         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2100         if (p1 && !*p1) p1 = NULL;
2101         if (p2 && !*p2) p2 = NULL;
2102         return(p1==p2 || strequal(p1,p2));
2103       }
2104      case P_SEP:
2105              break;
2106     }
2107   return(False);
2108 }
2109
2110 /***************************************************************************
2111 Process a new section (service). At this stage all sections are services.
2112 Later we'll have special sections that permit server parameters to be set.
2113 Returns True on success, False on failure.
2114 ***************************************************************************/
2115 static BOOL do_section(char *pszSectionName)
2116 {
2117    BOOL bRetval;
2118    BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || 
2119                     (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2120    bRetval = False;
2121
2122    /* if we were in a global section then do the local inits */
2123    if (bInGlobalSection && !isglobal)
2124      init_locals();
2125
2126    /* if we've just struck a global section, note the fact. */
2127    bInGlobalSection = isglobal;   
2128
2129    /* check for multiple global sections */
2130    if (bInGlobalSection)
2131    {
2132      DEBUG( 3, ( "Processing section \"[%s]\"\n", pszSectionName ) );
2133      return(True);
2134    }
2135
2136    if (!bInGlobalSection && bGlobalOnly) return(True);
2137
2138    /* if we have a current service, tidy it up before moving on */
2139    bRetval = True;
2140
2141    if (iServiceIndex >= 0)
2142      bRetval = service_ok(iServiceIndex);
2143
2144    /* if all is still well, move to the next record in the services array */
2145    if (bRetval)
2146      {
2147        /* We put this here to avoid an odd message order if messages are */
2148        /* issued by the post-processing of a previous section. */
2149        DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
2150
2151        if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
2152          {
2153            DEBUG(0,("Failed to add a new service\n"));
2154            return(False);
2155          }
2156      }
2157
2158    return (bRetval);
2159 }
2160
2161
2162 /***************************************************************************
2163 determine if a partcular base parameter is currently set to the default value.
2164 ***************************************************************************/
2165 static BOOL is_default(int i)
2166 {
2167         if (!defaults_saved) return False;
2168         switch (parm_table[i].type) {
2169         case P_STRING:
2170         case P_USTRING:
2171                 return strequal(parm_table[i].def.svalue,*(char **)parm_table[i].ptr);
2172         case P_GSTRING:
2173         case P_UGSTRING:
2174                 return strequal(parm_table[i].def.svalue,(char *)parm_table[i].ptr);
2175         case P_BOOL:
2176         case P_BOOLREV:
2177                 return parm_table[i].def.bvalue == *(BOOL *)parm_table[i].ptr;
2178         case P_CHAR:
2179                 return parm_table[i].def.cvalue == *(char *)parm_table[i].ptr;
2180         case P_INTEGER:
2181         case P_OCTAL:
2182         case P_ENUM:
2183                 return parm_table[i].def.ivalue == *(int *)parm_table[i].ptr;
2184         case P_SEP:
2185                 break;
2186         }
2187         return False;
2188 }
2189
2190
2191 /***************************************************************************
2192 Display the contents of the global structure.
2193 ***************************************************************************/
2194 static void dump_globals(FILE *f)
2195 {
2196         int i;
2197         fprintf(f, "# Global parameters\n");
2198         
2199         for (i=0;parm_table[i].label;i++)
2200                 if (parm_table[i].class == P_GLOBAL &&
2201                     parm_table[i].ptr &&
2202                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2203                         if (defaults_saved && is_default(i)) continue;
2204                         fprintf(f,"\t%s = ",parm_table[i].label);
2205                         print_parameter(&parm_table[i],parm_table[i].ptr, f);
2206                         fprintf(f,"\n");
2207                 }
2208 }
2209
2210 /***************************************************************************
2211 return True if a local parameter is currently set to the global default
2212 ***************************************************************************/
2213 BOOL lp_is_default(int snum, struct parm_struct *parm)
2214 {
2215         int pdiff = PTR_DIFF(parm->ptr,&sDefault);
2216                         
2217         return equal_parameter(parm->type,
2218                                ((char *)pSERVICE(snum)) + pdiff,
2219                                ((char *)&sDefault) + pdiff);
2220 }
2221
2222
2223 /***************************************************************************
2224 Display the contents of a single services record.
2225 ***************************************************************************/
2226 static void dump_a_service(service *pService, FILE *f)
2227 {
2228         int i;
2229         if (pService != &sDefault)
2230                 fprintf(f,"\n[%s]\n",pService->szService);
2231
2232         for (i=0;parm_table[i].label;i++)
2233                 if (parm_table[i].class == P_LOCAL &&
2234                     parm_table[i].ptr && 
2235                     (*parm_table[i].label != '-') &&
2236                     (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) {
2237                         int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
2238                         
2239                         if (pService == &sDefault) {
2240                                 if (defaults_saved && is_default(i)) continue;
2241                         } else {
2242                                 if (equal_parameter(parm_table[i].type,
2243                                                     ((char *)pService) + pdiff,
2244                                                     ((char *)&sDefault) + pdiff)) 
2245                                         continue;
2246                         }
2247
2248                         fprintf(f,"\t%s = ",parm_table[i].label);
2249                         print_parameter(&parm_table[i],
2250                                         ((char *)pService) + pdiff, f);
2251                         fprintf(f,"\n");
2252                 }
2253 }
2254
2255
2256 /***************************************************************************
2257 return info about the next service  in a service. snum==-1 gives the globals
2258
2259 return NULL when out of parameters
2260 ***************************************************************************/
2261 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
2262 {
2263         if (snum == -1) {
2264                 /* do the globals */
2265                 for (;parm_table[*i].label;(*i)++) {
2266                         if (parm_table[*i].class == P_SEPARATOR) 
2267                                 return &parm_table[(*i)++];
2268
2269                         if (!parm_table[*i].ptr || (*parm_table[*i].label == '-'))
2270                                 continue;
2271                         
2272                         if ((*i) > 0 && (parm_table[*i].ptr == parm_table[(*i)-1].ptr))
2273                                 continue;
2274
2275                         return &parm_table[(*i)++];
2276                 }
2277         } else {
2278                 service *pService = pSERVICE(snum);
2279
2280                 for (;parm_table[*i].label;(*i)++) {
2281                         if (parm_table[*i].class == P_SEPARATOR) 
2282                                 return &parm_table[(*i)++];
2283
2284                         if (parm_table[*i].class == P_LOCAL &&
2285                             parm_table[*i].ptr && 
2286                             (*parm_table[*i].label != '-') &&
2287                             ((*i) == 0 || 
2288                              (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
2289                                 int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault);
2290                                 
2291                                 if (allparameters ||
2292                                     !equal_parameter(parm_table[*i].type,
2293                                                      ((char *)pService) + pdiff,
2294                                                      ((char *)&sDefault) + pdiff)) {
2295                                         return &parm_table[(*i)++];
2296                                 }
2297                         }
2298                 }
2299         }
2300
2301         return NULL;
2302 }
2303
2304
2305 #if 0
2306 /***************************************************************************
2307 Display the contents of a single copy structure.
2308 ***************************************************************************/
2309 static void dump_copy_map(BOOL *pcopymap)
2310 {
2311   int i;
2312   if (!pcopymap) return;
2313
2314   printf("\n\tNon-Copied parameters:\n");
2315
2316   for (i=0;parm_table[i].label;i++)
2317     if (parm_table[i].class == P_LOCAL &&
2318         parm_table[i].ptr && !pcopymap[i] &&
2319         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
2320       {
2321         printf("\t\t%s\n",parm_table[i].label);
2322       }
2323 }
2324 #endif
2325
2326 /***************************************************************************
2327 Return TRUE if the passed service number is within range.
2328 ***************************************************************************/
2329 BOOL lp_snum_ok(int iService)
2330 {
2331    return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
2332 }
2333
2334
2335 /***************************************************************************
2336 auto-load some home services
2337 ***************************************************************************/
2338 static void lp_add_auto_services(char *str)
2339 {
2340         char *s;
2341         char *p;
2342         int homes;
2343
2344         if (!str) return;
2345
2346         s = strdup(str);
2347         if (!s) return;
2348
2349         homes = lp_servicenumber(HOMES_NAME);
2350         
2351         for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) {
2352                 char *home = get_home_dir(p);
2353                 
2354                 if (lp_servicenumber(p) >= 0) continue;
2355                 
2356                 if (home && homes >= 0) {
2357                         lp_add_home(p,homes,home);
2358                 }
2359         }
2360         free(s);
2361 }
2362
2363 /***************************************************************************
2364 auto-load one printer
2365 ***************************************************************************/
2366 void lp_add_one_printer(char *name,char *comment)
2367 {
2368         int printers = lp_servicenumber(PRINTERS_NAME);
2369         int i;
2370
2371         if (lp_servicenumber(name) < 0)  {
2372                 lp_add_printer(name,printers);
2373                 if ((i=lp_servicenumber(name)) >= 0)
2374                         string_set(&iSERVICE(i).comment,comment);
2375         }
2376 }
2377
2378 /***************************************************************************
2379 have we loaded a services file yet?
2380 ***************************************************************************/
2381 BOOL lp_loaded(void)
2382 {
2383   return(bLoaded);
2384 }
2385
2386 /***************************************************************************
2387 unload unused services
2388 ***************************************************************************/
2389 void lp_killunused(BOOL (*snumused)(int ))
2390 {
2391   int i;
2392   for (i=0;i<iNumServices;i++)
2393     if (VALID(i) && (!snumused || !snumused(i)))
2394       {
2395         iSERVICE(i).valid = False;
2396         free_service(pSERVICE(i));
2397       }
2398 }
2399
2400
2401 /***************************************************************************
2402 save the curent values of all global and sDefault parameters into the 
2403 defaults union. This allows swat and testparm to show only the
2404 changed (ie. non-default) parameters.
2405 ***************************************************************************/
2406 static void lp_save_defaults(void)
2407 {
2408         int i;
2409         for (i = 0; parm_table[i].label; i++) {
2410                 if (i>0 && parm_table[i].ptr == parm_table[i-1].ptr) continue;
2411                 switch (parm_table[i].type) {
2412                 case P_STRING:
2413                 case P_USTRING:
2414                         parm_table[i].def.svalue = strdup(*(char **)parm_table[i].ptr);
2415                         break;
2416                 case P_GSTRING:
2417                 case P_UGSTRING:
2418                         parm_table[i].def.svalue = strdup((char *)parm_table[i].ptr);
2419                         break;
2420                 case P_BOOL:
2421                 case P_BOOLREV:
2422                         parm_table[i].def.bvalue = *(BOOL *)parm_table[i].ptr;
2423                         break;
2424                 case P_CHAR:
2425                         parm_table[i].def.cvalue = *(char *)parm_table[i].ptr;
2426                         break;
2427                 case P_INTEGER:
2428                 case P_OCTAL:
2429                 case P_ENUM:
2430                         parm_table[i].def.ivalue = *(int *)parm_table[i].ptr;
2431                         break;
2432                 case P_SEP:
2433                         break;
2434                 }
2435         }
2436         defaults_saved = True;
2437 }
2438
2439
2440 /***************************************************************************
2441 Load the services array from the services file. Return True on success, 
2442 False on failure.
2443 ***************************************************************************/
2444 BOOL lp_load(char *pszFname,BOOL global_only, BOOL save_defaults, BOOL add_ipc)
2445 {
2446   pstring n2;
2447   BOOL bRetval;
2448  
2449   add_to_file_list(pszFname);
2450
2451   bRetval = False;
2452
2453   bInGlobalSection = True;
2454   bGlobalOnly = global_only;
2455   
2456   init_globals();
2457
2458   if (save_defaults) {
2459           init_locals();
2460           lp_save_defaults();
2461   }
2462   
2463   pstrcpy(n2,pszFname);
2464   standard_sub_basic(n2);
2465
2466   /* We get sections first, so have to start 'behind' to make up */
2467   iServiceIndex = -1;
2468   bRetval = pm_process(n2, do_section, do_parameter);
2469   
2470   /* finish up the last section */
2471   DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
2472   if (bRetval)
2473     if (iServiceIndex >= 0)
2474       bRetval = service_ok(iServiceIndex);         
2475
2476   lp_add_auto_services(lp_auto_services());
2477
2478   if (add_ipc)
2479           lp_add_ipc();
2480
2481   set_default_server_announce_type();
2482
2483   bLoaded = True;
2484
2485   return (bRetval);
2486 }
2487
2488
2489 /***************************************************************************
2490 return the max number of services
2491 ***************************************************************************/
2492 int lp_numservices(void)
2493 {
2494   return(iNumServices);
2495 }
2496
2497 /***************************************************************************
2498 Display the contents of the services array in human-readable form.
2499 ***************************************************************************/
2500 void lp_dump(FILE *f, BOOL show_defaults)
2501 {
2502    int iService;
2503
2504    if (show_defaults) {
2505            defaults_saved = False;
2506    }
2507
2508    dump_globals(f);
2509    
2510    dump_a_service(&sDefault, f);
2511
2512    for (iService = 0; iService < iNumServices; iService++)
2513    {
2514      if (VALID(iService))
2515        {
2516          if (iSERVICE(iService).szService[0] == '\0')
2517            break;
2518          dump_a_service(pSERVICE(iService), f);
2519        }
2520    }
2521 }
2522
2523
2524 /***************************************************************************
2525 Return the number of the service with the given name, or -1 if it doesn't
2526 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2527 getservicebyname()! This works ONLY if all services have been loaded, and
2528 does not copy the found service.
2529 ***************************************************************************/
2530 int lp_servicenumber(char *pszServiceName)
2531 {
2532    int iService;
2533
2534    for (iService = iNumServices - 1; iService >= 0; iService--)
2535       if (VALID(iService) &&
2536           strequal(lp_servicename(iService), pszServiceName)) 
2537          break;
2538
2539    if (iService < 0)
2540      DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
2541    
2542    return (iService);
2543 }
2544
2545 /*******************************************************************
2546   a useful volume label function
2547   ******************************************************************/
2548 char *volume_label(int snum)
2549 {
2550   char *ret = lp_volume(snum);
2551   if (!*ret) return(lp_servicename(snum));
2552   return(ret);
2553 }
2554
2555
2556 /*******************************************************************
2557  Set the server type we will announce as via nmbd.
2558 ********************************************************************/
2559 static void set_default_server_announce_type(void)
2560 {
2561   default_server_announce = (SV_TYPE_WORKSTATION | SV_TYPE_SERVER |
2562                               SV_TYPE_SERVER_UNIX | SV_TYPE_PRINTQ_SERVER);
2563   if(lp_announce_as() == ANNOUNCE_AS_NT)
2564     default_server_announce |= (SV_TYPE_SERVER_NT | SV_TYPE_NT);
2565   else if(lp_announce_as() == ANNOUNCE_AS_WIN95)
2566     default_server_announce |= SV_TYPE_WIN95_PLUS;
2567   else if(lp_announce_as() == ANNOUNCE_AS_WFW)
2568     default_server_announce |= SV_TYPE_WFW;
2569   default_server_announce |= (lp_time_server() ? SV_TYPE_TIME_SOURCE : 0);
2570 }
2571
2572
2573 /*******************************************************************
2574 remove a service
2575 ********************************************************************/
2576 void lp_remove_service(int snum)
2577 {
2578         pSERVICE(snum)->valid = False;
2579 }
2580
2581 /*******************************************************************
2582 copy a service
2583 ********************************************************************/
2584 void lp_copy_service(int snum, char *new_name)
2585 {
2586         char *oldname = lp_servicename(snum);
2587         do_section(new_name);
2588         if (snum >= 0) {
2589                 snum = lp_servicenumber(new_name);
2590                 if (snum >= 0)
2591                         lp_do_parameter(snum, "copy", oldname);
2592         }
2593 }
2594
2595
2596 /*******************************************************************
2597  Get the default server type we will announce as via nmbd.
2598 ********************************************************************/
2599 int lp_default_server_announce(void)
2600 {
2601   return default_server_announce;
2602 }
2603
2604 /*******************************************************************
2605  Split the announce version into major and minor numbers.
2606 ********************************************************************/
2607 int lp_major_announce_version(void)
2608 {
2609   static BOOL got_major = False;
2610   static int major_version = DEFAULT_MAJOR_VERSION;
2611   char *vers;
2612   char *p;
2613
2614   if(got_major)
2615     return major_version;
2616
2617   got_major = True;
2618   if((vers = lp_announce_version()) == NULL)
2619     return major_version;
2620   
2621   if((p = strchr(vers, '.')) == 0)
2622     return major_version;
2623
2624   *p = '\0';
2625   major_version = atoi(vers);
2626   return major_version;
2627 }
2628
2629 int lp_minor_announce_version(void)
2630 {
2631   static BOOL got_minor = False;
2632   static int minor_version = DEFAULT_MINOR_VERSION;
2633   char *vers;
2634   char *p;
2635
2636   if(got_minor)
2637     return minor_version;
2638
2639   got_minor = True;
2640   if((vers = lp_announce_version()) == NULL)
2641     return minor_version;
2642   
2643   if((p = strchr(vers, '.')) == 0)              
2644     return minor_version;
2645     
2646   p++;
2647   minor_version = atoi(p);
2648   return minor_version;
2649 }  
2650
2651 /***********************************************************
2652  Set the global name resolution order (used in smbclient).
2653 ************************************************************/
2654
2655 void lp_set_name_resolve_order(char *new_order)
2656
2657   Globals.szNameResolveOrder = new_order;
2658 }
2659
2660 /***********************************************************
2661  Set the real value of kernel oplocks (called by smbd).
2662 ************************************************************/
2663
2664 void lp_set_kernel_oplocks(BOOL val)
2665 {
2666   Globals.bKernelOplocks = val;
2667 }