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