2 Get information about a system from the HDB configuration files.
4 Copyright (C) 1992, 1993, 1995 Ian Lance Taylor
6 This file is part of the Taylor UUCP uuconf library.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License
10 as published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 The author of the program may be contacted at ian@airs.com or
23 c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
29 const char _uuconf_hsinfo_rcsid[] = "$FreeBSD$";
35 static int ihadd_machine_perm P((struct sglobal *qglobal,
36 struct uuconf_system *qsys,
37 struct shpermissions *qperm));
38 static int ihadd_logname_perm P((struct sglobal *qglobal,
39 struct uuconf_system *qsys,
40 struct shpermissions *qperm));
42 /* Get the information for a particular system from the HDB
43 configuration files. This does not make sure that all the default
47 _uuconf_ihdb_system_internal (qglobal, zsystem, qsys)
48 struct sglobal *qglobal;
50 struct uuconf_system *qsys;
53 struct shpermissions *qperm;
62 boolean ffound_machine, ffound_login;
63 struct shpermissions *qother_machine;
64 struct uuconf_system *qalt;
66 if (! qglobal->qprocess->fhdb_read_permissions)
68 iret = _uuconf_ihread_permissions (qglobal);
69 if (iret != UUCONF_SUCCESS)
73 /* First look through the Permissions information to see if this is
74 an alias for some system. I assume that an alias applies to the
75 first name in the corresponding MACHINE entry. */
77 for (qperm = qglobal->qprocess->qhdb_permissions;
81 if (qperm->pzalias == NULL
82 || qperm->pzmachine == NULL
83 || qperm->pzalias == (char **) &_uuconf_unset
84 || qperm->pzmachine == (char **) &_uuconf_unset)
87 for (pz = qperm->pzalias; *pz != NULL; pz++)
89 if (strcmp (*pz, zsystem) == 0)
91 zsystem = qperm->pzmachine[0];
108 iret = UUCONF_SUCCESS;
110 for (pz = qglobal->qprocess->pzhdb_systems; *pz != NULL; pz++)
115 qglobal->ilineno = 0;
117 e = fopen (*pz, "r");
120 if (FNO_SUCH_FILE ())
122 qglobal->ierrno = errno;
123 iret = UUCONF_FOPEN_FAILED | UUCONF_ERROR_ERRNO;
127 while ((cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
129 int ctoks, ctimes, i;
130 struct uuconf_system *qset;
137 if (zline[cchars] == '\n')
138 zline[cchars] = '\0';
139 if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
142 ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
145 qglobal->ierrno = errno;
146 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
150 /* If this isn't the system we're looking for, keep reading
153 || strcmp (zsystem, pzsplit[0]) != 0)
156 /* If this is the first time we've found the system, we want
157 to set *qsys directly. Otherwise, we allocate a new
161 pblock = uuconf_malloc_block ();
164 qglobal->ierrno = errno;
165 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
168 _uuconf_uclear_system (qsys);
169 qsys->uuconf_palloc = pblock;
174 struct uuconf_system **pq;
176 qset = ((struct uuconf_system *)
177 uuconf_malloc (pblock, sizeof (struct uuconf_system)));
180 qglobal->ierrno = errno;
181 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
184 _uuconf_uclear_system (qset);
185 for (pq = &qsys->uuconf_qalternate;
187 pq = &(*pq)->uuconf_qalternate)
192 /* Add this line to the memory block we are building for the
194 if (uuconf_add_block (pblock, zline) != 0)
196 qglobal->ierrno = errno;
197 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
204 /* The format of a line in Systems is
205 system time device speed phone chat
207 airs Any ACU 9600 5551212 ogin: foo pass: bar
210 /* Get the system name. */
212 qset->uuconf_zname = pzsplit[0];
213 qset->uuconf_fcall = TRUE;
214 qset->uuconf_fcalled = FALSE;
219 /* A time string is "time/grade,time/grade;retry". A
220 missing grade is taken as BGRADE_LOW. */
221 zretry = strchr (pzsplit[1], ';');
227 cretry = (int) strtol (zretry + 1, (char **) NULL, 10);
230 ctimes = _uuconf_istrsplit (pzsplit[1], ',', &pzcomma, &ccomma);
233 qglobal->ierrno = errno;
234 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
238 for (i = 0; i < ctimes; i++)
244 zslash = strchr (z, '/');
246 bgrade = UUCONF_GRADE_LOW;
251 if (! UUCONF_GRADE_LEGAL (bgrade))
252 bgrade = UUCONF_GRADE_LOW;
255 iret = _uuconf_itime_parse (qglobal, z, (long) bgrade,
256 cretry, _uuconf_itime_grade_cmp,
257 &qset->uuconf_qtimegrade,
260 /* We treat a syntax error in the time field as
261 equivalent to ``never'', on the assumption that that
263 if (iret == UUCONF_SYNTAX_ERROR)
264 iret = UUCONF_SUCCESS;
266 if (iret != UUCONF_SUCCESS)
269 /* Treat any time/grade setting as both a timegrade and
271 if (bgrade != UUCONF_GRADE_LOW)
272 qset->uuconf_qcalltimegrade = qset->uuconf_qtimegrade;
275 if (iret != UUCONF_SUCCESS)
281 /* Pick up the device name. It can be followed by a comma
282 and a list of protocols. */
283 qset->uuconf_zport = pzsplit[2];
284 z = strchr (pzsplit[2], ',');
287 qset->uuconf_zprotocols = z + 1;
294 /* The speed entry can be a numeric speed, or a range of
295 speeds, or "Any", or "-". If it starts with a letter,
296 the initial nonnumeric prefix is a modem class, which
297 gets appended to the port name. */
299 if (strcasecmp (z, "Any") != 0
300 && strcmp (z, "-") != 0)
304 while (*z != '\0' && ! isdigit (BUCHAR (*z)))
307 qset->uuconf_ibaud = strtol (z, &zend, 10);
309 qset->uuconf_ihighbaud = strtol (zend + 1, (char **) NULL,
314 size_t cport, cclass;
316 cport = strlen (pzsplit[2]);
317 cclass = z - pzsplit[3];
318 qset->uuconf_zport = uuconf_malloc (pblock,
320 if (qset->uuconf_zport == NULL)
322 qglobal->ierrno = errno;
323 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
326 memcpy ((pointer) qset->uuconf_zport, (pointer) pzsplit[2],
328 memcpy ((pointer) (qset->uuconf_zport + cport),
329 (pointer) pzsplit[3], cclass);
330 qset->uuconf_zport[cport + cclass] = '\0';
337 /* Get the phone number. */
338 qset->uuconf_zphone = pzsplit[4];
343 /* Get the chat script. We just hand this off to the chat
344 script processor, so that it will parse subsend and
345 subexpect strings correctly. */
346 pzsplit[4] = (char *) "chat";
347 iret = _uuconf_ichat_cmd (qglobal, ctoks - 4, pzsplit + 4,
348 &qset->uuconf_schat, pblock);
349 iret &=~ UUCONF_CMDTABRET_KEEP;
350 if (iret != UUCONF_SUCCESS)
356 if (iret != UUCONF_SUCCESS)
361 free ((pointer) zline);
363 free ((pointer) pzsplit);
365 free ((pointer) pzcomma);
367 if (iret != UUCONF_SUCCESS)
369 qglobal->zfilename = *pz;
370 return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
374 return UUCONF_NOT_FOUND;
376 /* Now we have to put in the Permissions information. The relevant
377 Permissions entries are those with this system in the MACHINE
378 list and (if this system does not have a VALIDATE entry) those
379 with a LOGNAME list but no MACHINE list. If no entry is found
380 with this system in the MACHINE list, then we must look for an
381 entry with "OTHER" in the MACHINE list. */
382 ffound_machine = FALSE;
383 ffound_login = FALSE;
384 qother_machine = NULL;
385 for (qperm = qglobal->qprocess->qhdb_permissions;
387 qperm = qperm->qnext)
391 /* MACHINE=OTHER is recognized specially. It appears that OTHER
392 need only be recognized by itself, not when combined with
393 other machine names. */
394 if (qother_machine == NULL
395 && qperm->pzmachine != NULL
396 && qperm->pzmachine != (char **) &_uuconf_unset
397 && qperm->pzmachine[0][0] == 'O'
398 && strcmp (qperm->pzmachine[0], "OTHER") == 0)
399 qother_machine = qperm;
401 /* If this system is named in a MACHINE entry, we must add the
402 appropriate information to every alternate that could be used
406 && qperm->pzmachine != NULL
407 && qperm->pzmachine != (char **) &_uuconf_unset)
409 for (pz = qperm->pzmachine; *pz != NULL; pz++)
411 if ((*pz)[0] == zsystem[0]
412 && strcmp (*pz, zsystem) == 0)
416 qalt = qalt->uuconf_qalternate)
418 if (qalt->uuconf_fcall)
420 iret = ihadd_machine_perm (qglobal, qalt, qperm);
421 if (iret != UUCONF_SUCCESS)
427 ffound_machine = TRUE;
434 /* A LOGNAME line applies to this machine if it is listed in the
435 corresponding VALIDATE entry, or if it is not listed in any
436 VALIDATE entry. On this pass through the Permissions entry
437 we pick up the information if the system appears in a
438 VALIDATE entry; if it does not, we make another pass to put
439 in all the LOGNAME lines. */
440 if (qperm->pzlogname != NULL
441 && qperm->pzlogname != (char **) &_uuconf_unset
442 && qperm->pzvalidate != NULL
443 && qperm->pzvalidate != (char **) &_uuconf_unset)
445 for (pz = qperm->pzvalidate; *pz != NULL; ++pz)
446 if ((*pz)[0] == zsystem[0]
447 && strcmp (*pz, zsystem) == 0)
451 for (pz = qperm->pzlogname; *pz != NULL; ++pz)
453 /* If this LOGNAME line is also a matching MACHINE
454 line, we can add the LOGNAME permissions to the
455 first alternate. Otherwise, we must create a new
456 alternate. We cannot put a LOGNAME line in the
457 first alternate if MACHINE does not match,
458 because certain permissions (e.g. READ) may be
459 specified by both types of lines, and we must use
460 LOGNAME entries only when accepting calls and
461 MACHINE entries only when placing calls. */
463 && (qsys->uuconf_zcalled_login == NULL
464 || (qsys->uuconf_zcalled_login
465 == (char *) &_uuconf_unset)))
467 qsys->uuconf_zcalled_login = *pz;
468 iret = ihadd_logname_perm (qglobal, qsys, qperm);
472 struct uuconf_system *qnew;
473 struct uuconf_system **pq;
475 qnew = ((struct uuconf_system *)
476 uuconf_malloc (pblock,
477 sizeof (struct uuconf_system)));
480 qglobal->ierrno = errno;
481 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
485 qnew->uuconf_qalternate = NULL;
486 for (pq = &qsys->uuconf_qalternate;
488 pq = &(*pq)->uuconf_qalternate)
492 qnew->uuconf_zcalled_login = *pz;
493 qnew->uuconf_fcall = FALSE;
494 iret = ihadd_logname_perm (qglobal, qnew, qperm);
497 if (iret != UUCONF_SUCCESS)
506 /* If we didn't find an entry for the machine, we must use the
507 MACHINE=OTHER entry, if any. */
508 if (! ffound_machine && qother_machine != NULL)
510 for (qalt = qsys; qalt != NULL; qalt = qalt->uuconf_qalternate)
512 if (qalt->uuconf_fcall)
514 iret = ihadd_machine_perm (qglobal, qalt, qother_machine);
515 if (iret != UUCONF_SUCCESS)
521 /* If this system was not listed in any VALIDATE entry, then we must
522 add a called-login for each LOGNAME entry in Permissions. */
525 for (qperm = qglobal->qprocess->qhdb_permissions;
527 qperm = qperm->qnext)
529 if (qperm->pzlogname == NULL
530 || qperm->pzlogname == (char **) &_uuconf_unset)
533 for (pz = qperm->pzlogname; *pz != NULL; pz++)
535 struct uuconf_system *qnew;
536 struct uuconf_system **pq;
538 qnew = ((struct uuconf_system *)
539 uuconf_malloc (pblock,
540 sizeof (struct uuconf_system)));
543 qglobal->ierrno = errno;
544 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
548 qnew->uuconf_qalternate = NULL;
549 for (pq = &qsys->uuconf_qalternate;
551 pq = &(*pq)->uuconf_qalternate)
555 /* We recognize LOGNAME=OTHER specially, although this
556 appears to be an SCO innovation. */
557 if (strcmp (*pz, "OTHER") == 0)
558 qnew->uuconf_zcalled_login = (char *) "ANY";
560 qnew->uuconf_zcalled_login = *pz;
561 qnew->uuconf_fcall = FALSE;
562 iret = ihadd_logname_perm (qglobal, qnew, qperm);
563 if (iret != UUCONF_SUCCESS)
569 /* HDB permits local requests to receive to any directory, which is
570 not the default put in by _uuconf_isystem_basic_default. We set
572 for (qalt = qsys; qalt != NULL; qalt = qalt->uuconf_qalternate)
574 iret = _uuconf_iadd_string (qglobal, (char *) ZROOTDIR,
576 &qalt->uuconf_pzlocal_receive,
578 if (iret != UUCONF_SUCCESS)
582 /* HDB does not have a maximum number of retries if a retry time is
583 given in the time field. */
584 if (qsys->uuconf_qtimegrade != NULL
585 && qsys->uuconf_qtimegrade != (struct uuconf_timespan *) &_uuconf_unset
586 && qsys->uuconf_qtimegrade->uuconf_cretry > 0)
587 qsys->uuconf_cmax_retries = 0;
589 return UUCONF_SUCCESS;
592 /* Add the settings of a MACHINE line in Permissions to a system. */
596 ihadd_machine_perm (qglobal, qsys, qperm)
597 struct sglobal *qglobal;
598 struct uuconf_system *qsys;
599 struct shpermissions *qperm;
601 if (qperm->frequest >= 0)
602 qsys->uuconf_fsend_request = qperm->frequest;
604 qsys->uuconf_fsend_request = FALSE;
605 qsys->uuconf_pzremote_send = qperm->pzread;
606 qsys->uuconf_pzremote_receive = qperm->pzwrite;
607 qsys->uuconf_pzcmds = qperm->pzcommands;
608 qsys->uuconf_zlocalname = qperm->zmyname;
609 qsys->uuconf_zpubdir = qperm->zpubdir;
610 qsys->uuconf_pzalias = qperm->pzalias;
612 return UUCONF_SUCCESS;
615 /* Add the settings of a LOGNAME line in Permissions to a system. */
619 ihadd_logname_perm (qglobal, qsys, qperm)
620 struct sglobal *qglobal;
621 struct uuconf_system *qsys;
622 struct shpermissions *qperm;
624 qsys->uuconf_fcalled = TRUE;
625 if (qperm->frequest >= 0)
626 qsys->uuconf_fsend_request = qperm->frequest;
628 qsys->uuconf_fsend_request = FALSE;
629 qsys->uuconf_fcalled_transfer = qperm->fsendfiles;
630 qsys->uuconf_pzremote_send = qperm->pzread;
631 qsys->uuconf_pzremote_receive = qperm->pzwrite;
632 qsys->uuconf_fcallback = qperm->fcallback;
633 qsys->uuconf_zlocalname = qperm->zmyname;
634 qsys->uuconf_zpubdir = qperm->zpubdir;
636 return UUCONF_SUCCESS;