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