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