2768a9da72fca6bf80dc0086d3abbb801e192995
[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
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
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 FN_GLOBAL_STRING(lp_domain_sid,&Globals.szDomainSID)
902 FN_GLOBAL_STRING(lp_domain_other_sids,&Globals.szDomainOtherSIDs)
903 FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups)
904 FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers)
905 FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers)
906 FN_GLOBAL_STRING(lp_domain_hostsallow,&Globals.szDomainHostsallow)
907 FN_GLOBAL_STRING(lp_domain_hostsdeny,&Globals.szDomainHostsdeny)
908
909 FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
910 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
911 FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport)
912 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
913 FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
914 FN_GLOBAL_BOOL(lp_domain_controller,&Globals.bDomainController)
915 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
916 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
917 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
918 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
919 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
920 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
921 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
922 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
923 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
924 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
925 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
926 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
927 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
928 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
929 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
930 FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
931 FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
932 FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
933 FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
934 FN_GLOBAL_BOOL(lp_net_wksta_user_logon,&Globals.bNetWkstaUserLogon)
935
936 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
937 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
938 FN_GLOBAL_INTEGER(lp_max_wins_ttl,&Globals.max_wins_ttl)
939 FN_GLOBAL_INTEGER(lp_min_wins_ttl,&Globals.max_wins_ttl)
940 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
941 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
942 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
943 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
944 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
945 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
946 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
947 FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel)
948 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
949 FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
950 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
951 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
952 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
953 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
954 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
955 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
956 FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
957 FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
958 FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
959 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
960
961 FN_LOCAL_STRING(lp_preexec,szPreExec)
962 FN_LOCAL_STRING(lp_postexec,szPostExec)
963 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
964 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
965 FN_LOCAL_STRING(lp_servicename,szService)
966 FN_LOCAL_STRING(lp_pathname,szPath)
967 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
968 FN_LOCAL_STRING(lp_username,szUsername)
969 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
970 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
971 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
972 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
973 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
974 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
975 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
976 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
977 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
978 FN_LOCAL_STRING(lp_printername,szPrintername)
979 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
980 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
981 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
982 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
983 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
984 FN_LOCAL_STRING(lp_comment,comment)
985 FN_LOCAL_STRING(lp_force_user,force_user)
986 FN_LOCAL_STRING(lp_force_group,force_group)
987 FN_LOCAL_STRING(lp_readlist,readlist)
988 FN_LOCAL_STRING(lp_writelist,writelist)
989 FN_LOCAL_STRING(lp_volume,volume)
990 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
991 FN_LOCAL_STRING(lp_veto_files,szVetoFiles)
992 FN_LOCAL_STRING(lp_hide_files,szHideFiles)
993 FN_LOCAL_STRING(lp_veto_oplocks,szVetoOplockFiles)
994 FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
995
996 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
997 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
998 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
999 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
1000 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
1001 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
1002 FN_LOCAL_BOOL(lp_status,status)
1003 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
1004 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
1005 FN_LOCAL_BOOL(lp_readonly,bRead_only)
1006 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
1007 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
1008 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
1009 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
1010 FN_LOCAL_BOOL(lp_postscript,bPostscript)
1011 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
1012 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
1013 FN_LOCAL_BOOL(lp_locking,bLocking)
1014 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
1015 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
1016 FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
1017 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
1018 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
1019 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
1020 FN_LOCAL_BOOL(lp_symlinks,bSymlinks)
1021 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
1022 FN_LOCAL_BOOL(lp_map_system,bMap_system)
1023 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
1024 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
1025 FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
1026 FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
1027 FN_LOCAL_BOOL(lp_dos_filetime_resolution,bDosFiletimeResolution)
1028
1029 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask)
1030 FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode)
1031 FN_LOCAL_INTEGER(lp_dir_mode,iDir_mask)
1032 FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode)
1033 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
1034 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
1035 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
1036 FN_LOCAL_INTEGER(lp_printing,iPrinting)
1037
1038 FN_LOCAL_CHAR(lp_magicchar,magic_char)
1039
1040
1041
1042 /* local prototypes */
1043 static int    strwicmp( char *psz1, char *psz2 );
1044 static int    map_parameter( char *pszParmName);
1045 static BOOL   set_boolean( BOOL *pb, char *pszParmValue );
1046 static int    getservicebyname(char *pszServiceName, service *pserviceDest);
1047 static void   copy_service( service *pserviceDest, 
1048                             service *pserviceSource,
1049                             BOOL *pcopymapDest );
1050 static BOOL   service_ok(int iService);
1051 static BOOL   do_parameter(char *pszParmName, char *pszParmValue);
1052 static BOOL   do_section(char *pszSectionName);
1053 static void init_copymap(service *pservice);
1054
1055
1056 /***************************************************************************
1057 initialise a service to the defaults
1058 ***************************************************************************/
1059 static void init_service(service *pservice)
1060 {
1061   bzero((char *)pservice,sizeof(service));
1062   copy_service(pservice,&sDefault,NULL);
1063 }
1064
1065
1066 /***************************************************************************
1067 free the dynamically allocated parts of a service struct
1068 ***************************************************************************/
1069 static void free_service(service *pservice)
1070 {
1071   int i;
1072   if (!pservice)
1073      return;
1074
1075   if(pservice->szService)
1076     DEBUG(5,("free_service: Freeing service %s\n", pservice->szService));
1077
1078   string_free(&pservice->szService);
1079   if (pservice->copymap)
1080   {
1081     free(pservice->copymap);
1082     pservice->copymap = NULL;
1083   }
1084  
1085   for (i=0;parm_table[i].label;i++)
1086     if ((parm_table[i].type == P_STRING ||
1087          parm_table[i].type == P_USTRING) &&
1088         parm_table[i].class == P_LOCAL)
1089       string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
1090 }
1091
1092 /***************************************************************************
1093 add a new service to the services array initialising it with the given 
1094 service
1095 ***************************************************************************/
1096 static int add_a_service(service *pservice, char *name)
1097 {
1098   int i;
1099   service tservice;
1100   int num_to_alloc = iNumServices+1;
1101
1102   tservice = *pservice;
1103
1104   /* it might already exist */
1105   if (name) 
1106     {
1107       i = getservicebyname(name,NULL);
1108       if (i >= 0)
1109         return(i);
1110     }
1111
1112   /* find an invalid one */
1113   for (i=0;i<iNumServices;i++)
1114     if (!pSERVICE(i)->valid)
1115       break;
1116
1117   /* if not, then create one */
1118   if (i == iNumServices)
1119     {
1120       ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
1121       if (ServicePtrs)
1122         pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
1123
1124       if (!ServicePtrs || !pSERVICE(iNumServices))
1125         return(-1);
1126
1127       iNumServices++;
1128     }
1129   else
1130     free_service(pSERVICE(i));
1131
1132   pSERVICE(i)->valid = True;
1133
1134   init_service(pSERVICE(i));
1135   copy_service(pSERVICE(i),&tservice,NULL);
1136   if (name)
1137     string_set(&iSERVICE(i).szService,name);  
1138
1139   return(i);
1140 }
1141
1142 /***************************************************************************
1143 add a new home service, with the specified home directory, defaults coming 
1144 from service ifrom
1145 ***************************************************************************/
1146 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
1147 {
1148   int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
1149
1150   if (i < 0)
1151     return(False);
1152
1153   if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
1154     string_set(&iSERVICE(i).szPath,pszHomedir);
1155   if (!(*(iSERVICE(i).comment)))
1156     {
1157       pstring comment;
1158       sprintf(comment,"Home directory of %s",pszHomename);
1159       string_set(&iSERVICE(i).comment,comment);
1160     }
1161   iSERVICE(i).bAvailable = sDefault.bAvailable;
1162   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1163
1164   DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
1165
1166   return(True);
1167 }
1168
1169 /***************************************************************************
1170 add a new service, based on an old one
1171 ***************************************************************************/
1172 int lp_add_service(char *pszService, int iDefaultService)
1173 {
1174   return(add_a_service(pSERVICE(iDefaultService),pszService));
1175 }
1176
1177
1178 /***************************************************************************
1179 add the IPC service
1180 ***************************************************************************/
1181 static BOOL lp_add_ipc(void)
1182 {
1183   pstring comment;
1184   int i = add_a_service(&sDefault,"IPC$");
1185
1186   if (i < 0)
1187     return(False);
1188
1189   sprintf(comment,"IPC Service (%s)",lp_serverstring());
1190
1191   string_set(&iSERVICE(i).szPath,tmpdir());
1192   string_set(&iSERVICE(i).szUsername,"");
1193   string_set(&iSERVICE(i).comment,comment);
1194   iSERVICE(i).status = False;
1195   iSERVICE(i).iMaxConnections = 0;
1196   iSERVICE(i).bAvailable = True;
1197   iSERVICE(i).bRead_only = True;
1198   iSERVICE(i).bGuest_only = False;
1199   iSERVICE(i).bGuest_ok = True;
1200   iSERVICE(i).bPrint_ok = False;
1201   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1202
1203   DEBUG(3,("adding IPC service\n"));
1204
1205   return(True);
1206 }
1207
1208
1209 /***************************************************************************
1210 add a new printer service, with defaults coming from service iFrom
1211 ***************************************************************************/
1212 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1213 {
1214   char *comment = "From Printcap";
1215   int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1216   
1217   if (i < 0)
1218     return(False);
1219   
1220   /* note that we do NOT default the availability flag to True - */
1221   /* we take it from the default service passed. This allows all */
1222   /* dynamic printers to be disabled by disabling the [printers] */
1223   /* entry (if/when the 'available' keyword is implemented!).    */
1224   
1225   /* the printer name is set to the service name. */
1226   string_set(&iSERVICE(i).szPrintername,pszPrintername);
1227   string_set(&iSERVICE(i).comment,comment);
1228   iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1229   /* Printers cannot be read_only. */
1230   iSERVICE(i).bRead_only = False;
1231   /* No share modes on printer services. */
1232   iSERVICE(i).bShareModes = False;
1233   /* No oplocks on printer services. */
1234   iSERVICE(i).bOpLocks = False;
1235   /* Printer services must be printable. */
1236   iSERVICE(i).bPrint_ok = True;
1237   
1238   DEBUG(3,("adding printer service %s\n",pszPrintername));
1239   
1240   return(True);
1241 }
1242
1243
1244 /***************************************************************************
1245 Do a case-insensitive, whitespace-ignoring string compare.
1246 ***************************************************************************/
1247 static int strwicmp(char *psz1, char *psz2)
1248 {
1249    /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1250    /* appropriate value. */
1251    if (psz1 == psz2)
1252       return (0);
1253    else
1254       if (psz1 == NULL)
1255          return (-1);
1256       else
1257           if (psz2 == NULL)
1258               return (1);
1259
1260    /* sync the strings on first non-whitespace */
1261    while (1)
1262    {
1263       while (isspace(*psz1))
1264          psz1++;
1265       while (isspace(*psz2))
1266          psz2++;
1267       if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1268          break;
1269       psz1++;
1270       psz2++;
1271    }
1272    return (*psz1 - *psz2);
1273 }
1274
1275 /***************************************************************************
1276 Map a parameter's string representation to something we can use. 
1277 Returns False if the parameter string is not recognised, else TRUE.
1278 ***************************************************************************/
1279 static int map_parameter(char *pszParmName)
1280 {
1281    int iIndex;
1282
1283    if (*pszParmName == '-')
1284      return(-1);
1285
1286    for (iIndex = 0; parm_table[iIndex].label; iIndex++) 
1287       if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1288          return(iIndex);
1289
1290    DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1291    return(-1);
1292 }
1293
1294
1295 /***************************************************************************
1296 Set a boolean variable from the text value stored in the passed string.
1297 Returns True in success, False if the passed string does not correctly 
1298 represent a boolean.
1299 ***************************************************************************/
1300 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1301 {
1302    BOOL bRetval;
1303
1304    bRetval = True;
1305    if (strwicmp(pszParmValue, "yes") == 0 ||
1306        strwicmp(pszParmValue, "true") == 0 ||
1307        strwicmp(pszParmValue, "1") == 0)
1308       *pb = True;
1309    else
1310       if (strwicmp(pszParmValue, "no") == 0 ||
1311           strwicmp(pszParmValue, "False") == 0 ||
1312           strwicmp(pszParmValue, "0") == 0)
1313          *pb = False;
1314       else
1315       {
1316          DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1317                pszParmValue));
1318          bRetval = False;
1319       }
1320    return (bRetval);
1321 }
1322
1323 /***************************************************************************
1324 Find a service by name. Otherwise works like get_service.
1325 ***************************************************************************/
1326 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1327 {
1328    int iService;
1329
1330    for (iService = iNumServices - 1; iService >= 0; iService--)
1331       if (VALID(iService) &&
1332           strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) 
1333       {
1334          if (pserviceDest != NULL)
1335            copy_service(pserviceDest, pSERVICE(iService), NULL);
1336          break;
1337       }
1338
1339    return (iService);
1340 }
1341
1342
1343
1344 /***************************************************************************
1345 Copy a service structure to another
1346
1347 If pcopymapDest is NULL then copy all fields
1348 ***************************************************************************/
1349 static void copy_service(service *pserviceDest, 
1350                          service *pserviceSource,
1351                          BOOL *pcopymapDest)
1352 {
1353   int i;
1354   BOOL bcopyall = (pcopymapDest == NULL);
1355
1356   for (i=0;parm_table[i].label;i++)
1357     if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && 
1358         (bcopyall || pcopymapDest[i]))
1359       {
1360         void *def_ptr = parm_table[i].ptr;
1361         void *src_ptr = 
1362           ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1363         void *dest_ptr = 
1364           ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1365
1366         switch (parm_table[i].type)
1367           {
1368           case P_BOOL:
1369           case P_BOOLREV:
1370             *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1371             break;
1372
1373           case P_INTEGER:
1374           case P_ENUM:
1375           case P_OCTAL:
1376             *(int *)dest_ptr = *(int *)src_ptr;
1377             break;
1378
1379           case P_CHAR:
1380             *(char *)dest_ptr = *(char *)src_ptr;
1381             break;
1382
1383           case P_STRING:
1384             string_set(dest_ptr,*(char **)src_ptr);
1385             break;
1386
1387           case P_USTRING:
1388             string_set(dest_ptr,*(char **)src_ptr);
1389             strupper(*(char **)dest_ptr);
1390             break;
1391           default:
1392             break;
1393           }
1394       }
1395
1396   if (bcopyall)
1397     {
1398       init_copymap(pserviceDest);
1399       if (pserviceSource->copymap)
1400         memcpy((void *)pserviceDest->copymap,
1401                (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1402     }
1403 }
1404
1405 /***************************************************************************
1406 Check a service for consistency. Return False if the service is in any way
1407 incomplete or faulty, else True.
1408 ***************************************************************************/
1409 static BOOL service_ok(int iService)
1410 {
1411    BOOL bRetval;
1412
1413    bRetval = True;
1414    if (iSERVICE(iService).szService[0] == '\0')
1415    {
1416       DEBUG(0,( "The following message indicates an internal error:\n"));
1417       DEBUG(0,( "No service name in service entry.\n"));
1418       bRetval = False;
1419    }
1420
1421    /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1422    /* I can't see why you'd want a non-printable printer service...        */
1423    if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1424       if (!iSERVICE(iService).bPrint_ok)
1425       {
1426          DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1427                iSERVICE(iService).szService));
1428          iSERVICE(iService).bPrint_ok = True;
1429       }
1430
1431    if (iSERVICE(iService).szPath[0] == '\0' &&
1432        strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1433    {
1434       DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1435       string_set(&iSERVICE(iService).szPath,tmpdir());      
1436    }
1437
1438    /* If a service is flagged unavailable, log the fact at level 0. */
1439    if (!iSERVICE(iService).bAvailable) 
1440       DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1441             iSERVICE(iService).szService));
1442
1443    return (bRetval);
1444 }
1445
1446 static struct file_lists {
1447   struct file_lists *next;
1448   char *name;
1449   time_t modtime;
1450 } *file_lists = NULL;
1451
1452 /*******************************************************************
1453 keep a linked list of all config files so we know when one has changed 
1454 it's date and needs to be reloaded
1455 ********************************************************************/
1456 static void add_to_file_list(char *fname)
1457 {
1458   struct file_lists *f=file_lists;
1459
1460   while (f) {
1461     if (f->name && !strcmp(f->name,fname)) break;
1462     f = f->next;
1463   }
1464
1465   if (!f) {
1466     f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1467     if (!f) return;
1468     f->next = file_lists;
1469     f->name = strdup(fname);
1470     if (!f->name) {
1471       free(f);
1472       return;
1473     }
1474     file_lists = f;
1475   }
1476
1477   {
1478     pstring n2;
1479     pstrcpy(n2,fname);
1480     standard_sub_basic(n2);
1481     f->modtime = file_modtime(n2);
1482   }
1483
1484 }
1485
1486 /*******************************************************************
1487 check if a config file has changed date
1488 ********************************************************************/
1489 BOOL lp_file_list_changed(void)
1490 {
1491   struct file_lists *f = file_lists;
1492   DEBUG(6,("lp_file_list_changed()\n"));
1493
1494   while (f)
1495   {
1496     pstring n2;
1497     time_t mod_time;
1498
1499     pstrcpy(n2,f->name);
1500     standard_sub_basic(n2);
1501
1502     DEBUG(6,("file %s -> %s  last mod_time: %s\n",
1503              f->name, n2, ctime(&f->modtime)));
1504
1505     mod_time = file_modtime(n2);
1506
1507     if (f->modtime != mod_time) {
1508             DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time)));
1509             f->modtime = mod_time;
1510             return(True);
1511     }
1512     f = f->next;   
1513   }
1514   return(False);
1515 }
1516
1517 /***************************************************************************
1518   handle the interpretation of the coding system parameter
1519   *************************************************************************/
1520 static BOOL handle_coding_system(char *pszParmValue,char **ptr)
1521 {
1522         string_set(ptr,pszParmValue);
1523         interpret_coding_system(pszParmValue);
1524         return(True);
1525 }
1526
1527 /***************************************************************************
1528 handle the interpretation of the character set system parameter
1529 ***************************************************************************/
1530 static BOOL handle_character_set(char *pszParmValue,char **ptr)
1531 {
1532         string_set(ptr,pszParmValue);
1533         interpret_character_set(pszParmValue);
1534         return(True);
1535 }
1536
1537
1538 /***************************************************************************
1539 handle the valid chars lines
1540 ***************************************************************************/
1541 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1542
1543   string_set(ptr,pszParmValue);
1544
1545   /* A dependency here is that the parameter client code page must be
1546      set before this is called - as calling codepage_initialise()
1547      would overwrite the valid char lines.
1548    */
1549   codepage_initialise(lp_client_code_page());
1550
1551   add_char_string(pszParmValue);
1552   return(True);
1553 }
1554
1555
1556 /***************************************************************************
1557 handle the include operation
1558 ***************************************************************************/
1559 static BOOL handle_include(char *pszParmValue,char **ptr)
1560
1561   pstring fname;
1562   pstrcpy(fname,pszParmValue);
1563
1564   add_to_file_list(fname);
1565
1566   standard_sub_basic(fname);
1567
1568   string_set(ptr,fname);
1569
1570   if (file_exist(fname,NULL))
1571     return(pm_process(fname, do_section, do_parameter));      
1572
1573   DEBUG(2,("Can't find include file %s\n",fname));
1574
1575   return(False);
1576 }
1577
1578
1579 /***************************************************************************
1580 handle the interpretation of the copy parameter
1581 ***************************************************************************/
1582 static BOOL handle_copy(char *pszParmValue,char **ptr)
1583 {
1584    BOOL bRetval;
1585    int iTemp;
1586    service serviceTemp;
1587
1588    string_set(ptr,pszParmValue);
1589
1590    init_service(&serviceTemp);
1591
1592    bRetval = False;
1593    
1594    DEBUG(3,("Copying service from service %s\n",pszParmValue));
1595
1596    if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1597      {
1598        if (iTemp == iServiceIndex)
1599          {
1600            DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1601                     pszParmValue));
1602          }
1603        else
1604          {
1605            copy_service(pSERVICE(iServiceIndex), 
1606                         &serviceTemp,
1607                         iSERVICE(iServiceIndex).copymap);
1608            bRetval = True;
1609          }
1610      }
1611    else
1612      {
1613        DEBUG(0,( "Unable to copy service - source not found: %s\n",
1614                 pszParmValue));
1615        bRetval = False;
1616      }
1617
1618    free_service(&serviceTemp);
1619    return (bRetval);
1620 }
1621
1622
1623 /***************************************************************************
1624 initialise a copymap
1625 ***************************************************************************/
1626 static void init_copymap(service *pservice)
1627 {
1628   int i;
1629   if (pservice->copymap) free(pservice->copymap);
1630   pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1631   if (!pservice->copymap)
1632     DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1633
1634   for (i=0;i<NUMPARAMETERS;i++)
1635     pservice->copymap[i] = True;
1636 }
1637
1638
1639 /***************************************************************************
1640  return the local pointer to a parameter given the service number and the 
1641  pointer into the default structure
1642 ***************************************************************************/
1643 void *lp_local_ptr(int snum, void *ptr)
1644 {
1645         return (void *)(((char *)pSERVICE(snum)) + PTR_DIFF(ptr,&sDefault));
1646 }
1647
1648 /***************************************************************************
1649 Process a parameter for a particular service number. If snum < 0
1650 then assume we are in the globals
1651 ***************************************************************************/
1652 BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
1653 {
1654    int parmnum, i;
1655    void *parm_ptr=NULL; /* where we are going to store the result */
1656    void *def_ptr=NULL;
1657
1658    parmnum = map_parameter(pszParmName);
1659
1660    if (parmnum < 0)
1661      {
1662        DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1663        return(True);
1664      }
1665
1666    def_ptr = parm_table[parmnum].ptr;
1667
1668    /* we might point at a service, the default service or a global */
1669    if (snum < 0) {
1670      parm_ptr = def_ptr;
1671    } else {
1672        if (parm_table[parmnum].class == P_GLOBAL) {
1673            DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1674            return(True);
1675          }
1676        parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
1677    }
1678
1679    if (snum >= 0) {
1680            if (!iSERVICE(snum).copymap)
1681                    init_copymap(pSERVICE(snum));
1682            
1683            /* this handles the aliases - set the copymap for other entries with
1684               the same data pointer */
1685            for (i=0;parm_table[i].label;i++)
1686                    if (parm_table[i].ptr == parm_table[parmnum].ptr)
1687                            iSERVICE(snum).copymap[i] = False;
1688    }
1689
1690    /* if it is a special case then go ahead */
1691    if (parm_table[parmnum].special) {
1692            parm_table[parmnum].special(pszParmValue,parm_ptr);
1693            return(True);
1694    }
1695
1696    /* now switch on the type of variable it is */
1697    switch (parm_table[parmnum].type)
1698      {
1699      case P_BOOL:
1700        set_boolean(parm_ptr,pszParmValue);
1701        break;
1702
1703      case P_BOOLREV:
1704        set_boolean(parm_ptr,pszParmValue);
1705        *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1706        break;
1707
1708      case P_INTEGER:
1709        *(int *)parm_ptr = atoi(pszParmValue);
1710        break;
1711
1712      case P_CHAR:
1713        *(char *)parm_ptr = *pszParmValue;
1714        break;
1715
1716      case P_OCTAL:
1717        sscanf(pszParmValue,"%o",(int *)parm_ptr);
1718        break;
1719
1720      case P_STRING:
1721        string_set(parm_ptr,pszParmValue);
1722        break;
1723
1724      case P_USTRING:
1725        string_set(parm_ptr,pszParmValue);
1726        strupper(*(char **)parm_ptr);
1727        break;
1728
1729      case P_GSTRING:
1730        strcpy((char *)parm_ptr,pszParmValue);
1731        break;
1732
1733      case P_UGSTRING:
1734        strcpy((char *)parm_ptr,pszParmValue);
1735        strupper((char *)parm_ptr);
1736        break;
1737
1738      case P_ENUM:
1739              for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
1740                      if (strequal(pszParmValue, parm_table[parmnum].enum_list[i].name)) {
1741                              *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
1742                              break;
1743                      }
1744              }
1745              break;
1746      }
1747
1748    return(True);
1749 }
1750
1751 /***************************************************************************
1752 Process a parameter.
1753 ***************************************************************************/
1754 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1755 {
1756    if (!bInGlobalSection && bGlobalOnly) return(True);
1757
1758    DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1759
1760    return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, pszParmName, pszParmValue);
1761 }
1762
1763
1764 /***************************************************************************
1765 print a parameter of the specified type
1766 ***************************************************************************/
1767 static void print_parameter(struct parm_struct *p,void *ptr, FILE *f)
1768 {
1769         int i;
1770         switch (p->type) {
1771         case P_ENUM:
1772                 for (i=0;p->enum_list[i].name;i++) {
1773                         if (*(int *)ptr == p->enum_list[i].value) {
1774                                 fprintf(f,"%s",p->enum_list[i].name);
1775                                 break;
1776                         }
1777                 }
1778                 break;
1779
1780         case P_BOOL:
1781                 fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr));
1782                 break;
1783       
1784         case P_BOOLREV:
1785                 fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr));
1786                 break;
1787       
1788         case P_INTEGER:
1789                 fprintf(f,"%d",*(int *)ptr);
1790                 break;
1791       
1792         case P_CHAR:
1793                 fprintf(f,"%c",*(char *)ptr);
1794                 break;
1795       
1796         case P_OCTAL:
1797                 fprintf(f,"0%o",*(int *)ptr);
1798                 break;
1799       
1800         case P_GSTRING:
1801         case P_UGSTRING:
1802                 if ((char *)ptr)
1803                         fprintf(f,"%s",(char *)ptr);
1804                 break;
1805                 
1806         case P_STRING:
1807         case P_USTRING:
1808                 if (*(char **)ptr)
1809                         fprintf(f,"%s",*(char **)ptr);
1810                 break;
1811         }
1812 }
1813
1814
1815 /***************************************************************************
1816 check if two parameters are equal
1817 ***************************************************************************/
1818 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1819 {
1820   switch (type)
1821     {
1822     case P_BOOL:
1823     case P_BOOLREV:
1824       return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1825
1826     case P_INTEGER:
1827     case P_ENUM:
1828     case P_OCTAL:
1829       return(*((int *)ptr1) == *((int *)ptr2));
1830       
1831     case P_CHAR:
1832       return(*((char *)ptr1) == *((char *)ptr2));
1833
1834     case P_GSTRING:
1835     case P_UGSTRING:
1836       {
1837         char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1838         if (p1 && !*p1) p1 = NULL;
1839         if (p2 && !*p2) p2 = NULL;
1840         return(p1==p2 || strequal(p1,p2));
1841       }
1842     case P_STRING:
1843     case P_USTRING:
1844       {
1845         char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1846         if (p1 && !*p1) p1 = NULL;
1847         if (p2 && !*p2) p2 = NULL;
1848         return(p1==p2 || strequal(p1,p2));
1849       }
1850     }
1851   return(False);
1852 }
1853
1854 /***************************************************************************
1855 Process a new section (service). At this stage all sections are services.
1856 Later we'll have special sections that permit server parameters to be set.
1857 Returns True on success, False on failure.
1858 ***************************************************************************/
1859 static BOOL do_section(char *pszSectionName)
1860 {
1861    BOOL bRetval;
1862    BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || 
1863                     (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1864    bRetval = False;
1865
1866    /* if we were in a global section then do the local inits */
1867    if (bInGlobalSection && !isglobal)
1868      init_locals();
1869
1870    /* if we've just struck a global section, note the fact. */
1871    bInGlobalSection = isglobal;   
1872
1873    /* check for multiple global sections */
1874    if (bInGlobalSection)
1875    {
1876      DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1877      return(True);
1878    }
1879
1880    if (!bInGlobalSection && bGlobalOnly) return(True);
1881
1882    /* if we have a current service, tidy it up before moving on */
1883    bRetval = True;
1884
1885    if (iServiceIndex >= 0)
1886      bRetval = service_ok(iServiceIndex);
1887
1888    /* if all is still well, move to the next record in the services array */
1889    if (bRetval)
1890      {
1891        /* We put this here to avoid an odd message order if messages are */
1892        /* issued by the post-processing of a previous section. */
1893        DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1894
1895        if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1896          {
1897            DEBUG(0,("Failed to add a new service\n"));
1898            return(False);
1899          }
1900      }
1901
1902    return (bRetval);
1903 }
1904
1905 /***************************************************************************
1906 Display the contents of the global structure.
1907 ***************************************************************************/
1908 static void dump_globals(FILE *f)
1909 {
1910   int i;
1911   fprintf(f, "# Global parameters\n");
1912
1913   for (i=0;parm_table[i].label;i++)
1914     if (parm_table[i].class == P_GLOBAL &&
1915         parm_table[i].ptr &&
1916         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1917       {
1918         fprintf(f,"\t%s = ",parm_table[i].label);
1919         print_parameter(&parm_table[i],parm_table[i].ptr, f);
1920         fprintf(f,"\n");
1921       }
1922 }
1923
1924 /***************************************************************************
1925 Display the contents of a single services record.
1926 ***************************************************************************/
1927 static void dump_a_service(service *pService, FILE *f)
1928 {
1929   int i;
1930   if (pService == &sDefault)
1931     fprintf(f,"\n\n# Default service parameters\n");
1932   else
1933     fprintf(f,"\n[%s]\n",pService->szService);
1934
1935   for (i=0;parm_table[i].label;i++)
1936     if (parm_table[i].class == P_LOCAL &&
1937         parm_table[i].ptr && 
1938         (*parm_table[i].label != '-') &&
1939         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1940       {
1941         int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1942
1943         if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1944                                                       ((char *)pService) + pdiff,
1945                                                       ((char *)&sDefault) + pdiff))
1946           {
1947             fprintf(f,"\t%s = ",parm_table[i].label);
1948             print_parameter(&parm_table[i],
1949                             ((char *)pService) + pdiff, f);
1950             fprintf(f,"\n");
1951           }
1952       }
1953 }
1954
1955
1956 /***************************************************************************
1957 return info about the next service  in a service. snum==-1 gives the default
1958 serice and snum==-2 gives the globals
1959
1960 return 0 when out of parameters
1961 ***************************************************************************/
1962 struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters)
1963 {
1964         if (snum == -2) {
1965                 /* do the globals */
1966                 for (;parm_table[*i].label;(*i)++)
1967                         if (parm_table[*i].class == P_GLOBAL &&
1968                             parm_table[*i].ptr && 
1969                             (*parm_table[*i].label != '-') &&
1970                             ((*i) == 0 || 
1971                              (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
1972                                 return &parm_table[(*i)++];
1973                         }
1974                 return 0;
1975         } else {
1976                 service *pService = (snum==-1?&sDefault:pSERVICE(snum));
1977
1978                 for (;parm_table[*i].label;(*i)++)
1979                         if (parm_table[*i].class == P_LOCAL &&
1980                             parm_table[*i].ptr && 
1981                             (*parm_table[*i].label != '-') &&
1982                             ((*i) == 0 || 
1983                              (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
1984                                 int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault);
1985                                 
1986                                 if (snum == -1 || allparameters ||
1987                                     !equal_parameter(parm_table[*i].type,
1988                                                      ((char *)pService) + pdiff,
1989                                                      ((char *)&sDefault) + pdiff)) {
1990                                         return &parm_table[(*i)++];
1991                                 }
1992                         }
1993         }
1994
1995   return 0;
1996 }
1997
1998
1999 #if 0
2000 /***************************************************************************
2001 Display the contents of a single copy structure.
2002 ***************************************************************************/
2003 static void dump_copy_map(BOOL *pcopymap)
2004 {
2005   int i;
2006   if (!pcopymap) return;
2007
2008   printf("\n\tNon-Copied parameters:\n");
2009
2010   for (i=0;parm_table[i].label;i++)
2011     if (parm_table[i].class == P_LOCAL &&
2012         parm_table[i].ptr && !pcopymap[i] &&
2013         (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
2014       {
2015         printf("\t\t%s\n",parm_table[i].label);
2016       }
2017 }
2018 #endif
2019
2020 /***************************************************************************
2021 Return TRUE if the passed service number is within range.
2022 ***************************************************************************/
2023 BOOL lp_snum_ok(int iService)
2024 {
2025    return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
2026 }
2027
2028
2029 /***************************************************************************
2030 auto-load some homes and printer services
2031 ***************************************************************************/
2032 static void lp_add_auto_services(char *str)
2033 {
2034   char *s;
2035   char *p;
2036   int homes = lp_servicenumber(HOMES_NAME);
2037   int printers = lp_servicenumber(PRINTERS_NAME);
2038
2039   if (!str)
2040     return;
2041
2042   s = strdup(str);
2043   if (!s) return;
2044
2045   for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
2046     {
2047       char *home = get_home_dir(p);
2048
2049       if (lp_servicenumber(p) >= 0) continue;
2050
2051       if (home && homes >= 0)
2052         {
2053           lp_add_home(p,homes,home);
2054           continue;
2055         }
2056
2057       if (printers >= 0 && pcap_printername_ok(p,NULL))
2058         lp_add_printer(p,printers);
2059     }
2060   free(s);
2061 }
2062
2063 /***************************************************************************
2064 auto-load one printer
2065 ***************************************************************************/
2066 static void lp_add_one_printer(char *name,char *comment)
2067 {
2068   int printers = lp_servicenumber(PRINTERS_NAME);
2069   int i;
2070
2071   if (lp_servicenumber(name) < 0)
2072     {
2073       lp_add_printer(name,printers);
2074       if ((i=lp_servicenumber(name)) >= 0)
2075         string_set(&iSERVICE(i).comment,comment);
2076     }      
2077 }
2078
2079
2080 /***************************************************************************
2081 auto-load printer services
2082 ***************************************************************************/
2083 static void lp_add_all_printers(void)
2084 {
2085   int printers = lp_servicenumber(PRINTERS_NAME);
2086
2087   if (printers < 0) return;
2088
2089   pcap_printer_fn(lp_add_one_printer);
2090 }
2091
2092 /***************************************************************************
2093 have we loaded a services file yet?
2094 ***************************************************************************/
2095 BOOL lp_loaded(void)
2096 {
2097   return(bLoaded);
2098 }
2099
2100 /***************************************************************************
2101 unload unused services
2102 ***************************************************************************/
2103 void lp_killunused(BOOL (*snumused)(int ))
2104 {
2105   int i;
2106   for (i=0;i<iNumServices;i++)
2107     if (VALID(i) && (!snumused || !snumused(i)))
2108       {
2109         iSERVICE(i).valid = False;
2110         free_service(pSERVICE(i));
2111       }
2112 }
2113
2114 /***************************************************************************
2115 Load the services array from the services file. Return True on success, 
2116 False on failure.
2117 ***************************************************************************/
2118 BOOL lp_load(char *pszFname,BOOL global_only)
2119 {
2120   pstring n2;
2121   BOOL bRetval;
2122  
2123   add_to_file_list(pszFname);
2124
2125   bRetval = False;
2126
2127   bInGlobalSection = True;
2128   bGlobalOnly = global_only;
2129   
2130   init_globals();
2131   
2132   pstrcpy(n2,pszFname);
2133   standard_sub_basic(n2);
2134
2135   /* We get sections first, so have to start 'behind' to make up */
2136   iServiceIndex = -1;
2137   bRetval = pm_process(n2, do_section, do_parameter);
2138   
2139   /* finish up the last section */
2140   DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
2141   if (bRetval)
2142     if (iServiceIndex >= 0)
2143       bRetval = service_ok(iServiceIndex);         
2144
2145   lp_add_auto_services(lp_auto_services());
2146   if (lp_load_printers())
2147     lp_add_all_printers();
2148
2149   lp_add_ipc();
2150
2151   set_default_server_announce_type();
2152
2153   bLoaded = True;
2154
2155   return (bRetval);
2156 }
2157
2158
2159 /***************************************************************************
2160 return the max number of services
2161 ***************************************************************************/
2162 int lp_numservices(void)
2163 {
2164   return(iNumServices);
2165 }
2166
2167 /***************************************************************************
2168 Display the contents of the services array in human-readable form.
2169 ***************************************************************************/
2170 void lp_dump(FILE *f)
2171 {
2172    int iService;
2173
2174    dump_globals(f);
2175    
2176    dump_a_service(&sDefault, f);
2177
2178    for (iService = 0; iService < iNumServices; iService++)
2179    {
2180      if (VALID(iService))
2181        {
2182          if (iSERVICE(iService).szService[0] == '\0')
2183            break;
2184          dump_a_service(pSERVICE(iService), f);
2185        }
2186    }
2187 }
2188
2189
2190 /***************************************************************************
2191 Return the number of the service with the given name, or -1 if it doesn't
2192 exist. Note that this is a DIFFERENT ANIMAL from the internal function
2193 getservicebyname()! This works ONLY if all services have been loaded, and
2194 does not copy the found service.
2195 ***************************************************************************/
2196 int lp_servicenumber(char *pszServiceName)
2197 {
2198    int iService;
2199
2200    for (iService = iNumServices - 1; iService >= 0; iService--)
2201       if (VALID(iService) &&
2202           strequal(lp_servicename(iService), pszServiceName)) 
2203          break;
2204
2205    if (iService < 0)
2206      DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
2207    
2208    return (iService);
2209 }
2210
2211 /*******************************************************************
2212   a useful volume label function
2213   ******************************************************************/
2214 char *volume_label(int snum)
2215 {
2216   char *ret = lp_volume(snum);
2217   if (!*ret) return(lp_servicename(snum));
2218   return(ret);
2219 }
2220
2221 #if 0
2222 /*
2223  * nmbd only loads the global section. There seems to be no way to
2224  * determine exactly is a service is printable by only looking at the
2225  * [global] section so for now always announce as a print server. This
2226  * will need looking at in the future. Jeremy (jallison@whistle.com).
2227  */
2228 /*******************************************************************
2229  Return true if any printer services are defined.
2230   ******************************************************************/
2231 static BOOL lp_printer_services(void)
2232 {
2233   int iService;
2234
2235   for (iService = iNumServices - 1; iService >= 0; iService--)
2236       if (VALID(iService) && iSERVICE(iService).bPrint_ok)
2237           return True;
2238   return False;
2239 }
2240 #endif
2241
2242 /*******************************************************************
2243  Set the server type we will announce as via nmbd.
2244 ********************************************************************/
2245 static void set_default_server_announce_type()
2246 {
2247   default_server_announce = (SV_TYPE_WORKSTATION | SV_TYPE_SERVER |
2248                               SV_TYPE_SERVER_UNIX | SV_TYPE_PRINTQ_SERVER);
2249   if(lp_announce_as() == ANNOUNCE_AS_NT)
2250     default_server_announce |= (SV_TYPE_SERVER_NT | SV_TYPE_NT);
2251   else if(lp_announce_as() == ANNOUNCE_AS_WIN95)
2252     default_server_announce |= SV_TYPE_WIN95_PLUS;
2253   else if(lp_announce_as() == ANNOUNCE_AS_WFW)
2254     default_server_announce |= SV_TYPE_WFW;
2255   default_server_announce |= (lp_time_server() ? SV_TYPE_TIME_SOURCE : 0);
2256 /*
2257  * nmbd only loads the [global] section. There seems to be no way to
2258  * determine exactly if any service is printable by only looking at the
2259  * [global] section so for now always announce as a print server. This
2260  * will need looking at in the future. Jeremy (jallison@whistle.com).
2261  */
2262 #if 0
2263   default_server_announce |= (lp_printer_services() ? SV_TYPE_PRINTQ_SERVER : 0);
2264 #endif
2265 }
2266
2267
2268 /*******************************************************************
2269 rename a service
2270 ********************************************************************/
2271 void lp_rename_service(int snum, char *new_name)
2272 {
2273         string_set(&pSERVICE(snum)->szService, new_name);
2274 }
2275
2276 /*******************************************************************
2277 remove a service
2278 ********************************************************************/
2279 void lp_remove_service(int snum)
2280 {
2281         pSERVICE(snum)->valid = False;
2282 }
2283
2284 /*******************************************************************
2285 copy a service
2286 ********************************************************************/
2287 void lp_copy_service(int snum, char *new_name)
2288 {
2289         char *oldname = lp_servicename(snum);
2290         do_section(new_name);
2291         if (snum >= 0) {
2292                 snum = lp_servicenumber(new_name);
2293                 if (snum >= 0)
2294                         lp_do_parameter(snum, "copy", oldname);
2295         }
2296 }
2297
2298
2299 /*******************************************************************
2300  Get the default server type we will announce as via nmbd.
2301 ********************************************************************/
2302 int lp_default_server_announce(void)
2303 {
2304   return default_server_announce;
2305 }
2306
2307 /*******************************************************************
2308  Split the announce version into major and minor numbers.
2309 ********************************************************************/
2310 int lp_major_announce_version(void)
2311 {
2312   static BOOL got_major = False;
2313   static int major_version = DEFAULT_MAJOR_VERSION;
2314   char *vers;
2315   char *p;
2316
2317   if(got_major)
2318     return major_version;
2319
2320   got_major = True;
2321   if((vers = lp_announce_version()) == NULL)
2322     return major_version;
2323   
2324   if((p = strchr(vers, '.')) == 0)
2325     return major_version;
2326
2327   *p = '\0';
2328   major_version = atoi(vers);
2329   return major_version;
2330 }
2331
2332 int lp_minor_announce_version(void)
2333 {
2334   static BOOL got_minor = False;
2335   static int minor_version = DEFAULT_MINOR_VERSION;
2336   char *vers;
2337   char *p;
2338
2339   if(got_minor)
2340     return minor_version;
2341
2342   got_minor = True;
2343   if((vers = lp_announce_version()) == NULL)
2344     return minor_version;
2345   
2346   if((p = strchr(vers, '.')) == 0)              
2347     return minor_version;
2348     
2349   p++;
2350   minor_version = atoi(p);
2351   return minor_version;
2352 }  
2353