|
|
1.1 root 1: /* @(#)conn.c 1.16
2: */
3: #include "uucp.h"
4: VERSION(@(#)conn.c 1.16);
5:
6: static char _ProtoStr[20] = ""; /* protocol string from Systems file entry */
7: extern jmp_buf Sjbuf;
8:
9: int alarmtr();
10: static void getProto();
11: /* static getto(), finds(); PUT this back after altconn is included */
12: extern getto();
13: static finds();
14:
15: static notin(), ifdate(), classmatch();
16:
17: extern struct caller caller[];
18:
19: /* Needed for cu for force which line will be used */
20: #ifdef STANDALONE
21: extern char *Myline;
22: #endif STANDALONE
23:
24: /*
25: * conn - place a telephone call to system and login, etc.
26: *
27: * return codes:
28: * FAIL - connection failed
29: * >0 - file no. - connect ok
30: * When a failure occurs, Uerror is set.
31: */
32:
33: conn(system)
34: char *system;
35: {
36: int nf, fn = FAIL;
37: char *flds[F_MAX+1];
38: FILE *fsys;
39: #ifdef MANYSYS
40: int nsys = 0;
41: int lerror = 0; /* local copy so first error is saved */
42: FILE *sysopen();
43: #endif
44:
45: CDEBUG(4, "conn(%s)\n", system);
46: #ifndef MANYSYS
47: fsys = fopen(SYSFILE, "r");
48: ASSERT(fsys != NULL, Ct_OPEN, SYSFILE, errno);
49: #else
50: sysrewind();
51: while ((fsys = sysopen("r")) != NULL) {
52: nsys++;
53: #endif
54: Uerror = 0;
55: while ((nf = finds(fsys, system, flds, F_MAX)) > 0) {
56: fn = getto(flds);
57: CDEBUG(4, "getto ret %d\n", fn);
58: if (fn < 0)
59: continue;
60:
61: #ifdef STANDALONE
62: fclose(fsys);
63: return(fn);
64: #else !STANDALONE
65: if (chat(nf - F_LOGIN, flds + F_LOGIN, fn,"","") == SUCCESS) {
66: fclose(fsys);
67: return(fn); /* successful return */
68: }
69:
70: /* login failed */
71: DEBUG(6, "close caller (%d)\n", fn);
72: close(fn);
73: if (Dc[0] != NULLCHAR) {
74: DEBUG(6, "delock(%s)\n", Dc);
75: delock(Dc);
76: }
77: #endif STANDALONE
78: }
79:
80: /* finds or getto failed */
81: fclose(fsys);
82: #ifdef MANYSYS
83: if (lerror == 0 && Uerror != SS_BADSYSTEM)
84: lerror = Uerror;
85: CDEBUG(4, "not in this Systems; Uerror %d\n", Uerror);
86: }
87: ASSERT(nsys != 0, Ct_OPEN, SYSFILE, errno);
88: if (lerror)
89: Uerror = lerror;
90: #endif
91: CDEBUG(1, "Call Failed: %s\n", UERRORTEXT);
92: return(FAIL);
93: }
94:
95: /*
96: * getto - connect to remote machine
97: *
98: * return codes:
99: * >0 - file number - ok
100: * FAIL - failed
101: */
102:
103: getto(flds)
104: char *flds[];
105: {
106: FILE *dfp;
107: char *dev[D_MAX+2], devbuf[BUFSIZ];
108: register int status;
109: register int dcf = -1;
110: int reread = 0;
111: int tries = 0; /* count of call attempts - for limit purposes */
112:
113: CDEBUG(1, "Device Type %s wanted\n", flds[F_TYPE]);
114: dfp = fopen(DEVFILE, "r");
115: ASSERT(dfp != NULL, Ct_OPEN, DEVFILE, errno);
116: Uerror = 0;
117: while (tries < TRYCALLS) {
118: if ((status=rddev(dfp, flds[F_TYPE], dev, devbuf, D_MAX)) == FAIL) {
119: if (tries == 0 || ++reread >= TRYCALLS)
120: break;
121: rewind(dfp);
122: continue;
123: }
124: /* check class, check (and possibly set) speed */
125: if (classmatch(flds, dev) != SUCCESS)
126: continue;
127: if ((dcf = processdev(flds, dev)) >= 0)
128: break;
129:
130: switch(Uerror) {
131: case SS_CANT_ACCESS_DEVICE:
132: case SS_DEVICE_FAILED:
133: case SS_LOCKED_DEVICE:
134: break;
135: default:
136: tries++;
137: break;
138: }
139: }
140: (void) fclose(dfp);
141: if (status == FAIL && !Uerror) {
142: CDEBUG(1, "Requested Device Type Not Found\n", 0);
143: Uerror = SS_NO_DEVICE;
144: }
145: return(dcf);
146: }
147:
148: /*
149: * classmatch - process 'Any' in Devices and Systems and
150: * determine the correct speed, or match for ==
151: */
152:
153: static int
154: classmatch(flds, dev)
155: char *flds[], *dev[];
156: {
157: /* check class, check (and possibly set) speed */
158: if (EQUALS(flds[F_CLASS], "Any")
159: && EQUALS(dev[D_CLASS], "Any")) {
160: dev[D_CLASS] = flds[F_CLASS] = DEFAULT_BAUDRATE;
161: return(SUCCESS);
162: } else if (EQUALS(dev[F_CLASS], "Any")) {
163: dev[D_CLASS] = flds[F_CLASS];
164: return(SUCCESS);
165: } else if (EQUALS(flds[F_CLASS], "Any")) {
166: flds[D_CLASS] = dev[F_CLASS];
167: return(SUCCESS);
168: } else if (EQUALS(flds[F_CLASS], dev[D_CLASS]))
169: return(SUCCESS);
170: else
171: return(FAIL);
172: }
173:
174:
175: /***
176: * rddev - find and unpack a line from device file for this caller type
177: * lines starting with whitespace of '#' are comments
178: *
179: * return codes:
180: * >0 - number of arguments in vector - succeeded
181: * FAIL - EOF
182: ***/
183:
184: rddev(fp, type, dev, buf, devcount)
185: FILE *fp;
186: char *type;
187: char *dev[];
188: char *buf;
189: {
190: int na;
191:
192: while (fgets(buf, BUFSIZ, fp) != NULL) {
193: if (buf[0] == ' ' || buf[0] == '\t'
194: || buf[0] == '\n' || buf[0] == '\0' || buf[0] == '#')
195: continue;
196: na = getargs(buf, dev, devcount);
197: ASSERT(na >= D_CALLER, "BAD LINE", buf, na);
198:
199: /* For cu -- to force the requested line to be used */
200: #ifdef STANDALONE
201: if ((Myline != NULL) && (!EQUALS(Myline, dev[D_LINE])) )
202: continue;
203: #endif STANDALONE
204:
205: bsfix(dev); /* replace \X fields */
206: if (EQUALS(dev[D_TYPE], type))
207: return(na);
208: }
209: return(FAIL);
210: }
211:
212:
213: /*
214: * finds - set system attribute vector
215: *
216: * input:
217: * fsys - open Systems file descriptor
218: * sysnam - system name to find
219: * output:
220: * flds - attibute vector from Systems file
221: * fldcount - number of fields in flds
222: * return codes:
223: * >0 - number of arguments in vector - succeeded
224: * FAIL - failed
225: * Uerror set:
226: * 0 - found a line in Systems file
227: * SS_BADSYSTEM - no line found in Systems file
228: * SS_TIME_WRONG - wrong time to call
229: */
230:
231: static
232: finds(fsys, sysnam, flds, fldcount)
233: char *sysnam, *flds[];
234: FILE *fsys;
235: {
236: static char info[BUFSIZ];
237: int na;
238:
239: /* format of fields
240: * 0 name;
241: * 1 time
242: * 2 acu/hardwired
243: * 3 speed
244: * etc
245: */
246: while (fgets(info, BUFSIZ, fsys) != NULL) {
247: if (info[0] == '#')
248: continue;
249: na = getargs(info, flds, fldcount);
250: bsfix(flds); /* replace \X fields */
251: if ( !EQUALSN(sysnam, flds[F_NAME], SYSNSIZE))
252: continue;
253: #ifndef STANDALONE
254: if (ifdate(flds[F_TIME])) {
255: /* found a good entry */
256: getProto(flds[F_TYPE]);
257: Uerror = 0;
258: return(na); /* FOUND OK LINE */
259: }
260: CDEBUG(1, "Wrong Time To Call: %s\n", flds[F_TIME]);
261: Uerror = SS_TIME_WRONG;
262: #else !STANDALONE
263: Uerror = 0;
264: return(na); /* FOUND OK LINE */
265: #endif STANDALONE
266: }
267: if (!Uerror)
268: Uerror = SS_BADSYSTEM;
269: return(FAIL);
270: }
271:
272: /*
273: * getProto - get the protocol letters from the input string.
274: * input:
275: * str - string from Systems file (flds[F_TYPE])--the ,
276: * delimits the protocol string
277: * e.g. ACU,g or DK,d
278: * output:
279: * str - the , (if present) will be replaced with NULLCHAR
280: * global ProtoStr will be modified
281: * return: none
282: */
283:
284: static
285: void
286: getProto(str)
287: char *str;
288: {
289: register char *p;
290: if ( (p=strchr(str, ',')) != NULL) {
291: *p = NULLCHAR;
292: (void) strcpy(_ProtoStr, p+1);
293: DEBUG(7, "ProtoStr = %s\n", _ProtoStr);
294: }
295: else
296: *_ProtoStr = NULLCHAR;
297: }
298:
299: /*
300: * check for a specified protocol selection string
301: * return:
302: * protocol string pointer
303: * NULL if none specified for LOGNAME
304: */
305: char *
306: protoString()
307: {
308: return(_ProtoStr[0] == NULLCHAR ? NULL : _ProtoStr);
309: }
310:
311: static int _Echoflag;
312: static int _Slowflag;
313: /*
314: * chat - do conversation
315: * input:
316: * flds - fields from Systems file
317: * nf - number of fields in flds array
318: * dcr - write file number
319: * phstr1 - phone number to replace \D
320: * phstr2 - phone number to replace \T
321: *
322: * return codes: 0 | FAIL
323: */
324:
325: chat(nf, flds, fn, phstr1, phstr2)
326: char *flds[], *phstr1, *phstr2;
327: int nf, fn;
328: {
329: char *want, *altern;
330: extern char *index();
331: int k, ok;
332:
333: _Echoflag = 0;
334: _Slowflag = 0;
335: for (k = 0; k < nf; k += 2) {
336: want = flds[k];
337: ok = FAIL;
338: while (ok != 0) {
339: altern = index(want, '-');
340: if (altern != NULL)
341: *altern++ = NULLCHAR;
342: ok = expect(want, fn);
343: if (ok == 0)
344: break;
345: if (altern == NULL) {
346: Uerror = SS_LOGIN_FAILED;
347: logent(UERRORTEXT, "FAILED");
348: return(FAIL);
349: }
350: want = index(altern, '-');
351: if (want != NULL)
352: *want++ = NULLCHAR;
353: sendthem(altern, fn, phstr1, phstr2);
354: }
355: sleep(2);
356: if (flds[k+1])
357: sendthem(flds[k+1], fn, phstr1, phstr2);
358: }
359: return(0);
360: }
361:
362: #define MR 500
363:
364: /***
365: * expect(str, fn) look for expected string
366: * char *str;
367: *
368: * return codes:
369: * 0 - found
370: * FAIL - lost line or too many characters read
371: * some character - timed out
372: */
373:
374: expect(str, fn)
375: char *str;
376: int fn;
377: {
378: static char rdvec[MR];
379: char *rp = rdvec;
380: register int kr, c;
381: char nextch;
382: extern errno;
383:
384: *rp = 0;
385:
386: CDEBUG(4, "expect: (", 0);
387: for (c=0; kr=str[c]; c++)
388: if (kr < 040) {
389: CDEBUG(4, "^%c", kr | 0100);
390: } else
391: CDEBUG(4, "%c", kr);
392: CDEBUG(4, ")\n", 0);
393:
394: if (EQUALS(str, "\"\"")) {
395: CDEBUG(4, "got it\n", 0);
396: return(0);
397: }
398: if (setjmp(Sjbuf)) {
399: return(FAIL);
400: }
401: (void) signal(SIGALRM, alarmtr);
402: alarm(MAXEXPECTTIME);
403: while (notin(str, rdvec)) {
404: errno = 0;
405: kr = read(fn, &nextch, 1);
406: if (kr <= 0) {
407: alarm(0);
408: CDEBUG(4, "lost line errno - %d\n", errno);
409: logent("LOGIN", "LOST LINE");
410: return(FAIL);
411: }
412: c = nextch & 0177;
413: if ((*rp = c) != NULLCHAR) {
414: CDEBUG(4, "%s", c < 040 ? "^" : "");
415: CDEBUG(4, "%c", c < 040 ? c | 0100 : c);
416: rp++;
417: }
418: if (rp >= rdvec + MR) {
419: CDEBUG(4, "enough already\n", 0);
420: alarm(0);
421: return(FAIL);
422: }
423: *rp = NULLCHAR;
424: }
425: alarm(0);
426: CDEBUG(4, "got it\n", 0);
427: return(0);
428: }
429:
430:
431: /***
432: * alarmtr() - catch alarm routine for "expect".
433: */
434:
435: alarmtr()
436: {
437: CDEBUG(6, "timed out\n", 0);
438: longjmp(Sjbuf, 1);
439: }
440:
441:
442: /***
443: * sendthem(str, fn, phstr1, phstr2) send line of chat sequence
444: * char *str, *phstr;
445: *
446: * return codes: none
447: */
448:
449: sendthem(str, fn, phstr1, phstr2)
450: char *str, *phstr1, *phstr2;
451: int fn;
452: {
453: int sendcr = 1;
454: register char *sptr, *pptr;
455:
456: if (PREFIX("BREAK", str)) {
457: /* send break */
458: CDEBUG(5, "BREAK\n", 0);
459: genbrk(fn);
460: return;
461: }
462:
463: if (EQUALS(str, "EOT")) {
464: CDEBUG(5, "EOT\n", 0);
465: (void) write(fn, EOTMSG, strlen(EOTMSG));
466: return;
467: }
468:
469: if (EQUALS(str, "\"\"")) {
470: CDEBUG(5, "\"\"\n", 0);
471: str += 2;
472: }
473:
474: CDEBUG(5, "sendthem (", "");
475: if (setjmp(Sjbuf)) /* Timer so echo check doesn't last forever */
476: goto err;
477: (void) signal(SIGALRM, alarmtr);
478: alarm(MAXEXPECTTIME);
479: for (sptr = str; *sptr; sptr++) {
480: if (*sptr == '\\')
481: switch(*++sptr) {
482: case 'D':
483: for (pptr=phstr1; *pptr; pptr++)
484: if (wrchar(fn, pptr))
485: goto err;
486: continue;
487: case 'T':
488: for (pptr=phstr2; *pptr; pptr++)
489: if (wrchar(fn, pptr))
490: goto err;
491: continue;
492: case 'N':
493: *sptr = 0;
494: break;
495: case 'd':
496: CDEBUG(5, "DELAY\n", 0);
497: sleep(2);
498: continue;
499: case 'c':
500: if (*(sptr+1) == NULLCHAR) {
501: CDEBUG(5, "<NO CR>", 0);
502: sendcr = 0;
503: continue;
504: }
505: CDEBUG(5, "<NO CR - MIDDLE IGNORED>\n", 0);
506: continue;
507: case 's':
508: *sptr = ' ';
509: break;
510: case 'p':
511: CDEBUG(5, "PAUSE\n", 0);
512: nap(HZ/4); /* approximately 1/4 second */
513: continue;
514: case 'E':
515: CDEBUG(5, "ECHO CHECK ON\n", 0);
516: _Echoflag = 1;
517: continue;
518: case 'e':
519: CDEBUG(5, "ECHO CHECK OFF\n", 0);
520: _Echoflag = 0;
521: continue;
522: case 'K':
523: CDEBUG(5, "BREAK\n", 0);
524: genbrk(fn);
525: continue;
526: case 'W':
527: _Slowflag = 1;
528: continue;
529: case 'w':
530: _Slowflag = 0;
531: continue;
532: case '\\':
533: /* backslash escapes itself */
534: break;
535: default:
536: /* send the backslash */
537: --sptr;
538: break;
539: }
540: if (wrchar(fn, sptr))
541: goto err;
542: }
543:
544: if (sendcr) {
545: CDEBUG(5, "^M", 0);
546: (void) write(fn, "\r", 1);
547: }
548: err:
549: alarm(0);
550: CDEBUG(5, ")\n", 0);
551: return;
552: }
553:
554: wrchar(fn, sptr)
555: register int fn;
556: register char *sptr;
557: {
558: if (GRPCHK(getgid())) /* protect Systems file */
559: {
560: CDEBUG(5, "%s", *sptr < 040 ? "^" : "");
561: CDEBUG(5, "%c", *sptr < 040 ? *sptr | 0100 : *sptr);
562: }
563: if ((write(fn, sptr, 1)) != 1)
564: return(FAIL);
565: if (_Echoflag) {
566: char chr;
567: while(1) { /* Should set a timer here */
568: if (read(fn, &chr, 1) != 1)
569: return(FAIL);
570: chr &= 0177;
571: CDEBUG(4, "%s", chr < 040 ? "^" : "");
572: CDEBUG(4, "%c", chr < 040 ? chr | 0100 : chr);
573: if (chr == ((*sptr) & 0177))
574: break;
575: }
576:
577: }
578: if (_Slowflag)
579: sleep(1);
580: return(SUCCESS);
581: }
582:
583:
584: /***
585: * notin(sh, lg) check for occurrence of substring "sh"
586: * char *sh, *lg;
587: *
588: * return codes:
589: * 0 - found the string
590: * 1 - not in the string
591: */
592:
593: static
594: notin(sh, lg)
595: char *sh, *lg;
596: {
597: while (*lg != NULLCHAR) {
598: if (PREFIX(sh, lg))
599: return(0);
600: else
601: lg++;
602: }
603: return(1);
604: }
605:
606:
607: /*******
608: * ifdate(s)
609: * char *s;
610: *
611: * ifdate - this routine will check a string (s)
612: * like "MoTu0800-1730" to see if the present
613: * time is within the given limits.
614: * SIDE EFFECT - Retrytime is set to number following ";"
615: *
616: * String alternatives:
617: * Wk - Mo thru Fr
618: * zero or one time means all day
619: * Any - any day
620: *
621: * return codes:
622: * 0 - not within limits
623: * 1 - within limits
624: */
625:
626: static
627: ifdate(s)
628: char *s;
629: {
630: static char *days[] = {
631: "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
632: };
633: time_t clock;
634: int t__now;
635: char *p, *rindex(), *index();
636: struct tm *tp;
637:
638: time(&clock);
639: tp = localtime(&clock);
640: t__now = tp->tm_hour * 100 + tp->tm_min; /* "navy" time */
641:
642: /*
643: * pick up retry time for failures
644: * global variable Retrytime is set here
645: */
646: if ((p = rindex(s, ';')) != NULL)
647: if (isdigit(p[1])) {
648: if (sscanf(p+1, "%d", &Retrytime) < 1)
649: Retrytime = 5; /* 5 minutes is error default */
650: Retrytime *= 60;
651: *p = NULLCHAR;
652: }
653:
654: while (*s) {
655: int i, dayok;
656:
657: for (dayok = 0; (!dayok) && isalpha(*s); s++) {
658: if (PREFIX("Any", s))
659: dayok = 1;
660: else if (PREFIX("Wk", s)) {
661: if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
662: dayok = 1;
663: } else
664: for (i = 0; days[i]; i++)
665: if (PREFIX(days[i], s))
666: if (tp->tm_wday == i)
667: dayok = 1;
668: }
669:
670: if (dayok) {
671: int t__low, t__high;
672:
673: while (isalpha(*s)) /* flush remaining day stuff */
674: s++;
675:
676: if ((sscanf(s, "%d-%d", &t__low, &t__high) < 2)
677: || (t__low == t__high))
678: return(1);
679:
680: /* 0000 crossover? */
681: if (t__low < t__high) {
682: if (t__low <= t__now && t__now <= t__high)
683: return(1);
684: } else if (t__low <= t__now || t__now <= t__high)
685: return(1);
686:
687: /* aim at next time slot */
688: if ((s = index(s, ',')) == NULL)
689: break;
690: }
691: s++;
692: }
693: return(0);
694: }
695:
696: /***
697: * char *
698: * fdig(cp) find first digit in string
699: *
700: * return - pointer to first digit in string or end of string
701: */
702:
703: char *
704: fdig(cp)
705: char *cp;
706: {
707: char *c;
708:
709: for (c = cp; *c; c++)
710: if (*c >= '0' && *c <= '9')
711: break;
712: return(c);
713: }
714:
715:
716: #ifdef FASTTIMER
717: /* Sleep in increments of 60ths of second. */
718: nap (time)
719: register int time;
720: {
721: static int fd;
722:
723: if (fd == 0)
724: fd = open (FASTTIMER, 0);
725:
726: read (fd, 0, time);
727: }
728:
729: #endif FASTTIMER
730:
731: #ifdef BSD4_2
732:
733: /* nap(n) -- sleep for 'n' ticks of 1/60th sec each. */
734: /* This version, by Mark Horton, uses the select system call */
735:
736:
737: nap(n)
738: unsigned n;
739: {
740: struct timeval tv;
741: int rc;
742:
743: if (n==0)
744: return;
745: tv.tv_sec = n/60;
746: tv.tv_usec = ((n%60)*1000000L)/60;
747: rc = select(32, 0, 0, 0, &tv);
748: }
749:
750: #endif BSD4_2
751:
752: #ifdef NONAP
753:
754: /* nap(n) where n is ticks
755: *
756: * loop using n/HZ part of a second
757: * if n represents more than 1 second, then
758: * use sleep(time) where time is the equivalent
759: * seconds rounded off to full seconds
760: * NOTE - this is a rough approximation and chews up
761: * processor resource!
762: */
763:
764: nap(n)
765: unsigned n;
766: {
767: struct tms tbuf;
768: long endtime;
769: int i;
770:
771: if (n > HZ) {
772: /* > second, use sleep, rounding time */
773: sleep( (int) (((n)+HZ/2)/HZ) );
774: return;
775: }
776:
777: /* use timing loop for < 1 second */
778: endtime = times(&tbuf) + 3*n/4; /* use 3/4 because of scheduler! */
779: while (times(&tbuf) < endtime) {
780: for (i=0; i<1000; i++, i*i)
781: ;
782: }
783: return;
784: }
785:
786:
787: #endif NONAP
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.