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