|
|
1.1 root 1: /* hsinfo.c
2: Get information about a system from the HDB configuration files.
3:
4: Copyright (C) 1992 Ian Lance Taylor
5:
6: This file is part of the Taylor UUCP uuconf library.
7:
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.
12:
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.
17:
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., 675 Mass Ave, Cambridge, MA 02139, USA.
21:
22: The author of the program may be contacted at [email protected] or
23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24: */
25:
26: #include "uucnfi.h"
27:
28: #if USE_RCS_ID
29: const char _uuconf_hsinfo_rcsid[] = "$Id: hsinfo.c,v 1.1 93/07/30 08:07:17 bin Exp Locker: bin $";
30: #endif
31:
32: #include <errno.h>
33: #include <ctype.h>
34:
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));
41:
42: /* Get the information for a particular system from the HDB
43: configuration files. This does not make sure that all the default
44: values are set. */
45:
46: int
47: _uuconf_ihdb_system_internal (qglobal, zsystem, qsys)
48: struct sglobal *qglobal;
49: const char *zsystem;
50: struct uuconf_system *qsys;
51: {
52: int iret;
53: struct shpermissions *qperm;
54: char *zline;
55: size_t cline;
56: char **pzsplit;
57: size_t csplit;
58: char **pzcomma;
59: size_t ccomma;
60: pointer pblock;
61: char **pz;
62: boolean ffound_machine, ffound_login;
63: struct shpermissions *qother_machine;
64: struct uuconf_system *qalt;
65:
66: if (! qglobal->qprocess->fhdb_read_permissions)
67: {
68: iret = _uuconf_ihread_permissions (qglobal);
69: if (iret != UUCONF_SUCCESS)
70: return iret;
71: }
72:
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. */
76:
77: for (qperm = qglobal->qprocess->qhdb_permissions;
78: qperm != NULL;
79: qperm = qperm->qnext)
80: {
81: if (qperm->pzalias == NULL
82: || qperm->pzmachine == NULL
83: || qperm->pzalias == (char **) &_uuconf_unset
84: || qperm->pzmachine == (char **) &_uuconf_unset)
85: continue;
86:
87: for (pz = qperm->pzalias; *pz != NULL; pz++)
88: {
89: if (strcmp (*pz, zsystem) == 0)
90: {
91: zsystem = qperm->pzmachine[0];
92: break;
93: }
94: }
95: if (*pz != NULL)
96: break;
97: }
98:
99: zline = NULL;
100: cline = 0;
101: pzsplit = NULL;
102: csplit = 0;
103: pzcomma = NULL;
104: ccomma = 0;
105:
106: pblock = NULL;
107:
108: iret = UUCONF_SUCCESS;
109:
110: for (pz = qglobal->qprocess->pzhdb_systems; *pz != NULL; pz++)
111: {
112: FILE *e;
113: int cchars;
114:
115: e = fopen (*pz, "r");
116: if (e == NULL)
117: {
118: if (FNO_SUCH_FILE ())
119: continue;
120: qglobal->ierrno = errno;
121: iret = UUCONF_FOPEN_FAILED | UUCONF_ERROR_ERRNO;
122: break;
123: }
124:
125: qglobal->ilineno = 0;
126:
127: while ((cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
128: {
129: int ctoks, ctimes, i;
130: struct uuconf_system *qset;
131: char *z, *zretry;
132: int cretry;
133:
134: ++qglobal->ilineno;
135:
136: --cchars;
137: if (zline[cchars] == '\n')
138: zline[cchars] = '\0';
139: if (isspace (BUCHAR (zline[0])) || zline[0] == '#')
140: continue;
141:
142: ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
143: if (ctoks < 0)
144: {
145: qglobal->ierrno = errno;
146: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
147: break;
148: }
149:
150: /* If this isn't the system we're looking for, keep reading
151: the file. */
152: if (ctoks < 1
153: || strcmp (zsystem, pzsplit[0]) != 0)
154: continue;
155:
156: /* If this is the first time we've found the system, we want
157: to set *qsys directly. Otherwise, we allocate a new
158: alternate. */
159: if (pblock == NULL)
160: {
161: pblock = uuconf_malloc_block ();
162: if (pblock == NULL)
163: {
164: qglobal->ierrno = errno;
165: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
166: break;
167: }
168: _uuconf_uclear_system (qsys);
169: qsys->uuconf_palloc = pblock;
170: qset = qsys;
171: }
172: else
173: {
174: struct uuconf_system **pq;
175:
176: qset = ((struct uuconf_system *)
177: uuconf_malloc (pblock, sizeof (struct uuconf_system)));
178: if (qset == NULL)
179: {
180: qglobal->ierrno = errno;
181: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
182: break;
183: }
184: _uuconf_uclear_system (qset);
185: for (pq = &qsys->uuconf_qalternate;
186: *pq != NULL;
187: pq = &(*pq)->uuconf_qalternate)
188: ;
189: *pq = qset;
190: }
191:
192: /* Add this line to the memory block we are building for the
193: system. */
194: if (uuconf_add_block (pblock, zline) != 0)
195: {
196: qglobal->ierrno = errno;
197: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
198: break;
199: }
200:
201: zline = NULL;
202: cline = 0;
203:
204: /* The format of a line in Systems is
205: system time device speed phone chat
206: For example,
207: airs Any ACU 9600 5551212 ogin: foo pass: bar
208: */
209:
210: /* Get the system name. */
211:
212: qset->uuconf_zname = pzsplit[0];
213: qset->uuconf_fcall = TRUE;
214: qset->uuconf_fcalled = FALSE;
215:
216: if (ctoks < 2)
217: continue;
218:
219: /* A time string is "time/grade,time/grade;retry". A
220: missing grade is taken as BGRADE_LOW. */
221: zretry = strchr (pzsplit[1], ';');
222: if (zretry == NULL)
223: cretry = 0;
224: else
225: {
226: *zretry = '\0';
227: cretry = (int) strtol (zretry + 1, (char **) NULL, 10);
228: }
229:
230: ctimes = _uuconf_istrsplit (pzsplit[1], ',', &pzcomma, &ccomma);
231: if (ctimes < 0)
232: {
233: qglobal->ierrno = errno;
234: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
235: break;
236: }
237:
238: for (i = 0; i < ctimes; i++)
239: {
240: char *zslash;
241: char bgrade;
242:
243: z = pzcomma[i];
244: zslash = strchr (z, '/');
245: if (zslash == NULL)
246: bgrade = UUCONF_GRADE_LOW;
247: else
248: {
249: *zslash = '\0';
250: bgrade = zslash[1];
251: if (! UUCONF_GRADE_LEGAL (bgrade))
252: bgrade = UUCONF_GRADE_LOW;
253: }
254:
255: iret = _uuconf_itime_parse (qglobal, z, (long) bgrade,
256: cretry, _uuconf_itime_grade_cmp,
257: &qset->uuconf_qtimegrade,
258: pblock);
259: if (iret != UUCONF_SUCCESS)
260: break;
261: }
262:
263: if (iret != UUCONF_SUCCESS)
264: break;
265:
266: if (ctoks < 3)
267: continue;
268:
269: /* Pick up the device name. It can be followed by a comma
270: and a list of protocols. */
271: qset->uuconf_zport = pzsplit[2];
272: z = strchr (pzsplit[2], ',');
273: if (z != NULL)
274: {
275: qset->uuconf_zprotocols = z + 1;
276: *z = '\0';
277: }
278:
279: if (ctoks < 4)
280: continue;
281:
282: /* The speed entry can be a numeric speed, or a range of
283: speeds, or "Any", or "-". If it starts with a letter,
284: the initial nonnumeric prefix is a modem class, which
285: gets appended to the port name. */
286: z = pzsplit[3];
287: if (strcasecmp (z, "Any") != 0
288: && strcmp (z, "-") != 0)
289: {
290: char *zend;
291:
292: while (*z != '\0' && ! isdigit (BUCHAR (*z)))
293: ++z;
294:
295: qset->uuconf_ibaud = strtol (z, &zend, 10);
296: if (*zend == '-')
297: qset->uuconf_ihighbaud = strtol (zend + 1, (char **) NULL,
298: 10);
299:
300: if (z != pzsplit[3])
301: {
302: size_t cport, cclass;
303:
304: cport = strlen (pzsplit[2]);
305: cclass = z - pzsplit[3];
306: qset->uuconf_zport = uuconf_malloc (pblock,
307: cport + cclass + 1);
308: if (qset->uuconf_zport == NULL)
309: {
310: qglobal->ierrno = errno;
311: iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
312: break;
313: }
314: memcpy ((pointer) qset->uuconf_zport, (pointer) pzsplit[2],
315: cport);
316: memcpy ((pointer) (qset->uuconf_zport + cport),
317: (pointer) pzsplit[3], cclass);
318: qset->uuconf_zport[cport + cclass] = '\0';
319: }
320: }
321:
322: if (ctoks < 5)
323: continue;
324:
325: /* Get the phone number. */
326: qset->uuconf_zphone = pzsplit[4];
327:
328: if (ctoks < 6)
329: continue;
330:
331: /* Get the chat script. We just hand this off to the chat
332: script processor, so that it will parse subsend and
333: subexpect strings correctly. */
334: pzsplit[4] = (char *) "chat";
335: iret = _uuconf_ichat_cmd (qglobal, ctoks - 4, pzsplit + 4,
336: &qset->uuconf_schat, pblock);
337: iret &=~ UUCONF_CMDTABRET_KEEP;
338: if (iret != UUCONF_SUCCESS)
339: break;
340: }
341:
342: (void) fclose (e);
343:
344: if (iret != UUCONF_SUCCESS)
345: break;
346: }
347:
348: if (zline != NULL)
349: free ((pointer) zline);
350: if (pzsplit != NULL)
351: free ((pointer) pzsplit);
352: if (pzcomma != NULL)
353: free ((pointer) pzcomma);
354:
355: if (iret != UUCONF_SUCCESS)
356: {
357: qglobal->zfilename = *pz;
358: return iret | UUCONF_ERROR_FILENAME;
359: }
360:
361: if (pblock == NULL)
362: return UUCONF_NOT_FOUND;
363:
364: /* Now we have to put in the Permissions information. The relevant
365: Permissions entries are those with this system in the MACHINE
366: list and (if this system does not have a VALIDATE entry) those
367: with a LOGNAME list but no MACHINE list. If no entry is found
368: with this system in the MACHINE list, then we must look for an
369: entry with "OTHER" in the MACHINE list. */
370: ffound_machine = FALSE;
371: ffound_login = FALSE;
372: qother_machine = NULL;
373: for (qperm = qglobal->qprocess->qhdb_permissions;
374: qperm != NULL;
375: qperm = qperm->qnext)
376: {
377: boolean fmachine;
378:
379: /* MACHINE=OTHER is recognized specially. It appears that OTHER
380: need only be recognized by itself, not when combined with
381: other machine names. */
382: if (qother_machine == NULL
383: && qperm->pzmachine != NULL
384: && qperm->pzmachine != (char **) &_uuconf_unset
385: && qperm->pzmachine[0][0] == 'O'
386: && strcmp (qperm->pzmachine[0], "OTHER") == 0)
387: qother_machine = qperm;
388:
389: /* If this system is named in a MACHINE entry, we must add the
390: appropriate information to every alternate that could be used
391: for calling out. */
392: fmachine = FALSE;
393: if (! ffound_machine
394: && qperm->pzmachine != NULL
395: && qperm->pzmachine != (char **) &_uuconf_unset)
396: {
397: for (pz = qperm->pzmachine; *pz != NULL; pz++)
398: {
399: if ((*pz)[0] == zsystem[0]
400: && strcmp (*pz, zsystem) == 0)
401: {
402: for (qalt = qsys;
403: qalt != NULL;
404: qalt = qalt->uuconf_qalternate)
405: {
406: if (qalt->uuconf_fcall)
407: {
408: iret = ihadd_machine_perm (qglobal, qalt, qperm);
409: if (iret != UUCONF_SUCCESS)
410: return iret;
411: }
412: }
413:
414: fmachine = TRUE;
415: ffound_machine = TRUE;
416:
417: break;
418: }
419: }
420: }
421:
422: /* A LOGNAME line applies to this machine if it is listed in the
423: corresponding VALIDATE entry, or if it is not listed in any
424: VALIDATE entry. On this pass through the Permissions entry
425: we pick up the information if the system appears in a
426: VALIDATE entry; if it does not, we make another pass to put
427: in all the LOGNAME lines. */
428: if (qperm->pzlogname != NULL
429: && qperm->pzlogname != (char **) &_uuconf_unset
430: && qperm->pzvalidate != NULL
431: && qperm->pzvalidate != (char **) &_uuconf_unset)
432: {
433: for (pz = qperm->pzvalidate; *pz != NULL; ++pz)
434: if ((*pz)[0] == zsystem[0]
435: && strcmp (*pz, zsystem) == 0)
436: break;
437: if (*pz != NULL)
438: {
439: for (pz = qperm->pzlogname; *pz != NULL; ++pz)
440: {
441: /* If this LOGNAME line is also a matching MACHINE
442: line, we can add the LOGNAME permissions to the
443: first alternate. Otherwise, we must create a new
444: alternate. We cannot put a LOGNAME line in the
445: first alternate if MACHINE does not match,
446: because certain permissions (e.g. READ) may be
447: specified by both types of lines, and we must use
448: LOGNAME entries only when accepting calls and
449: MACHINE entries only when placing calls. */
450: if (fmachine
451: && (qsys->uuconf_zcalled_login == NULL
452: || (qsys->uuconf_zcalled_login
453: == (char *) &_uuconf_unset)))
454: {
455: qsys->uuconf_zcalled_login = *pz;
456: iret = ihadd_logname_perm (qglobal, qsys, qperm);
457: }
458: else
459: {
460: struct uuconf_system *qnew;
461: struct uuconf_system **pq;
462:
463: qnew = ((struct uuconf_system *)
464: uuconf_malloc (pblock,
465: sizeof (struct uuconf_system)));
466: if (qnew == NULL)
467: {
468: qglobal->ierrno = errno;
469: return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
470: }
471:
472: *qnew = *qsys;
473: qnew->uuconf_qalternate = NULL;
474: for (pq = &qsys->uuconf_qalternate;
475: *pq != NULL;
476: pq = &(*pq)->uuconf_qalternate)
477: ;
478: *pq = qnew;
479:
480: qnew->uuconf_zcalled_login = *pz;
481: qnew->uuconf_fcall = FALSE;
482: iret = ihadd_logname_perm (qglobal, qnew, qperm);
483: }
484:
485: if (iret != UUCONF_SUCCESS)
486: return iret;
487: }
488:
489: ffound_login = TRUE;
490: }
491: }
492: }
493:
494: /* If we didn't find an entry for the machine, we must use the
495: MACHINE=OTHER entry, if any. */
496: if (! ffound_machine && qother_machine != NULL)
497: {
498: for (qalt = qsys; qalt != NULL; qalt = qalt->uuconf_qalternate)
499: {
500: if (qalt->uuconf_fcall)
501: {
502: iret = ihadd_machine_perm (qglobal, qalt, qother_machine);
503: if (iret != UUCONF_SUCCESS)
504: return iret;
505: }
506: }
507: }
508:
509: /* If this system was not listed in any VALIDATE entry, then we must
510: add a called-login for each LOGNAME entry in Permissions. */
511: if (! ffound_login)
512: {
513: for (qperm = qglobal->qprocess->qhdb_permissions;
514: qperm != NULL;
515: qperm = qperm->qnext)
516: {
517: if (qperm->pzlogname == NULL
518: || qperm->pzlogname == (char **) &_uuconf_unset)
519: continue;
520:
521: for (pz = qperm->pzlogname; *pz != NULL; pz++)
522: {
523: struct uuconf_system *qnew;
524: struct uuconf_system **pq;
525:
526: qnew = ((struct uuconf_system *)
527: uuconf_malloc (pblock,
528: sizeof (struct uuconf_system)));
529: if (qnew == NULL)
530: {
531: qglobal->ierrno = errno;
532: return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
533: }
534:
535: *qnew = *qsys;
536: qnew->uuconf_qalternate = NULL;
537: for (pq = &qsys->uuconf_qalternate;
538: *pq != NULL;
539: pq = &(*pq)->uuconf_qalternate)
540: ;
541: *pq = qnew;
542:
543: /* We recognize LOGNAME=OTHER specially, although this
544: appears to be an SCO innovation. */
545: if (strcmp (*pz, "OTHER") == 0)
546: qnew->uuconf_zcalled_login = (char *) "ANY";
547: else
548: qnew->uuconf_zcalled_login = *pz;
549: qnew->uuconf_fcall = FALSE;
550: iret = ihadd_logname_perm (qglobal, qnew, qperm);
551: if (iret != UUCONF_SUCCESS)
552: return iret;
553: }
554: }
555: }
556:
557: /* HDB permits local requests to receive to any directory, which is
558: not the default put in by _uuconf_isystem_basic_default. We set
559: it here instead. */
560: for (qalt = qsys; qalt != NULL; qalt = qalt->uuconf_qalternate)
561: {
562: iret = _uuconf_iadd_string (qglobal, (char *) ZROOTDIR,
563: FALSE, FALSE,
564: &qalt->uuconf_pzlocal_receive,
565: pblock);
566: if (iret != UUCONF_SUCCESS)
567: return iret;
568: }
569:
570: /* HDB does not have a maximum number of retries if a retry time is
571: given in the time field. */
572: if (qsys->uuconf_qtimegrade != NULL
573: && qsys->uuconf_qtimegrade != (struct uuconf_timespan *) &_uuconf_unset
574: && qsys->uuconf_qtimegrade->uuconf_cretry > 0)
575: qsys->uuconf_cmax_retries = 0;
576:
577: return UUCONF_SUCCESS;
578: }
579:
580: /* Add the settings of a MACHINE line in Permissions to a system. */
581:
582: /*ARGSIGNORED*/
583: static int
584: ihadd_machine_perm (qglobal, qsys, qperm)
585: struct sglobal *qglobal;
586: struct uuconf_system *qsys;
587: struct shpermissions *qperm;
588: {
589: if (qperm->frequest >= 0)
590: qsys->uuconf_fsend_request = qperm->frequest;
591: else
592: qsys->uuconf_fsend_request = FALSE;
593: qsys->uuconf_pzremote_send = qperm->pzread;
594: qsys->uuconf_pzremote_receive = qperm->pzwrite;
595: qsys->uuconf_pzcmds = qperm->pzcommands;
596: qsys->uuconf_zlocalname = qperm->zmyname;
597: qsys->uuconf_zpubdir = qperm->zpubdir;
598: qsys->uuconf_pzalias = qperm->pzalias;
599:
600: return UUCONF_SUCCESS;
601: }
602:
603: /* Add the settings of a LOGNAME line in Permissions to a system. */
604:
605: /*ARGSIGNORED*/
606: static int
607: ihadd_logname_perm (qglobal, qsys, qperm)
608: struct sglobal *qglobal;
609: struct uuconf_system *qsys;
610: struct shpermissions *qperm;
611: {
612: qsys->uuconf_fcalled = TRUE;
613: if (qperm->frequest >= 0)
614: qsys->uuconf_fsend_request = qperm->frequest;
615: else
616: qsys->uuconf_fsend_request = FALSE;
617: qsys->uuconf_fcalled_transfer = qperm->fsendfiles;
618: qsys->uuconf_pzremote_send = qperm->pzread;
619: qsys->uuconf_pzremote_receive = qperm->pzwrite;
620: qsys->uuconf_fcallback = qperm->fcallback;
621: qsys->uuconf_zlocalname = qperm->zmyname;
622: qsys->uuconf_zpubdir = qperm->zpubdir;
623:
624: return UUCONF_SUCCESS;
625: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.