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;
134 char *szRemoteAnnounce;
135 char *szSocketAddress;
154 BOOL bPreferredMaster;
157 BOOL bEncryptPasswords;
164 BOOL bReadPrediction;
170 static global Globals;
175 * This structure describes a single service.
183 char *szGuestaccount;
184 char *szInvalidUsers;
192 char *szRootPostExec;
193 char *szPrintcommand;
196 char *szLppausecommand;
197 char *szLpresumecommand;
199 char *szPrinterDriver;
220 BOOL bShortCasePreserve;
244 BOOL bDeleteReadonly;
246 char dummy[3]; /* for alignment */
250 /* This is a default service used to prime a services structure */
251 static service sDefault =
254 NULL, /* szService */
256 NULL, /* szUsername */
257 NULL, /* szGuestAccount */
258 NULL, /* szInvalidUsers */
259 NULL, /* szValidUsers */
260 NULL, /* szAdminUsers */
262 NULL, /* szInclude */
263 NULL, /* szPreExec */
264 NULL, /* szPostExec */
265 NULL, /* szRootPreExec */
266 NULL, /* szRootPostExec */
267 NULL, /* szPrintcommand */
268 NULL, /* szLpqcommand */
269 NULL, /* szLprmcommand */
270 NULL, /* szLppausecommand */
271 NULL, /* szLpresumecommand */
272 NULL, /* szPrintername */
273 NULL, /* szPrinterDriver */
274 NULL, /* szDontdescend */
275 NULL, /* szHostsallow */
276 NULL, /* szHostsdeny */
277 NULL, /* szMagicScript */
278 NULL, /* szMagicOutput */
279 NULL, /* szMangledMap */
281 NULL, /* force user */
282 NULL, /* force group */
284 NULL, /* writelist */
286 0, /* iMinPrintSpace */
287 0755, /* iCreate_mode */
288 0, /* iMaxConnections */
289 CASE_LOWER, /* iDefaultCase */
290 False, /* bAlternatePerm */
291 False, /* revalidate */
292 False, /* case sensitive */
293 False, /* case preserve */
294 False, /* short case preserve */
295 False, /* case mangle */
297 True, /* bHideDotFiles */
298 True, /* bBrowseable */
299 True, /* bAvailable */
300 True, /* bRead_only */
301 True, /* bNo_set_dir */
302 False, /* bGuest_only */
303 False, /* bGuest_ok */
304 False, /* bPrint_ok */
305 False, /* bPostscript */
306 False, /* bMap_system */
307 False, /* bMap_hidden */
308 True, /* bMap_archive */
310 False, /* bStrictLocking */
311 True, /* bShareModes */
312 False, /* bOnlyUser */
313 True, /* bMangledNames */
314 True, /* bWidelinks */
315 False, /* bSyncAlways */
316 '~', /* magic char */
318 False, /* bDeleteReadonly */
319 False, /* bFakeOplocks */
325 /* local variables */
326 static service **ServicePtrs = NULL;
327 static int iNumServices = 0;
328 static int iServiceIndex = 0;
329 static BOOL bInGlobalSection = True;
330 static BOOL bGlobalOnly = False;
333 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
335 /* prototypes for the special type handlers */
336 static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
337 static BOOL handle_include(char *pszParmValue, char **ptr);
338 static BOOL handle_copy(char *pszParmValue, char **ptr);
339 static BOOL handle_protocol(char *pszParmValue,int *val);
340 static BOOL handle_security(char *pszParmValue,int *val);
341 static BOOL handle_case(char *pszParmValue,int *val);
342 static BOOL handle_printing(char *pszParmValue,int *val);
343 static BOOL handle_character_set(char *pszParmValue,int *val);
345 static BOOL handle_coding_system(char *pszParmValue,int *val);
357 {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
358 {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
359 {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
360 {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
361 {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
362 {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
363 {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
364 {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
365 {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
366 {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
367 {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
368 {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
369 {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
370 {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
371 {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
372 {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
373 {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
374 {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
375 {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
376 {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
377 {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
378 {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
379 {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL},
380 {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
381 {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
382 {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
383 {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
384 {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
385 {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
386 {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
387 {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
388 {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
389 {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
390 {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
391 {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
392 {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
393 {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
394 {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
395 {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
396 {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
397 {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
398 {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
399 {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
400 {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
401 {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
402 {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
403 {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
404 {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
405 {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
406 {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
407 {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL},
408 {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL},
409 {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
410 {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
411 {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
412 {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
413 {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
414 {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
415 {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
416 {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
417 {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
418 {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
419 {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
421 {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
423 {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
424 {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
425 {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
426 {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
427 {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
428 {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
429 {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
430 {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
431 {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
432 {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
434 {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
435 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
436 {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
437 {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
438 {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
439 {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
440 {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
441 {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
442 {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
443 {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
444 {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
445 {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
446 {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
447 {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
448 {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
449 {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
450 {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
451 {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
452 {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
453 {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
454 {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
455 {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
456 {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
457 {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
458 {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
459 {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
460 {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
461 {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
462 {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
463 {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
464 {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
465 {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
466 {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
467 {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
468 {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
469 {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
470 {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
471 {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
472 {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
473 {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
474 {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
475 {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
476 {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
477 {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mode, NULL},
478 {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
479 {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
480 {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
481 {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
482 {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
483 {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
484 {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
485 {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
486 {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
487 {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
488 {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
489 {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
490 {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
491 {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
492 {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
493 {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
494 {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
495 {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
496 {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
497 {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
498 {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL},
499 {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
500 {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
501 {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
502 {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
503 {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
504 {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
505 {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
506 {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL},
507 {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
508 {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
509 {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
510 {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
511 {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
512 {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
513 {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
514 {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
515 {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
517 {NULL, P_BOOL, P_NONE, NULL, NULL}
522 /***************************************************************************
523 Initialise the global parameter structure.
524 ***************************************************************************/
525 static void init_globals(void)
527 static BOOL done_init = False;
533 bzero((void *)&Globals,sizeof(Globals));
535 for (i = 0; parm_table[i].label; i++)
536 if ((parm_table[i].type == P_STRING ||
537 parm_table[i].type == P_USTRING) &&
539 string_init(parm_table[i].ptr,"");
541 string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT);
542 string_set(&sDefault.szPrinterDriver, "NULL");
548 DEBUG(3,("Initialising global parameters\n"));
550 #ifdef SMB_PASSWD_FILE
551 string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE);
553 string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
554 string_set(&Globals.szWorkGroup, WORKGROUP);
556 string_set(&Globals.szPasswdProgram, SMB_PASSWD);
558 string_set(&Globals.szPasswdProgram, "/bin/passwd");
560 string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
561 string_set(&Globals.szLockDir, LOCKDIR);
562 string_set(&Globals.szRootdir, "/");
563 string_set(&Globals.szSmbrun, SMBRUN);
564 string_set(&Globals.szSocketAddress, "0.0.0.0");
565 sprintf(s,"Samba %s",VERSION);
566 string_set(&Globals.szServerString,s);
567 Globals.bLoadPrinters = True;
568 Globals.bUseRhosts = False;
569 Globals.max_packet = 65535;
570 Globals.mangled_stack = 50;
571 Globals.max_xmit = Globals.max_packet;
573 Globals.lpqcachetime = 10;
574 Globals.pwordlevel = 0;
575 Globals.deadtime = 0;
576 Globals.max_log_size = 5000;
577 Globals.maxprotocol = PROTOCOL_NT1;
578 Globals.security = SEC_SHARE;
579 Globals.bEncryptPasswords = False;
580 Globals.printing = DEFAULT_PRINTING;
581 Globals.bReadRaw = True;
582 Globals.bWriteRaw = True;
583 Globals.bReadPrediction = False;
584 Globals.bReadbmpx = True;
585 Globals.bNullPasswords = False;
586 Globals.bStripDot = False;
588 Globals.bSyslogOnly = False;
589 Globals.os_level = 0;
590 Globals.max_ttl = 60*60*4; /* 2 hours default */
591 Globals.bPreferredMaster = True;
592 Globals.bDomainMaster = False;
593 Globals.bDomainLogons = False;
594 Globals.bBrowseList = True;
595 Globals.bWINSsupport = True;
596 Globals.bWINSproxy = False;
597 Globals.ReadSize = 16*1024;
600 coding_system = interpret_coding_system (KANJI, SJIS_CODE);
605 /***************************************************************************
606 check if a string is initialised and if not then initialise it
607 ***************************************************************************/
608 static void string_initial(char **s,char *v)
615 /***************************************************************************
616 Initialise the sDefault parameter structure.
617 ***************************************************************************/
618 static void init_locals(void)
620 /* choose defaults depending on the type of printing */
621 switch (Globals.printing)
627 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
628 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
629 string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s");
634 string_initial(&sDefault.szLpqcommand,"lpstat -o%p");
635 string_initial(&sDefault.szLprmcommand,"cancel %p-%j");
636 string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s");
638 string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold");
639 string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume");
644 string_initial(&sDefault.szLpqcommand,"lpq -P%p");
645 string_initial(&sDefault.szLprmcommand,"lprm -P%p %j");
646 string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s");
654 /******************************************************************* a
655 convenience routine to grab string parameters into a rotating buffer,
656 and run standard_sub_basic on them. The buffers can be written to by
657 callers without affecting the source string.
658 ********************************************************************/
659 char *lp_string(char *s)
661 static char *bufs[10];
662 static int buflen[10];
663 static int next = -1;
666 int len = s?strlen(s):0;
677 len = MAX(len+100,sizeof(pstring)); /* the +100 is for some
680 if (buflen[next] != len) {
682 if (bufs[next]) free(bufs[next]);
683 bufs[next] = (char *)malloc(len);
685 DEBUG(0,("out of memory in lp_string()"));
690 ret = &bufs[next][0];
698 standard_sub_basic(ret);
704 In this section all the functions that are used to access the
705 parameters from the rest of the program are defined
708 #define FN_GLOBAL_STRING(fn_name,ptr) \
709 char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));}
710 #define FN_GLOBAL_BOOL(fn_name,ptr) \
711 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
712 #define FN_GLOBAL_CHAR(fn_name,ptr) \
713 char fn_name(void) {return(*(char *)(ptr));}
714 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
715 int fn_name(void) {return(*(int *)(ptr));}
717 #define FN_LOCAL_STRING(fn_name,val) \
718 char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));}
719 #define FN_LOCAL_BOOL(fn_name,val) \
720 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
721 #define FN_LOCAL_CHAR(fn_name,val) \
722 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
723 #define FN_LOCAL_INTEGER(fn_name,val) \
724 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
726 FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile)
727 FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
728 FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
729 FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
730 FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
731 FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
732 FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
733 FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
734 FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService)
735 FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand)
736 FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree)
737 FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv)
738 FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices)
739 FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
740 FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
741 FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
742 FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
743 FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
744 FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
745 FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
746 FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
747 FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce)
748 FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
749 FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
750 FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
752 FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
753 FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
754 FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
755 FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
756 FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
757 FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
758 FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
759 FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
760 FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction)
761 FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx)
762 FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw)
763 FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw)
764 FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords)
765 FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot)
766 FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
767 FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly)
768 FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
770 FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
771 FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
772 FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
773 FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
774 FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
775 FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
776 FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
777 FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
778 FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
779 FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
780 FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
781 FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
782 FN_GLOBAL_INTEGER(lp_security,&Globals.security)
783 FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
784 FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
785 FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
786 FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
788 FN_LOCAL_STRING(lp_preexec,szPreExec)
789 FN_LOCAL_STRING(lp_postexec,szPostExec)
790 FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec)
791 FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec)
792 FN_LOCAL_STRING(lp_servicename,szService)
793 FN_LOCAL_STRING(lp_pathname,szPath)
794 FN_LOCAL_STRING(lp_dontdescend,szDontdescend)
795 FN_LOCAL_STRING(lp_username,szUsername)
796 FN_LOCAL_STRING(lp_guestaccount,szGuestaccount)
797 FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers)
798 FN_LOCAL_STRING(lp_valid_users,szValidUsers)
799 FN_LOCAL_STRING(lp_admin_users,szAdminUsers)
800 FN_LOCAL_STRING(lp_printcommand,szPrintcommand)
801 FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand)
802 FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand)
803 FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand)
804 FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand)
805 FN_LOCAL_STRING(lp_printername,szPrintername)
806 FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver)
807 FN_LOCAL_STRING(lp_hostsallow,szHostsallow)
808 FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny)
809 FN_LOCAL_STRING(lp_magicscript,szMagicScript)
810 FN_LOCAL_STRING(lp_magicoutput,szMagicOutput)
811 FN_LOCAL_STRING(lp_comment,comment)
812 FN_LOCAL_STRING(lp_force_user,force_user)
813 FN_LOCAL_STRING(lp_force_group,force_group)
814 FN_LOCAL_STRING(lp_readlist,readlist)
815 FN_LOCAL_STRING(lp_writelist,writelist)
816 FN_LOCAL_STRING(lp_volume,volume)
817 FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
819 FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
820 FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
821 FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive)
822 FN_LOCAL_BOOL(lp_preservecase,bCasePreserve)
823 FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve)
824 FN_LOCAL_BOOL(lp_casemangle,bCaseMangle)
825 FN_LOCAL_BOOL(lp_status,status)
826 FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles)
827 FN_LOCAL_BOOL(lp_browseable,bBrowseable)
828 FN_LOCAL_BOOL(lp_readonly,bRead_only)
829 FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir)
830 FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok)
831 FN_LOCAL_BOOL(lp_guest_only,bGuest_only)
832 FN_LOCAL_BOOL(lp_print_ok,bPrint_ok)
833 FN_LOCAL_BOOL(lp_postscript,bPostscript)
834 FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden)
835 FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
836 FN_LOCAL_BOOL(lp_locking,bLocking)
837 FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
838 FN_LOCAL_BOOL(lp_share_modes,bShareModes)
839 FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
840 FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
841 FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
842 FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
843 FN_LOCAL_BOOL(lp_map_system,bMap_system)
844 FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
845 FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
847 FN_LOCAL_INTEGER(lp_create_mode,iCreate_mode)
848 FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
849 FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
850 FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
852 FN_LOCAL_CHAR(lp_magicchar,magic_char)
856 /* local prototypes */
857 static int strwicmp( char *psz1, char *psz2 );
858 static int map_parameter( char *pszParmName);
859 static BOOL set_boolean( BOOL *pb, char *pszParmValue );
860 static int getservicebyname(char *pszServiceName, service *pserviceDest);
861 static void copy_service( service *pserviceDest,
862 service *pserviceSource,
863 BOOL *pcopymapDest );
864 static BOOL service_ok(int iService);
865 static BOOL do_parameter(char *pszParmName, char *pszParmValue);
866 static BOOL do_section(char *pszSectionName);
867 static void dump_globals(void);
868 static void dump_a_service(service *pService);
869 static void init_copymap(service *pservice);
872 /***************************************************************************
873 initialise a service to the defaults
874 ***************************************************************************/
875 static void init_service(service *pservice)
877 bzero((char *)pservice,sizeof(service));
878 copy_service(pservice,&sDefault,NULL);
882 /***************************************************************************
883 free the dynamically allocated parts of a service struct
884 ***************************************************************************/
885 static void free_service(service *pservice)
891 for (i=0;parm_table[i].label;i++)
892 if ((parm_table[i].type == P_STRING ||
893 parm_table[i].type == P_STRING) &&
894 parm_table[i].class == P_LOCAL)
895 string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault)));
898 /***************************************************************************
899 add a new service to the services array initialising it with the given
901 ***************************************************************************/
902 static int add_a_service(service *pservice, char *name)
906 int num_to_alloc = iNumServices+1;
908 tservice = *pservice;
910 /* it might already exist */
913 i = getservicebyname(name,NULL);
918 /* find an invalid one */
919 for (i=0;i<iNumServices;i++)
920 if (!pSERVICE(i)->valid)
923 /* if not, then create one */
924 if (i == iNumServices)
926 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
928 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
930 if (!ServicePtrs || !pSERVICE(iNumServices))
936 free_service(pSERVICE(i));
938 pSERVICE(i)->valid = True;
940 init_service(pSERVICE(i));
941 copy_service(pSERVICE(i),&tservice,NULL);
943 string_set(&iSERVICE(i).szService,name);
948 /***************************************************************************
949 add a new home service, with the specified home directory, defaults coming
951 ***************************************************************************/
952 BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir)
954 int i = add_a_service(pSERVICE(iDefaultService),pszHomename);
959 if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1)))
960 string_set(&iSERVICE(i).szPath,pszHomedir);
961 if (!(*(iSERVICE(i).comment)))
964 sprintf(comment,"Home directory of %s",pszHomename);
965 string_set(&iSERVICE(i).comment,comment);
967 iSERVICE(i).bAvailable = sDefault.bAvailable;
968 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
970 DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
975 /***************************************************************************
976 add a new service, based on an old one
977 ***************************************************************************/
978 int lp_add_service(char *pszService, int iDefaultService)
980 return(add_a_service(pSERVICE(iDefaultService),pszService));
984 /***************************************************************************
986 ***************************************************************************/
987 static BOOL lp_add_ipc(void)
990 int i = add_a_service(&sDefault,"IPC$");
995 sprintf(comment,"IPC Service (%s)",lp_serverstring());
997 string_set(&iSERVICE(i).szPath,tmpdir());
998 string_set(&iSERVICE(i).szUsername,"");
999 string_set(&iSERVICE(i).comment,comment);
1000 iSERVICE(i).status = False;
1001 iSERVICE(i).iMaxConnections = 0;
1002 iSERVICE(i).bAvailable = True;
1003 iSERVICE(i).bRead_only = True;
1004 iSERVICE(i).bGuest_only = False;
1005 iSERVICE(i).bGuest_ok = True;
1006 iSERVICE(i).bPrint_ok = False;
1007 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1009 DEBUG(3,("adding IPC service\n"));
1015 /***************************************************************************
1016 add a new printer service, with defaults coming from service iFrom
1017 ***************************************************************************/
1018 BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
1020 char *comment = "From Printcap";
1021 int i = add_a_service(pSERVICE(iDefaultService),pszPrintername);
1026 /* note that we do NOT default the availability flag to True - */
1027 /* we take it from the default service passed. This allows all */
1028 /* dynamic printers to be disabled by disabling the [printers] */
1029 /* entry (if/when the 'available' keyword is implemented!). */
1031 /* the printer name is set to the service name. */
1032 string_set(&iSERVICE(i).szPrintername,pszPrintername);
1033 string_set(&iSERVICE(i).comment,comment);
1034 iSERVICE(i).bBrowseable = sDefault.bBrowseable;
1036 DEBUG(3,("adding printer service %s\n",pszPrintername));
1042 /***************************************************************************
1043 Do a case-insensitive, whitespace-ignoring string compare.
1044 ***************************************************************************/
1045 static int strwicmp(char *psz1, char *psz2)
1047 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
1048 /* appropriate value. */
1058 /* sync the strings on first non-whitespace */
1061 while (isspace(*psz1))
1063 while (isspace(*psz2))
1065 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
1070 return (*psz1 - *psz2);
1073 /***************************************************************************
1074 Map a parameter's string representation to something we can use.
1075 Returns False if the parameter string is not recognised, else TRUE.
1076 ***************************************************************************/
1077 static int map_parameter(char *pszParmName)
1081 if (*pszParmName == '-')
1084 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
1085 if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
1088 DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName));
1093 /***************************************************************************
1094 Set a boolean variable from the text value stored in the passed string.
1095 Returns True in success, False if the passed string does not correctly
1096 represent a boolean.
1097 ***************************************************************************/
1098 static BOOL set_boolean(BOOL *pb, char *pszParmValue)
1103 if (strwicmp(pszParmValue, "yes") == 0 ||
1104 strwicmp(pszParmValue, "true") == 0 ||
1105 strwicmp(pszParmValue, "1") == 0)
1108 if (strwicmp(pszParmValue, "no") == 0 ||
1109 strwicmp(pszParmValue, "False") == 0 ||
1110 strwicmp(pszParmValue, "0") == 0)
1114 DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n",
1121 /***************************************************************************
1122 Find a service by name. Otherwise works like get_service.
1123 ***************************************************************************/
1124 static int getservicebyname(char *pszServiceName, service *pserviceDest)
1128 for (iService = iNumServices - 1; iService >= 0; iService--)
1129 if (VALID(iService) &&
1130 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1132 if (pserviceDest != NULL)
1133 copy_service(pserviceDest, pSERVICE(iService), NULL);
1142 /***************************************************************************
1143 Copy a service structure to another
1145 If pcopymapDest is NULL then copy all fields
1146 ***************************************************************************/
1147 static void copy_service(service *pserviceDest,
1148 service *pserviceSource,
1152 BOOL bcopyall = (pcopymapDest == NULL);
1154 for (i=0;parm_table[i].label;i++)
1155 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL &&
1156 (bcopyall || pcopymapDest[i]))
1158 void *def_ptr = parm_table[i].ptr;
1160 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
1162 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
1164 switch (parm_table[i].type)
1168 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
1173 *(int *)dest_ptr = *(int *)src_ptr;
1177 *(char *)dest_ptr = *(char *)src_ptr;
1181 string_set(dest_ptr,*(char **)src_ptr);
1185 string_set(dest_ptr,*(char **)src_ptr);
1186 strupper(*(char **)dest_ptr);
1195 init_copymap(pserviceDest);
1196 if (pserviceSource->copymap)
1197 memcpy((void *)pserviceDest->copymap,
1198 (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS);
1202 /***************************************************************************
1203 Check a service for consistency. Return False if the service is in any way
1204 incomplete or faulty, else True.
1205 ***************************************************************************/
1206 static BOOL service_ok(int iService)
1211 if (iSERVICE(iService).szService[0] == '\0')
1213 DEBUG(0,( "The following message indicates an internal error:\n"));
1214 DEBUG(0,( "No service name in service entry.\n"));
1218 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
1219 /* I can't see why you'd want a non-printable printer service... */
1220 if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0)
1221 if (!iSERVICE(iService).bPrint_ok)
1223 DEBUG(0,( "WARNING: [%s] service MUST be printable!\n",
1224 iSERVICE(iService).szService));
1225 iSERVICE(iService).bPrint_ok = True;
1228 if (iSERVICE(iService).szPath[0] == '\0' &&
1229 strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0)
1231 DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir()));
1232 string_set(&iSERVICE(iService).szPath,tmpdir());
1235 /* If a service is flagged unavailable, log the fact at level 0. */
1236 if (!iSERVICE(iService).bAvailable)
1237 DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n",
1238 iSERVICE(iService).szService));
1243 static struct file_lists {
1244 struct file_lists *next;
1247 } *file_lists = NULL;
1249 /*******************************************************************
1250 keep a linked list of all config files so we know when one has changed
1251 it's date and needs to be reloaded
1252 ********************************************************************/
1253 static void add_to_file_list(char *fname)
1255 struct file_lists *f=file_lists;
1258 if (f->name && !strcmp(f->name,fname)) break;
1263 f = (struct file_lists *)malloc(sizeof(file_lists[0]));
1265 f->next = file_lists;
1266 f->name = strdup(fname);
1277 standard_sub_basic(n2);
1278 f->modtime = file_modtime(n2);
1283 /*******************************************************************
1284 check if a config file has changed date
1285 ********************************************************************/
1286 BOOL lp_file_list_changed(void)
1288 struct file_lists *f = file_lists;
1292 standard_sub_basic(n2);
1293 if (f->modtime != file_modtime(n2)) return(True);
1300 /***************************************************************************
1301 handle the interpretation of the coding system parameter
1302 *************************************************************************/
1303 static BOOL handle_coding_system(char *pszParmValue,int *val)
1305 *val = interpret_coding_system(pszParmValue,*val);
1310 /***************************************************************************
1311 handle the interpretation of the character set system parameter
1312 ***************************************************************************/
1313 static BOOL handle_character_set(char *pszParmValue,int *val)
1315 string_set(&Globals.szCharacterSet,pszParmValue);
1316 *val = interpret_character_set(pszParmValue,*val);
1321 /***************************************************************************
1322 handle the interpretation of the protocol parameter
1323 ***************************************************************************/
1324 static BOOL handle_protocol(char *pszParmValue,int *val)
1326 *val = interpret_protocol(pszParmValue,*val);
1330 /***************************************************************************
1331 handle the interpretation of the security parameter
1332 ***************************************************************************/
1333 static BOOL handle_security(char *pszParmValue,int *val)
1335 *val = interpret_security(pszParmValue,*val);
1339 /***************************************************************************
1340 handle the interpretation of the default case
1341 ***************************************************************************/
1342 static BOOL handle_case(char *pszParmValue,int *val)
1344 if (strequal(pszParmValue,"LOWER"))
1346 else if (strequal(pszParmValue,"UPPER"))
1351 /***************************************************************************
1352 handle the interpretation of the printing system
1353 ***************************************************************************/
1354 static BOOL handle_printing(char *pszParmValue,int *val)
1356 if (strequal(pszParmValue,"sysv"))
1358 else if (strequal(pszParmValue,"aix"))
1360 else if (strequal(pszParmValue,"hpux"))
1362 else if (strequal(pszParmValue,"bsd"))
1364 else if (strequal(pszParmValue,"qnx"))
1366 else if (strequal(pszParmValue,"plp"))
1368 else if (strequal(pszParmValue,"lprng"))
1373 /***************************************************************************
1374 handle the valid chars lines
1375 ***************************************************************************/
1376 static BOOL handle_valid_chars(char *pszParmValue,char **ptr)
1378 string_set(ptr,pszParmValue);
1380 add_char_string(pszParmValue);
1385 /***************************************************************************
1386 handle the include operation
1387 ***************************************************************************/
1388 static BOOL handle_include(char *pszParmValue,char **ptr)
1391 strcpy(fname,pszParmValue);
1393 add_to_file_list(fname);
1395 standard_sub_basic(fname);
1397 string_set(ptr,fname);
1399 if (file_exist(fname,NULL))
1400 return(pm_process(fname, do_section, do_parameter));
1402 DEBUG(2,("Can't find include file %s\n",fname));
1408 /***************************************************************************
1409 handle the interpretation of the copy parameter
1410 ***************************************************************************/
1411 static BOOL handle_copy(char *pszParmValue,char **ptr)
1415 service serviceTemp;
1417 string_set(ptr,pszParmValue);
1419 init_service(&serviceTemp);
1423 DEBUG(3,("Copying service from service %s\n",pszParmValue));
1425 if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0)
1427 if (iTemp == iServiceIndex)
1429 DEBUG(0,("Can't copy service %s - unable to copy self!\n",
1434 copy_service(pSERVICE(iServiceIndex),
1436 iSERVICE(iServiceIndex).copymap);
1442 DEBUG(0,( "Unable to copy service - source not found: %s\n",
1447 free_service(&serviceTemp);
1452 /***************************************************************************
1453 initialise a copymap
1454 ***************************************************************************/
1455 static void init_copymap(service *pservice)
1458 if (pservice->copymap) free(pservice->copymap);
1459 pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS);
1460 if (!pservice->copymap)
1461 DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS));
1463 for (i=0;i<NUMPARAMETERS;i++)
1464 pservice->copymap[i] = True;
1468 /***************************************************************************
1469 Process a parameter.
1470 ***************************************************************************/
1471 static BOOL do_parameter(char *pszParmName, char *pszParmValue)
1474 void *parm_ptr=NULL; /* where we are going to store the result */
1477 if (!bInGlobalSection && bGlobalOnly) return(True);
1479 DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
1481 parmnum = map_parameter(pszParmName);
1485 DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName));
1489 def_ptr = parm_table[parmnum].ptr;
1491 /* we might point at a service, the default service or a global */
1492 if (bInGlobalSection)
1496 if (parm_table[parmnum].class == P_GLOBAL)
1498 DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
1501 parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
1504 if (!bInGlobalSection)
1507 if (!iSERVICE(iServiceIndex).copymap)
1508 init_copymap(pSERVICE(iServiceIndex));
1510 /* this handles the aliases - set the copymap for other entries with
1511 the same data pointer */
1512 for (i=0;parm_table[i].label;i++)
1513 if (parm_table[i].ptr == parm_table[parmnum].ptr)
1514 iSERVICE(iServiceIndex).copymap[i] = False;
1517 /* if it is a special case then go ahead */
1518 if (parm_table[parmnum].special)
1520 parm_table[parmnum].special(pszParmValue,parm_ptr);
1524 /* now switch on the type of variable it is */
1525 switch (parm_table[parmnum].type)
1528 set_boolean(parm_ptr,pszParmValue);
1532 set_boolean(parm_ptr,pszParmValue);
1533 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
1537 *(int *)parm_ptr = atoi(pszParmValue);
1541 *(char *)parm_ptr = *pszParmValue;
1545 sscanf(pszParmValue,"%o",(int *)parm_ptr);
1549 string_set(parm_ptr,pszParmValue);
1553 string_set(parm_ptr,pszParmValue);
1554 strupper(*(char **)parm_ptr);
1558 strcpy((char *)parm_ptr,pszParmValue);
1562 strcpy((char *)parm_ptr,pszParmValue);
1563 strupper((char *)parm_ptr);
1570 /***************************************************************************
1571 print a parameter of the specified type
1572 ***************************************************************************/
1573 static void print_parameter(parm_type type,void *ptr)
1578 printf("%s",BOOLSTR(*(BOOL *)ptr));
1582 printf("%s",BOOLSTR(! *(BOOL *)ptr));
1586 printf("%d",*(int *)ptr);
1590 printf("%c",*(char *)ptr);
1594 printf("0%o",*(int *)ptr);
1600 printf("%s",(char *)ptr);
1606 printf("%s",*(char **)ptr);
1612 /***************************************************************************
1613 check if two parameters are equal
1614 ***************************************************************************/
1615 static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
1621 return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
1625 return(*((int *)ptr1) == *((int *)ptr2));
1628 return(*((char *)ptr1) == *((char *)ptr2));
1633 char *p1 = (char *)ptr1, *p2 = (char *)ptr2;
1634 if (p1 && !*p1) p1 = NULL;
1635 if (p2 && !*p2) p2 = NULL;
1636 return(p1==p2 || strequal(p1,p2));
1641 char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
1642 if (p1 && !*p1) p1 = NULL;
1643 if (p2 && !*p2) p2 = NULL;
1644 return(p1==p2 || strequal(p1,p2));
1650 /***************************************************************************
1651 Process a new section (service). At this stage all sections are services.
1652 Later we'll have special sections that permit server parameters to be set.
1653 Returns True on success, False on failure.
1654 ***************************************************************************/
1655 static BOOL do_section(char *pszSectionName)
1658 BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
1659 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
1662 /* if we were in a global section then do the local inits */
1663 if (bInGlobalSection && !isglobal)
1666 /* if we've just struck a global section, note the fact. */
1667 bInGlobalSection = isglobal;
1669 /* check for multiple global sections */
1670 if (bInGlobalSection)
1672 DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName));
1676 if (!bInGlobalSection && bGlobalOnly) return(True);
1678 /* if we have a current service, tidy it up before moving on */
1681 if (iServiceIndex >= 0)
1682 bRetval = service_ok(iServiceIndex);
1684 /* if all is still well, move to the next record in the services array */
1687 /* We put this here to avoid an odd message order if messages are */
1688 /* issued by the post-processing of a previous section. */
1689 DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName));
1691 if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0)
1693 DEBUG(0,("Failed to add a new service\n"));
1701 /***************************************************************************
1702 Display the contents of the global structure.
1703 ***************************************************************************/
1704 static void dump_globals(void)
1707 printf("Global parameters:\n");
1709 for (i=0;parm_table[i].label;i++)
1710 if (parm_table[i].class == P_GLOBAL &&
1711 parm_table[i].ptr &&
1712 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1714 printf("\t%s: ",parm_table[i].label);
1715 print_parameter(parm_table[i].type,parm_table[i].ptr);
1720 /***************************************************************************
1721 Display the contents of a single services record.
1722 ***************************************************************************/
1723 static void dump_a_service(service *pService)
1726 if (pService == &sDefault)
1727 printf("\nDefault service parameters:\n");
1729 printf("\nService parameters [%s]:\n",pService->szService);
1731 for (i=0;parm_table[i].label;i++)
1732 if (parm_table[i].class == P_LOCAL &&
1733 parm_table[i].ptr &&
1734 (*parm_table[i].label != '-') &&
1735 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1737 int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault);
1739 if (pService == &sDefault || !equal_parameter(parm_table[i].type,
1740 ((char *)pService) + pdiff,
1741 ((char *)&sDefault) + pdiff))
1743 printf("\t%s: ",parm_table[i].label);
1744 print_parameter(parm_table[i].type,
1745 ((char *)pService) + pdiff);
1752 /***************************************************************************
1753 Display the contents of a single copy structure.
1754 ***************************************************************************/
1755 static void dump_copy_map(BOOL *pcopymap)
1758 if (!pcopymap) return;
1760 printf("\n\tNon-Copied parameters:\n");
1762 for (i=0;parm_table[i].label;i++)
1763 if (parm_table[i].class == P_LOCAL &&
1764 parm_table[i].ptr && !pcopymap[i] &&
1765 (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
1767 printf("\t\t%s\n",parm_table[i].label);
1772 /***************************************************************************
1773 Return TRUE if the passed service number is within range.
1774 ***************************************************************************/
1775 BOOL lp_snum_ok(int iService)
1777 return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable);
1781 /***************************************************************************
1782 auto-load some homes and printer services
1783 ***************************************************************************/
1784 static void lp_add_auto_services(char *str)
1788 int homes = lp_servicenumber(HOMES_NAME);
1789 int printers = lp_servicenumber(PRINTERS_NAME);
1797 for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
1799 char *home = get_home_dir(p);
1801 if (lp_servicenumber(p) >= 0) continue;
1803 if (home && homes >= 0)
1805 lp_add_home(p,homes,home);
1809 if (printers >= 0 && pcap_printername_ok(p,NULL))
1810 lp_add_printer(p,printers);
1815 /***************************************************************************
1816 auto-load one printer
1817 ***************************************************************************/
1818 static void lp_add_one_printer(char *name,char *comment)
1820 int printers = lp_servicenumber(PRINTERS_NAME);
1823 if (lp_servicenumber(name) < 0)
1825 lp_add_printer(name,printers);
1826 if ((i=lp_servicenumber(name)) >= 0)
1827 string_set(&iSERVICE(i).comment,comment);
1832 /***************************************************************************
1833 auto-load printer services
1834 ***************************************************************************/
1835 static void lp_add_all_printers(void)
1837 int printers = lp_servicenumber(PRINTERS_NAME);
1839 if (printers < 0) return;
1841 pcap_printer_fn(lp_add_one_printer);
1844 /***************************************************************************
1845 have we loaded a services file yet?
1846 ***************************************************************************/
1847 BOOL lp_loaded(void)
1852 /***************************************************************************
1853 unload unused services
1854 ***************************************************************************/
1855 void lp_killunused(BOOL (*snumused)(int ))
1858 for (i=0;i<iNumServices;i++)
1859 if (VALID(i) && !snumused(i))
1861 iSERVICE(i).valid = False;
1862 free_service(pSERVICE(i));
1866 /***************************************************************************
1867 Load the services array from the services file. Return True on success,
1869 ***************************************************************************/
1870 BOOL lp_load(char *pszFname,BOOL global_only)
1875 add_to_file_list(pszFname);
1879 bInGlobalSection = True;
1880 bGlobalOnly = global_only;
1884 strcpy(n2,pszFname);
1885 standard_sub_basic(n2);
1887 /* We get sections first, so have to start 'behind' to make up */
1889 bRetval = pm_process(n2, do_section, do_parameter);
1891 /* finish up the last section */
1892 DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval)));
1894 if (iServiceIndex >= 0)
1895 bRetval = service_ok(iServiceIndex);
1897 lp_add_auto_services(lp_auto_services());
1898 if (lp_load_printers())
1899 lp_add_all_printers();
1909 /***************************************************************************
1910 return the max number of services
1911 ***************************************************************************/
1912 int lp_numservices(void)
1914 return(iNumServices);
1917 /***************************************************************************
1918 Display the contents of the services array in human-readable form.
1919 ***************************************************************************/
1926 dump_a_service(&sDefault);
1928 for (iService = 0; iService < iNumServices; iService++)
1930 if (VALID(iService))
1932 if (iSERVICE(iService).szService[0] == '\0')
1934 dump_a_service(pSERVICE(iService));
1939 /***************************************************************************
1940 Return the number of the service with the given name, or -1 if it doesn't
1941 exist. Note that this is a DIFFERENT ANIMAL from the internal function
1942 getservicebyname()! This works ONLY if all services have been loaded, and
1943 does not copy the found service.
1944 ***************************************************************************/
1945 int lp_servicenumber(char *pszServiceName)
1949 for (iService = iNumServices - 1; iService >= 0; iService--)
1950 if (VALID(iService) &&
1951 strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
1955 DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName));
1960 /*******************************************************************
1961 a useful volume label function
1962 ******************************************************************/
1963 char *volume_label(int snum)
1965 char *ret = lp_volume(snum);
1966 if (!*ret) return(lp_servicename(snum));