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