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