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