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