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