2 Unix SMB/Netbios implementation.
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.
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.
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
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
54 extern int DEBUGLEVEL;
55 extern pstring user_socket_options;
56 extern pstring myname;
59 #define GLOBAL_NAME "global"
64 #define PRINTCAP_NAME "/etc/qconfig"
66 #define PRINTCAP_NAME "/etc/printcap"
71 #define PRINTERS_NAME "printers"
75 #define HOMES_NAME "homes"
78 /* some helpful bits */
79 #define pSERVICE(i) ServicePtrs[i]
80 #define iSERVICE(i) (*pSERVICE(i))
81 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid)
82 #define VALID(i) iSERVICE(i).valid
84 /* these are the types of parameter we have */
87 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
88 P_STRING,P_USTRING,P_GSTRING,P_UGSTRING
93 P_LOCAL,P_GLOBAL,P_NONE
97 extern BOOL use_getwd_cache;
99 extern int extra_time_offset;
101 extern int coding_system;
105 * This structure describes global (ie., server-wide) parameters.
109 char *szPrintcapname;
112 char *szDefaultService;
116 char *szServerString;
117 char *szAutoServices;
118 char *szPasswdProgram;
122 char *szSMBPasswdFile;
123 char *szPasswordServer;
124 char *szSocketOptions;
127 char *szDomainController;
129 char *szCharacterSet;
135 char *szRemoteAnnounce;
136 char *szSocketAddress;
155 BOOL bPreferredMaster;
158 BOOL bEncryptPasswords;
165 BOOL bReadPrediction;
171 static global Globals;
176 * This structure describes a single service.
184 char *szGuestaccount;
185 char *szInvalidUsers;
193 char *szRootPostExec;
194 char *szPrintcommand;
197 char *szLppausecommand;
198 char *szLpresumecommand;
200 char *szPrinterDriver;
221 BOOL bShortCasePreserve;
245 BOOL bDeleteReadonly;
247 char dummy[3]; /* for alignment */
251 /* This is a default service used to prime a services structure */
252 static service sDefault =
255 NULL, /* szService */
257 NULL, /* szUsername */
258 NULL, /* szGuestAccount */
259 NULL, /* szInvalidUsers */
260 NULL, /* szValidUsers */
261 NULL, /* szAdminUsers */
263 NULL, /* szInclude */
264 NULL, /* szPreExec */
265 NULL, /* szPostExec */
266 NULL, /* szRootPreExec */
267 NULL, /* szRootPostExec */
268 NULL, /* szPrintcommand */
269 NULL, /* szLpqcommand */
270 NULL, /* szLprmcommand */
271 NULL, /* szLppausecommand */
272 NULL, /* szLpresumecommand */
273 NULL, /* szPrintername */
274 NULL, /* szPrinterDriver */
275 NULL, /* szDontdescend */
276 NULL, /* szHostsallow */
277 NULL, /* szHostsdeny */
278 NULL, /* szMagicScript */
279 NULL, /* szMagicOutput */
280 NULL, /* szMangledMap */
282 NULL, /* force user */
283 NULL, /* force group */
285 NULL, /* writelist */
287 0, /* iMinPrintSpace */
288 0755, /* iCreate_mode */
289 0, /* iMaxConnections */
290 CASE_LOWER, /* iDefaultCase */
291 False, /* bAlternatePerm */
292 False, /* revalidate */
293 False, /* case sensitive */
294 False, /* case preserve */
295 False, /* short case preserve */
296 False, /* case mangle */
298 True, /* bHideDotFiles */
299 True, /* bBrowseable */
300 True, /* bAvailable */
301 True, /* bRead_only */
302 True, /* bNo_set_dir */
303 False, /* bGuest_only */
304 False, /* bGuest_ok */
305 False, /* bPrint_ok */
306 False, /* bPostscript */
307 False, /* bMap_system */
308 False, /* bMap_hidden */
309 True, /* bMap_archive */
311 False, /* bStrictLocking */
312 True, /* bShareModes */
313 False, /* bOnlyUser */
314 True, /* bMangledNames */
315 True, /* bWidelinks */
316 False, /* bSyncAlways */
317 '~', /* magic char */
319 False, /* bDeleteReadonly */
320 False, /* bFakeOplocks */
326 /* local variables */
327 static service **ServicePtrs = NULL;
328 static int iNumServices = 0;
329 static int iServiceIndex = 0;
330 static BOOL bInGlobalSection = True;
331 static BOOL bGlobalOnly = False;
334 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
336 /* prototypes for the special type handlers */
337 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
338 static BOOL handle_include(char *pszParmValue, char **ptr);
339 static BOOL handle_copy(char *pszParmValue, char **ptr);
340 static BOOL handle_protocol(char *pszParmValue,int *val);
341 static BOOL handle_security(char *pszParmValue,int *val);
342 static BOOL handle_case(char *pszParmValue,int *val);
343 static BOOL handle_printing(char *pszParmValue,int *val);
344 static BOOL handle_character_set(char *pszParmValue,int *val);
346 static BOOL handle_coding_system(char *pszParmValue,int *val);
358 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
359 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
360 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
361 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
362 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
363 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
364 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
365 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
366 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
367 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
368 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
369 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
370 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
371 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
372 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
373 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
374 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
375 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
376 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
377 {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
378 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
379 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
380 {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL},
381 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
382 {"veto files", P_STRING, P_GLOBAL, &Globals.szVetoFiles, NULL},
383 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
384 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
385 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
386 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
387 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
388 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
389 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
390 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
391 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
392 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
393 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
394 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
395 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
396 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
397 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
398 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
399 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
400 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
401 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
402 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
403 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
404 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
405 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
406 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
407 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
408 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
409 {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL},
410 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL},
411 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
412 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
413 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
414 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
415 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
416 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
417 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
418 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
419 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
420 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
421 {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
423 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
425 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
426 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
427 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
428 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
429 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
430 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
431 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
432 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
433 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
434 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
436 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
437 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
438 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
439 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
440 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
441 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
442 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
443 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
444 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
445 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
446 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
447 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
448 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
449 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
450 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
451 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
452 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
453 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
454 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
455 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
456 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
457 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
458 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
459 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
460 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
461 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
462 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
463 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
464 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
465 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
466 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
467 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
468 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
469 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
470 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
471 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
472 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
473 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
474 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
475 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
476 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
477 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
478 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
479 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
480 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
481 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
482 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
483 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
484 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
485 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
486 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
487 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
488 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
489 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
490 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
491 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
492 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
493 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
494 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
495 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
496 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
497 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
498 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
499 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
500 {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL},
501 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
502 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
503 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
504 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
505 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
506 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
507 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
508 {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL},
509 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
510 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
511 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
512 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
513 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
514 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
515 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
516 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
517 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
519 {NULL, P_BOOL, P_NONE, NULL, NULL}
524 /***************************************************************************
525 Initialise the global parameter structure.
526 ***************************************************************************/
527 static void init_globals(void)
529 static BOOL done_init = False;
535 bzero((void *)&Globals,sizeof(Globals));
537 for (i = 0; parm_table[i].label; i++)
538 if ((parm_table[i].type == P_STRING ||
539 parm_table[i].type == P_USTRING) &&
541 string_init(parm_table[i].ptr,"");
543 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
544 string_set(&sDefault.szPrinterDriver, "NULL");
550 DEBUG(3,("Initialising global parameters\n"));
552 #ifdef SMB_PASSWD_FILE
553 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
555 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
556 string_set(&Globals.szWorkGroup, WORKGROUP);
558 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
560 string_set(&Globals.szPasswdProgram, "/bin/passwd");
562 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
563 string_set(&Globals.szLockDir, LOCKDIR);
564 string_set(&Globals.szRootdir, "/");
565 string_set(&Globals.szSmbrun, SMBRUN);
566 string_set(&Globals.szSocketAddress, "0.0.0.0");
567 sprintf(s,"Samba %s",VERSION);
568 string_set(&Globals.szServerString,s);
569 Globals.bLoadPrinters = True;
570 Globals.bUseRhosts = False;
571 Globals.max_packet = 65535;
572 Globals.mangled_stack = 50;
573 Globals.max_xmit = Globals.max_packet;
575 Globals.lpqcachetime = 10;
576 Globals.pwordlevel = 0;
577 Globals.deadtime = 0;
578 Globals.max_log_size = 5000;
579 Globals.maxprotocol = PROTOCOL_NT1;
580 Globals.security = SEC_SHARE;
581 Globals.bEncryptPasswords = False;
582 Globals.printing = DEFAULT_PRINTING;
583 Globals.bReadRaw = True;
584 Globals.bWriteRaw = True;
585 Globals.bReadPrediction = False;
586 Globals.bReadbmpx = True;
587 Globals.bNullPasswords = False;
588 Globals.bStripDot = False;
590 Globals.bSyslogOnly = False;
591 Globals.os_level = 0;
592 Globals.max_ttl = 60*60*4; /* 2 hours default */
593 Globals.bPreferredMaster = True;
594 Globals.bDomainMaster = False;
595 Globals.bDomainLogons = False;
596 Globals.bBrowseList = True;
597 Globals.bWINSsupport = True;
598 Globals.bWINSproxy = False;
599 Globals.ReadSize = 16*1024;
602 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
607 /***************************************************************************
608 check if a string is initialised and if not then initialise it
609 ***************************************************************************/
610 static void string_initial(char **s,char *v)
617 /***************************************************************************
618 Initialise the sDefault parameter structure.
619 ***************************************************************************/
620 static void init_locals(void)
622 /* choose defaults depending on the type of printing */
623 switch (Globals.printing)
629 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
630 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
631 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
636 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
637 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
638 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
640 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
641 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
646 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
647 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
648 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
656 /******************************************************************* a
657 convenience routine to grab string parameters into a rotating buffer,
658 and run standard_sub_basic on them. The buffers can be written to by
659 callers without affecting the source string.
660 ********************************************************************/
661 char *lp_string(char *s)
663 static char *bufs[10];
664 static int buflen[10];
665 static int next = -1;
668 int len = s?strlen(s):0;
679 len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
682 if (buflen[next] != len) {
684 if (bufs[next]) free(bufs[next]);
685 bufs[next] = (char *)malloc(len);
687 DEBUG(0,("out of memory in lp_string()"));
692 ret = &bufs[next][0];
700 standard_sub_basic(ret);
706 In this section all the functions that are used to access the
707 parameters from the rest of the program are defined
710 #define FN_GLOBAL_STRING(fn_name,ptr) \
711 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
712 #define FN_GLOBAL_BOOL(fn_name,ptr) \
713 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
714 #define FN_GLOBAL_CHAR(fn_name,ptr) \
715 char fn_name(void) {return(*(char *)(ptr));}
716 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
717 int fn_name(void) {return(*(int *)(ptr));}
719 #define FN_LOCAL_STRING(fn_name,val) \
720 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
721 #define FN_LOCAL_BOOL(fn_name,val) \
722 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
723 #define FN_LOCAL_CHAR(fn_name,val) \
724 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
725 #define FN_LOCAL_INTEGER(fn_name,val) \
726 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
728 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
729 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
730 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
731 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
732 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
733 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
734 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
735 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
736 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
737 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
738 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
739 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
740 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
741 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
742 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
743 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
744 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
745 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
746 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
747 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
748 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
749 FN_GLOBAL_STRING(lp_veto_files,&Globals.szVetoFiles)
750 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce)
751 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
752 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
753 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
755 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
756 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
757 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
758 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
759 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
760 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
761 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
762 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
763 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
764 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
765 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
766 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
767 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
768 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
769 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
770 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
771 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
773 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
774 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
775 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
776 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
777 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
778 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
779 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
780 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
781 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
782 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
783 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
784 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
785 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
786 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
787 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
788 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
789 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
791 FN_LOCAL_STRING(lp_preexec,szPreExec)
792 FN_LOCAL_STRING(lp_postexec,szPostExec)
793 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
794 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
795 FN_LOCAL_STRING(lp_servicename,szService)
796 FN_LOCAL_STRING(lp_pathname,szPath)
797 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
798 FN_LOCAL_STRING(lp_username,szUsername)
799 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
800 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
801 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
802 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
803 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
804 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
805 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
806 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
807 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
808 FN_LOCAL_STRING(lp_printername,szPrintername)
809 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
810 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
811 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
812 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
813 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
814 FN_LOCAL_STRING(lp_comment,comment)
815 FN_LOCAL_STRING(lp_force_user,force_user)
816 FN_LOCAL_STRING(lp_force_group,force_group)
817 FN_LOCAL_STRING(lp_readlist,readlist)
818 FN_LOCAL_STRING(lp_writelist,writelist)
819 FN_LOCAL_STRING(lp_volume,volume)
820 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
822 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
823 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
824 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
825 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
826 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
827 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
828 FN_LOCAL_BOOL(lp_status,status)
829 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
830 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
831 FN_LOCAL_BOOL(lp_readonly,bRead_only)
832 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
833 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
834 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
835 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
836 FN_LOCAL_BOOL(lp_postscript,bPostscript)
837 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
838 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
839 FN_LOCAL_BOOL(lp_locking,bLocking)
840 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
841 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
842 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
843 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
844 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
845 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
846 FN_LOCAL_BOOL(lp_map_system,bMap_system)
847 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
848 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
850 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
851 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
852 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
853 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
855 FN_LOCAL_CHAR(lp_magicchar,magic_char)
859 /* local prototypes */
860 static int strwicmp( char *psz1, char *psz2 );
861 static int map_parameter( char *pszParmName);
862 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
863 static int getservicebyname(char *pszServiceName, service *pserviceDest);
864 static void copy_service( service *pserviceDest,
865 service *pserviceSource,
866 BOOL *pcopymapDest );
867 static BOOL service_ok(int iService);
868 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
869 static BOOL do_section(char *pszSectionName);
870 static void dump_globals(void);
871 static void dump_a_service(service *pService);
872 static void init_copymap(service *pservice);
875 /***************************************************************************
876 initialise a service to the defaults
877 ***************************************************************************/
878 static void init_service(service *pservice)
880 bzero((char *)pservice,sizeof(service));
881 copy_service(pservice,&sDefault,NULL);
885 /***************************************************************************
886 free the dynamically allocated parts of a service struct
887 ***************************************************************************/
888 static void free_service(service *pservice)
894 for (i=0;parm_table[i].label;i++)
895 if ((parm_table[i].type == P_STRING ||
896 parm_table[i].type == P_STRING) &&
897 parm_table[i].class == P_LOCAL)
898 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
901 /***************************************************************************
902 add a new service to the services array initialising it with the given
904 ***************************************************************************/
905 static int add_a_service(service *pservice, char *name)
909 int num_to_alloc = iNumServices+1;
911 tservice = *pservice;
913 /* it might already exist */
916 i = getservicebyname(name,NULL);
921 /* find an invalid one */
922 for (i=0;i<iNumServices;i++)
923 if (!pSERVICE(i)->valid)
926 /* if not, then create one */
927 if (i == iNumServices)
929 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
931 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
933 if (!ServicePtrs || !pSERVICE(iNumServices))
939 free_service(pSERVICE(i));
941 pSERVICE(i)->valid = True;
943 init_service(pSERVICE(i));
944 copy_service(pSERVICE(i),&tservice,NULL);
946 string_set(&iSERVICE(i).szService,name);
951 /***************************************************************************
952 add a new home service, with the specified home directory, defaults coming
954 ***************************************************************************/
955 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
957 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
962 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
963 string_set(&iSERVICE(i).szPath,pszHomedir);
964 if (!(*(iSERVICE(i).comment)))
967 sprintf(comment,"Home directory of %s",pszHomename);
968 string_set(&iSERVICE(i).comment,comment);
970 iSERVICE(i).bAvailable = sDefault.bAvailable;
971 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
973 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
978 /***************************************************************************
979 add a new service, based on an old one
980 ***************************************************************************/
981 int lp_add_service(char *pszService, int iDefaultService)
983 return(add_a_service(pSERVICE(iDefaultService),pszService));
987 /***************************************************************************
989 ***************************************************************************/
990 static BOOL lp_add_ipc(void)
993 int i = add_a_service(&sDefault,"IPC$");
998 sprintf(comment,"IPC Service (%s)",lp_serverstring());
1000 string_set(&iSERVICE(i).szPath,tmpdir());
1001 string_set(&iSERVICE(i).szUsername,"");
1002 string_set(&iSERVICE(i).comment,comment);
1003 iSERVICE(i).status = False;
1004 iSERVICE(i).iMaxConnections = 0;
1005 iSERVICE(i).bAvailable = True;
1006 iSERVICE(i).bRead_only = True;
1007 iSERVICE(i).bGuest_only = False;
1008 iSERVICE(i).bGuest_ok = True;
1009 iSERVICE(i).bPrint_ok = False;
1010 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1012 DEBUG(3,("adding IPC service\n"));
1018 /***************************************************************************
1019 add a new printer service, with defaults coming from service iFrom
1020 ***************************************************************************/
1021 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1023 char *comment = "From Printcap";
1024 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1029 /* note that we do NOT default the availability flag to True - */
1030 /* we take it from the default service passed. This allows all */
1031 /* dynamic printers to be disabled by disabling the [printers] */
1032 /* entry (if/when the 'available' keyword is implemented!). */
1034 /* the printer name is set to the service name. */
1035 string_set(&iSERVICE(i).szPrintername,pszPrintername);
1036 string_set(&iSERVICE(i).comment,comment);
1037 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1039 DEBUG(3,("adding printer service %s\n",pszPrintername));
1045 /***************************************************************************
1046 Do a case-insensitive, whitespace-ignoring string compare.
1047 ***************************************************************************/
1048 static int strwicmp(char *psz1, char *psz2)
1050 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1051 /* appropriate value. */
1061 /* sync the strings on first non-whitespace */
1064 while (isspace(*psz1))
1066 while (isspace(*psz2))
1068 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1073 return (*psz1 - *psz2);
1076 /***************************************************************************
1077 Map a parameter's string representation to something we can use.
1078 Returns False if the parameter string is not recognised, else TRUE.
1079 ***************************************************************************/
1080 static int map_parameter(char *pszParmName)
1084 if (*pszParmName == '-')
1087 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1088 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1091 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1096 /***************************************************************************
1097 Set a boolean variable from the text value stored in the passed string.
1098 Returns True in success, False if the passed string does not correctly
1099 represent a boolean.
1100 ***************************************************************************/
1101 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1106 if (strwicmp(pszParmValue, "yes") == 0 ||
1107 strwicmp(pszParmValue, "true") == 0 ||
1108 strwicmp(pszParmValue, "1") == 0)
1111 if (strwicmp(pszParmValue, "no") == 0 ||
1112 strwicmp(pszParmValue, "False") == 0 ||
1113 strwicmp(pszParmValue, "0") == 0)
1117 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1124 /***************************************************************************
1125 Find a service by name. Otherwise works like get_service.
1126 ***************************************************************************/
1127 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1131 for (iService = iNumServices - 1; iService >= 0; iService--)
1132 if (VALID(iService) &&
1133 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1135 if (pserviceDest != NULL)
1136 copy_service(pserviceDest, pSERVICE(iService), NULL);
1145 /***************************************************************************
1146 Copy a service structure to another
1148 If pcopymapDest is NULL then copy all fields
1149 ***************************************************************************/
1150 static void copy_service(service *pserviceDest,
1151 service *pserviceSource,
1155 BOOL bcopyall = (pcopymapDest == NULL);
1157 for (i=0;parm_table[i].label;i++)
1158 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1159 (bcopyall || pcopymapDest[i]))
1161 void *def_ptr = parm_table[i].ptr;
1163 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1165 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1167 switch (parm_table[i].type)
1171 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1176 *(int *)dest_ptr = *(int *)src_ptr;
1180 *(char *)dest_ptr = *(char *)src_ptr;
1184 string_set(dest_ptr,*(char **)src_ptr);
1188 string_set(dest_ptr,*(char **)src_ptr);
1189 strupper(*(char **)dest_ptr);
1198 init_copymap(pserviceDest);
1199 if (pserviceSource->copymap)
1200 memcpy((void *)pserviceDest->copymap,
1201 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1205 /***************************************************************************
1206 Check a service for consistency. Return False if the service is in any way
1207 incomplete or faulty, else True.
1208 ***************************************************************************/
1209 static BOOL service_ok(int iService)
1214 if (iSERVICE(iService).szService[0] == '\0')
1216 DEBUG(0,( "The following message indicates an internal error:\n"));
1217 DEBUG(0,( "No service name in service entry.\n"));
1221 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1222 /* I can't see why you'd want a non-printable printer service... */
1223 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1224 if (!iSERVICE(iService).bPrint_ok)
1226 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1227 iSERVICE(iService).szService));
1228 iSERVICE(iService).bPrint_ok = True;
1231 if (iSERVICE(iService).szPath[0] == '\0' &&
1232 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1234 DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1235 string_set(&iSERVICE(iService).szPath,tmpdir());
1238 /* If a service is flagged unavailable, log the fact at level 0. */
1239 if (!iSERVICE(iService).bAvailable)
1240 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1241 iSERVICE(iService).szService));
1246 static struct file_lists {
1247 struct file_lists *next;
1250 } *file_lists = NULL;
1252 /*******************************************************************
1253 keep a linked list of all config files so we know when one has changed
1254 it's date and needs to be reloaded
1255 ********************************************************************/
1256 static void add_to_file_list(char *fname)
1258 struct file_lists *f=file_lists;
1261 if (f->name && !strcmp(f->name,fname)) break;
1266 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1268 f->next = file_lists;
1269 f->name = strdup(fname);
1280 standard_sub_basic(n2);
1281 f->modtime = file_modtime(n2);
1286 /*******************************************************************
1287 check if a config file has changed date
1288 ********************************************************************/
1289 BOOL lp_file_list_changed(void)
1291 struct file_lists *f = file_lists;
1295 standard_sub_basic(n2);
1296 if (f->modtime != file_modtime(n2)) return(True);
1303 /***************************************************************************
1304 handle the interpretation of the coding system parameter
1305 *************************************************************************/
1306 static BOOL handle_coding_system(char *pszParmValue,int *val)
1308 *val = interpret_coding_system(pszParmValue,*val);
1313 /***************************************************************************
1314 handle the interpretation of the character set system parameter
1315 ***************************************************************************/
1316 static BOOL handle_character_set(char *pszParmValue,int *val)
1318 string_set(&Globals.szCharacterSet,pszParmValue);
1319 *val = interpret_character_set(pszParmValue,*val);
1324 /***************************************************************************
1325 handle the interpretation of the protocol parameter
1326 ***************************************************************************/
1327 static BOOL handle_protocol(char *pszParmValue,int *val)
1329 *val = interpret_protocol(pszParmValue,*val);
1333 /***************************************************************************
1334 handle the interpretation of the security parameter
1335 ***************************************************************************/
1336 static BOOL handle_security(char *pszParmValue,int *val)
1338 *val = interpret_security(pszParmValue,*val);
1342 /***************************************************************************
1343 handle the interpretation of the default case
1344 ***************************************************************************/
1345 static BOOL handle_case(char *pszParmValue,int *val)
1347 if (strequal(pszParmValue,"LOWER"))
1349 else if (strequal(pszParmValue,"UPPER"))
1354 /***************************************************************************
1355 handle the interpretation of the printing system
1356 ***************************************************************************/
1357 static BOOL handle_printing(char *pszParmValue,int *val)
1359 if (strequal(pszParmValue,"sysv"))
1361 else if (strequal(pszParmValue,"aix"))
1363 else if (strequal(pszParmValue,"hpux"))
1365 else if (strequal(pszParmValue,"bsd"))
1367 else if (strequal(pszParmValue,"qnx"))
1369 else if (strequal(pszParmValue,"plp"))
1371 else if (strequal(pszParmValue,"lprng"))
1376 /***************************************************************************
1377 handle the valid chars lines
1378 ***************************************************************************/
1379 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1381 string_set(ptr,pszParmValue);
1383 add_char_string(pszParmValue);
1388 /***************************************************************************
1389 handle the include operation
1390 ***************************************************************************/
1391 static BOOL handle_include(char *pszParmValue,char **ptr)
1394 strcpy(fname,pszParmValue);
1396 add_to_file_list(fname);
1398 standard_sub_basic(fname);
1400 string_set(ptr,fname);
1402 if (file_exist(fname,NULL))
1403 return(pm_process(fname, do_section, do_parameter));
1405 DEBUG(2,("Can't find include file %s\n",fname));
1411 /***************************************************************************
1412 handle the interpretation of the copy parameter
1413 ***************************************************************************/
1414 static BOOL handle_copy(char *pszParmValue,char **ptr)
1418 service serviceTemp;
1420 string_set(ptr,pszParmValue);
1422 init_service(&serviceTemp);
1426 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1428 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1430 if (iTemp == iServiceIndex)
1432 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1437 copy_service(pSERVICE(iServiceIndex),
1439 iSERVICE(iServiceIndex).copymap);
1445 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1450 free_service(&serviceTemp);
1455 /***************************************************************************
1456 initialise a copymap
1457 ***************************************************************************/
1458 static void init_copymap(service *pservice)
1461 if (pservice->copymap) free(pservice->copymap);
1462 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1463 if (!pservice->copymap)
1464 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1466 for (i=0;i<NUMPARAMETERS;i++)
1467 pservice->copymap[i] = True;
1471 /***************************************************************************
1472 Process a parameter.
1473 ***************************************************************************/
1474 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1477 void *parm_ptr=NULL; /* where we are going to store the result */
1480 if (!bInGlobalSection && bGlobalOnly) return(True);
1482 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1484 parmnum = map_parameter(pszParmName);
1488 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1492 def_ptr = parm_table[parmnum].ptr;
1494 /* we might point at a service, the default service or a global */
1495 if (bInGlobalSection)
1499 if (parm_table[parmnum].class == P_GLOBAL)
1501 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1504 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1507 if (!bInGlobalSection)
1510 if (!iSERVICE(iServiceIndex).copymap)
1511 init_copymap(pSERVICE(iServiceIndex));
1513 /* this handles the aliases - set the copymap for other entries with
1514 the same data pointer */
1515 for (i=0;parm_table[i].label;i++)
1516 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1517 iSERVICE(iServiceIndex).copymap[i] = False;
1520 /* if it is a special case then go ahead */
1521 if (parm_table[parmnum].special)
1523 parm_table[parmnum].special(pszParmValue,parm_ptr);
1527 /* now switch on the type of variable it is */
1528 switch (parm_table[parmnum].type)
1531 set_boolean(parm_ptr,pszParmValue);
1535 set_boolean(parm_ptr,pszParmValue);
1536 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1540 *(int *)parm_ptr = atoi(pszParmValue);
1544 *(char *)parm_ptr = *pszParmValue;
1548 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1552 string_set(parm_ptr,pszParmValue);
1556 string_set(parm_ptr,pszParmValue);
1557 strupper(*(char **)parm_ptr);
1561 strcpy((char *)parm_ptr,pszParmValue);
1565 strcpy((char *)parm_ptr,pszParmValue);
1566 strupper((char *)parm_ptr);
1573 /***************************************************************************
1574 print a parameter of the specified type
1575 ***************************************************************************/
1576 static void print_parameter(parm_type type,void *ptr)
1581 printf("%s",BOOLSTR(*(BOOL *)ptr));
1585 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1589 printf("%d",*(int *)ptr);
1593 printf("%c",*(char *)ptr);
1597 printf("0%o",*(int *)ptr);
1603 printf("%s",(char *)ptr);
1609 printf("%s",*(char **)ptr);
1615 /***************************************************************************
1616 check if two parameters are equal
1617 ***************************************************************************/
1618 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1624 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1628 return(*((int *)ptr1) == *((int *)ptr2));
1631 return(*((char *)ptr1) == *((char *)ptr2));
1636 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1637 if (p1 && !*p1) p1 = NULL;
1638 if (p2 && !*p2) p2 = NULL;
1639 return(p1==p2 || strequal(p1,p2));
1644 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1645 if (p1 && !*p1) p1 = NULL;
1646 if (p2 && !*p2) p2 = NULL;
1647 return(p1==p2 || strequal(p1,p2));
1653 /***************************************************************************
1654 Process a new section (service). At this stage all sections are services.
1655 Later we'll have special sections that permit server parameters to be set.
1656 Returns True on success, False on failure.
1657 ***************************************************************************/
1658 static BOOL do_section(char *pszSectionName)
1661 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1662 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1665 /* if we were in a global section then do the local inits */
1666 if (bInGlobalSection && !isglobal)
1669 /* if we've just struck a global section, note the fact. */
1670 bInGlobalSection = isglobal;
1672 /* check for multiple global sections */
1673 if (bInGlobalSection)
1675 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1679 if (!bInGlobalSection && bGlobalOnly) return(True);
1681 /* if we have a current service, tidy it up before moving on */
1684 if (iServiceIndex >= 0)
1685 bRetval = service_ok(iServiceIndex);
1687 /* if all is still well, move to the next record in the services array */
1690 /* We put this here to avoid an odd message order if messages are */
1691 /* issued by the post-processing of a previous section. */
1692 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1694 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1696 DEBUG(0,("Failed to add a new service\n"));
1704 /***************************************************************************
1705 Display the contents of the global structure.
1706 ***************************************************************************/
1707 static void dump_globals(void)
1710 printf("Global parameters:\n");
1712 for (i=0;parm_table[i].label;i++)
1713 if (parm_table[i].class == P_GLOBAL &&
1714 parm_table[i].ptr &&
1715 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1717 printf("\t%s: ",parm_table[i].label);
1718 print_parameter(parm_table[i].type,parm_table[i].ptr);
1723 /***************************************************************************
1724 Display the contents of a single services record.
1725 ***************************************************************************/
1726 static void dump_a_service(service *pService)
1729 if (pService == &sDefault)
1730 printf("\nDefault service parameters:\n");
1732 printf("\nService parameters [%s]:\n",pService->szService);
1734 for (i=0;parm_table[i].label;i++)
1735 if (parm_table[i].class == P_LOCAL &&
1736 parm_table[i].ptr &&
1737 (*parm_table[i].label != '-') &&
1738 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1740 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1742 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1743 ((char *)pService) + pdiff,
1744 ((char *)&sDefault) + pdiff))
1746 printf("\t%s: ",parm_table[i].label);
1747 print_parameter(parm_table[i].type,
1748 ((char *)pService) + pdiff);
1755 /***************************************************************************
1756 Display the contents of a single copy structure.
1757 ***************************************************************************/
1758 static void dump_copy_map(BOOL *pcopymap)
1761 if (!pcopymap) return;
1763 printf("\n\tNon-Copied parameters:\n");
1765 for (i=0;parm_table[i].label;i++)
1766 if (parm_table[i].class == P_LOCAL &&
1767 parm_table[i].ptr && !pcopymap[i] &&
1768 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1770 printf("\t\t%s\n",parm_table[i].label);
1775 /***************************************************************************
1776 Return TRUE if the passed service number is within range.
1777 ***************************************************************************/
1778 BOOL lp_snum_ok(int iService)
1780 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1784 /***************************************************************************
1785 auto-load some homes and printer services
1786 ***************************************************************************/
1787 static void lp_add_auto_services(char *str)
1791 int homes = lp_servicenumber(HOMES_NAME);
1792 int printers = lp_servicenumber(PRINTERS_NAME);
1800 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1802 char *home = get_home_dir(p);
1804 if (lp_servicenumber(p) >= 0) continue;
1806 if (home && homes >= 0)
1808 lp_add_home(p,homes,home);
1812 if (printers >= 0 && pcap_printername_ok(p,NULL))
1813 lp_add_printer(p,printers);
1818 /***************************************************************************
1819 auto-load one printer
1820 ***************************************************************************/
1821 static void lp_add_one_printer(char *name,char *comment)
1823 int printers = lp_servicenumber(PRINTERS_NAME);
1826 if (lp_servicenumber(name) < 0)
1828 lp_add_printer(name,printers);
1829 if ((i=lp_servicenumber(name)) >= 0)
1830 string_set(&iSERVICE(i).comment,comment);
1835 /***************************************************************************
1836 auto-load printer services
1837 ***************************************************************************/
1838 static void lp_add_all_printers(void)
1840 int printers = lp_servicenumber(PRINTERS_NAME);
1842 if (printers < 0) return;
1844 pcap_printer_fn(lp_add_one_printer);
1847 /***************************************************************************
1848 have we loaded a services file yet?
1849 ***************************************************************************/
1850 BOOL lp_loaded(void)
1855 /***************************************************************************
1856 unload unused services
1857 ***************************************************************************/
1858 void lp_killunused(BOOL (*snumused)(int ))
1861 for (i=0;i<iNumServices;i++)
1862 if (VALID(i) && !snumused(i))
1864 iSERVICE(i).valid = False;
1865 free_service(pSERVICE(i));
1869 /***************************************************************************
1870 Load the services array from the services file. Return True on success,
1872 ***************************************************************************/
1873 BOOL lp_load(char *pszFname,BOOL global_only)
1878 add_to_file_list(pszFname);
1882 bInGlobalSection = True;
1883 bGlobalOnly = global_only;
1887 strcpy(n2,pszFname);
1888 standard_sub_basic(n2);
1890 /* We get sections first, so have to start 'behind' to make up */
1892 bRetval = pm_process(n2, do_section, do_parameter);
1894 /* finish up the last section */
1895 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1897 if (iServiceIndex >= 0)
1898 bRetval = service_ok(iServiceIndex);
1900 lp_add_auto_services(lp_auto_services());
1901 if (lp_load_printers())
1902 lp_add_all_printers();
1912 /***************************************************************************
1913 return the max number of services
1914 ***************************************************************************/
1915 int lp_numservices(void)
1917 return(iNumServices);
1920 /***************************************************************************
1921 Display the contents of the services array in human-readable form.
1922 ***************************************************************************/
1929 dump_a_service(&sDefault);
1931 for (iService = 0; iService < iNumServices; iService++)
1933 if (VALID(iService))
1935 if (iSERVICE(iService).szService[0] == '\0')
1937 dump_a_service(pSERVICE(iService));
1942 /***************************************************************************
1943 Return the number of the service with the given name, or -1 if it doesn't
1944 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1945 getservicebyname()! This works ONLY if all services have been loaded, and
1946 does not copy the found service.
1947 ***************************************************************************/
1948 int lp_servicenumber(char *pszServiceName)
1952 for (iService = iNumServices - 1; iService >= 0; iService--)
1953 if (VALID(iService) &&
1954 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1958 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1963 /*******************************************************************
1964 a useful volume label function
1965 ******************************************************************/
1966 char *volume_label(int snum)
1968 char *ret = lp_volume(snum);
1969 if (!*ret) return(lp_servicename(snum));