|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)conn.c 5.15 (Berkeley) 5/4/88";
3: #endif
4:
5: #include <signal.h>
6: #include "uucp.h"
7: #include <setjmp.h>
8: #include <ctype.h>
9: #include <errno.h>
10: #ifdef USG
11: #include <termio.h>
12: #include <fcntl.h>
13: #endif
14: #ifndef USG
15: #include <sgtty.h>
16: #endif
17: #ifdef BSD4_2
18: #include <sys/time.h>
19: #else
20: #include <time.h>
21: #endif
22:
23: #define MAXC 1000
24:
25: extern jmp_buf Sjbuf;
26: jmp_buf Cjbuf;
27: extern int errno, onesys;
28: extern char *sys_errlist[];
29: extern char MaxGrade, DefMaxGrade;
30:
31: /* Parity control during login procedure */
32: #define P_ZERO 0
33: #define P_ONE 1
34: #define P_EVEN 2
35: #define P_ODD 3
36:
37: #define ABORT -2
38:
39: char *AbortOn = NULL;
40: char par_tab[128]; /* must be power of two */
41: int linebaudrate; /* used for the sleep test in pk1.c */
42: int next_fd = -1; /* predicted fd to close interrupted opens */
43:
44: char *PCP = "PCP"; /* PC Pursuit device type */
45: /*
46: * catch alarm routine for "expect".
47: */
48: alarmtr()
49: {
50: signal(SIGALRM, alarmtr);
51: if (next_fd >= 0) {
52: if (close(next_fd))
53: logent("FAIL", "ACU LINE CLOSE");
54: next_fd = -1;
55: }
56: longjmp(Sjbuf, 1);
57: }
58:
59: /* This template is for seismo to call ihnp4
60: * the 3 lines marked ---> will be overwritten for the appropriate city
61: */
62: #define PCP_BAUD 3
63: #define PCP_PHONE 4
64: #define PCP_CITY 14
65: #define PCP_PASSWORD 16
66: #define PCP_RPHONE 20
67: #define NPCFIELDS 23
68:
69: static char *PCFlds[] = {
70: "PC-PURSUIT",
71: "Any",
72: "ACU",
73: "1200",
74: CNULL,
75: CNULL,
76: "P_ZERO", /* Telenet insists on zero parity */
77: "ABORT",
78: "BUSY", /* Abort on Busy Signal */
79: CNULL,
80: "\\d\\d\\r\\d\\r", /* Get telenet's attention */
81: "TERMINAL=~3-\r-TERM~3-\r-TERM~5", /* Terminal type ? */
82: "\\r",
83: "@", /* telenet's prompt */
84: "D/DCWAS/21,telenetloginstring", /* overwritten later */
85: "PASSWORD",
86: CNULL, /* telenet password */
87: "CONNECTED", /* We're now talking to a Hayes in the remote city */
88: "ATZ", /* Reset it */
89: "OK",
90: "ATDT6907171", /* overwritten */
91: "CONNECT",
92: "\\d\\r", /* We're in !*/
93: CNULL,
94: };
95:
96: static char PCP_brand[25];
97: int Dcf = -1;
98: char *Flds[MAXC/10];
99: char LineType[10];
100: extern int LocalOnly;
101:
102: /*
103: * place a telephone call to system and login, etc.
104: *
105: * return codes:
106: * CF_SYSTEM: don't know system
107: * CF_TIME: wrong time to call
108: * CF_DIAL: call failed
109: * CF_NODEV: no devices available to place call
110: * CF_LOGIN: login/password dialog failed
111: *
112: * >0 - file no. - connect ok
113: */
114: conn(system)
115: char *system;
116: {
117: int nf;
118: char info[MAXC], wkpre[NAMESIZE], file[NAMESIZE];
119: register FILE *fsys;
120: int fcode = 0;
121:
122: nf = 0;
123:
124: fsys = fopen(SYSFILE, "r");
125: if (fsys == NULL) {
126: syslog(LOG_ERR, "fopen(%s) failed: %m", SYSFILE);
127: cleanup(FAIL);
128: }
129:
130: DEBUG(4, "finds (%s) called\n", system);
131: keeplooking:
132: while((nf = finds(fsys, system, info, Flds)) > 0) {
133: strncpy(LineType, Flds[F_LINE], 10);
134: if (LocalOnly) {
135: if (strcmp("TCP", LineType)
136: && strcmp("DIR", LineType)
137: && strcmp("LOCAL", LineType) ) {
138: fcode = CF_TIME;
139: continue;
140: }
141: }
142: sprintf(wkpre, "%c.%.*s", CMDPRE, SYSNSIZE, Rmtname);
143: if (!onesys && MaxGrade != DefMaxGrade &&
144: !iswrk(file, "chk", Spool, wkpre)) {
145: fcode = CF_TIME;
146: continue;
147: }
148: /* For GTE's PC Pursuit */
149: if (snccmp(LineType, PCP) == SAME) {
150: FILE *dfp;
151: int status;
152: static struct Devices dev;
153:
154: dfp = fopen(DEVFILE, "r");
155: if (dfp == NULL) {
156: syslog(LOG_ERR, "fopen(%s) failed: %m",
157: DEVFILE);
158: cleanup(FAIL);
159: }
160: while ((status=rddev(dfp, &dev)) != FAIL
161: && strcmp(PCP, dev.D_type) != SAME)
162: ;
163: fclose(dfp);
164: if (status == FAIL)
165: continue;
166: if (mlock(PCP) == FAIL) {
167: fcode = CF_NODEV;
168: logent("DEVICE", "NO");
169: continue;
170: }
171: PCFlds[PCP_BAUD] = dev.D_class;
172: PCFlds[PCP_PHONE] = dev.D_calldev;
173: sprintf(PCFlds[PCP_CITY], "c d/%s%s,%s",
174: Flds[F_CLASS],
175: index(Flds[F_CLASS], '/') == NULL ? "/12" : "",
176: dev.D_arg[D_CHAT]);
177: PCFlds[PCP_PASSWORD] = dev.D_line;
178: strncpy(&PCFlds[PCP_RPHONE][4], Flds[F_PHONE], 7);
179: strncpy(PCP_brand, dev.D_brand, sizeof(PCP_brand));
180: if ((fcode = getto(PCFlds)) < 0) {
181: rmlock(PCP);
182: continue;
183: }
184: Dcf = fcode;
185: fcode = login(NPCFIELDS, PCFlds, Dcf);
186: if (fcode == SUCCESS)
187: break;
188: fcode = CF_DIAL;
189: rmlock(PCP);
190: /* end PC Pursuit */
191: } else if ((fcode = getto(Flds)) > 0) {
192: Dcf = fcode;
193: break;
194: }
195: }
196:
197: if (nf <= 0) {
198: fclose(fsys);
199: return fcode ? fcode : nf;
200: }
201:
202:
203: if (fcode >= 0) {
204: DEBUG(4, "login %s\n", "called");
205: setproctitle("login");
206: fcode = login(nf, Flds, Dcf); }
207: if (fcode < 0) {
208: clsacu();
209: if (fcode == ABORT) {
210: fcode = CF_DIAL;
211: goto keeplooking;
212: } else {
213: fclose(fsys);
214: return CF_LOGIN;
215: }
216: }
217: fclose(fsys);
218: fioclex(Dcf);
219: return Dcf;
220: }
221:
222: int nulldev();
223: int (*CU_end)() = nulldev;
224:
225: /*
226: * connect to remote machine
227: *
228: * return codes:
229: * >0 - file number - ok
230: * FAIL - failed
231: */
232: getto(flds)
233: register char *flds[];
234: {
235: register struct condev *cd;
236: int diropn();
237: char *line;
238:
239: DEBUG(4, "getto: call no. %s ", flds[F_PHONE]);
240: DEBUG(4, "for sys %s\n", flds[F_NAME]);
241:
242: if (snccmp(flds[F_LINE], "LOCAL") == SAME)
243: line = "ACU";
244: else
245: line = flds[F_LINE];
246: #ifdef DIALINOUT
247: if (snccmp(line, "ACU") != SAME)
248: reenable();
249: #endif DIALINOUT
250: CU_end = nulldev;
251: if (snccmp(line, PCP) == SAME) {
252: for(cd = condevs; cd->CU_meth != NULL; cd++) {
253: if (snccmp(PCP_brand, cd->CU_brand) == SAME) {
254: CU_end = cd->CU_clos;
255: return diropn(flds);
256: }
257: }
258: logent(PCP_brand, "UNSUPPORTED ACU TYPE");
259: } else {
260: for (cd = condevs; cd->CU_meth != NULL; cd++) {
261: if (snccmp(cd->CU_meth, line) == SAME) {
262: DEBUG(4, "Using %s to call\n", cd->CU_meth);
263: return (*(cd->CU_gen))(flds);
264: }
265: }
266: DEBUG(1, "Can't find %s, assuming DIR\n", flds[F_LINE]);
267: }
268: return diropn(flds); /* search failed, so use direct */
269: }
270:
271: /*
272: * close call unit
273: *
274: * return codes: none
275: */
276: clsacu()
277: {
278: /* make *sure* Dcf is no longer exclusive.
279: * Otherwise dual call-in/call-out modems could get stuck.
280: * Unfortunately, doing this here is not ideal, but it is the
281: * easiest place to put the call.
282: * Hopefully everyone honors the LCK protocol, of course
283: */
284: #ifdef TIOCNXCL
285: if (!IsTcpIp && Dcf >= 0 && ioctl(Dcf, TIOCNXCL, STBNULL) < 0)
286: DEBUG(5, "clsacu ioctl %s\n", sys_errlist[errno]);
287: #endif
288: if (setjmp(Sjbuf))
289: logent(Rmtname, "CLOSE TIMEOUT");
290: else {
291: signal(SIGALRM, alarmtr);
292: alarm(20);
293: (*(CU_end))(Dcf);
294: alarm(0);
295: }
296: if (close(Dcf) == 0) {
297: DEBUG(4, "fd %d NOT CLOSED by CU_clos\n", Dcf);
298: logent("clsacu", "NOT CLOSED by CU_clos");
299: }
300: Dcf = -1;
301: CU_end = nulldev;
302: }
303:
304: /*
305: * expand phone number for given prefix and number
306: */
307: exphone(in, out)
308: register char *in, *out;
309: {
310: FILE *fn;
311: char pre[MAXPH], npart[MAXPH], tpre[MAXPH], p[MAXPH];
312: char buf[BUFSIZ];
313: register char *s1;
314:
315: if (!isascii(*in) || !isalpha(*in)) {
316: strcpy(out, in);
317: return;
318: }
319:
320: s1=pre;
321: while (isascii(*in) && isalpha(*in))
322: *s1++ = *in++;
323: *s1 = '\0';
324: s1 = npart;
325: while (*in != '\0')
326: *s1++ = *in++;
327: *s1 = '\0';
328:
329: tpre[0] = '\0';
330: if ((fn = fopen(DIALFILE, "r")) == NULL)
331: DEBUG(2, "CAN'T OPEN %s\n", DIALFILE);
332: else {
333: while (cfgets(buf, BUFSIZ, fn)) {
334: if (sscanf(buf, "%s%s", p, tpre) != 2)
335: continue;
336: if (strcmp(p, pre) == SAME)
337: goto found;
338: tpre[0] = '\0';
339: }
340: DEBUG(2, "CAN'T FIND dialcodes prefix '%s'\n", pre);
341: found:;
342: fclose(fn);
343: }
344:
345: strcpy(out, tpre);
346: strcat(out, npart);
347: }
348:
349: /*
350: * read and decode a line from device file
351: *
352: * return code - FAIL at end-of file; 0 otherwise
353: */
354: rddev(fp, dev)
355: register struct Devices *dev;
356: FILE *fp;
357: {
358: register int na;
359:
360: if (!cfgets(dev->D_argbfr, sizeof(dev->D_argbfr), fp))
361: return FAIL;
362: na = getargs(dev->D_argbfr, dev->D_arg, 20);
363: if (na < 4) {
364: syslog(LOG_ERR, "%s: invalid device entry", dev->D_argbfr);
365: cleanup(FAIL);
366: }
367: if (na == 4) {
368: dev->D_brand = "";
369: na++;
370: }
371: dev->D_speed = atoi(fdig(dev->D_class));
372: dev->D_numargs = na;
373: return 0;
374: }
375:
376: /*
377: * set system attribute vector
378: *
379: * return codes:
380: * >0 - number of arguments in vector - succeeded
381: * CF_SYSTEM - system name not found
382: * CF_TIME - wrong time to call
383: */
384: finds(fsys, sysnam, info, flds)
385: char *sysnam, info[], *flds[];
386: FILE *fsys;
387: {
388: int na;
389: int fcode = 0;
390:
391: /* format of fields
392: * 0 name;
393: * 1 time
394: * 2 acu/hardwired
395: * 3 speed
396: * etc
397: */
398: while (cfgets(info, MAXC, fsys) != NULL) {
399: na = getargs(info, flds, MAXC/10);
400: if (strncmp(sysnam, flds[F_NAME], MAXBASENAME) != SAME)
401: continue;
402: if (ifdate(flds[F_TIME]) != FAIL)
403: /* found a good entry */
404: return na;
405: DEBUG(2, "Wrong time ('%s') to call\n", flds[F_TIME]);
406: fcode = CF_TIME;
407: }
408: return fcode ? fcode : CF_SYSTEM;
409: }
410:
411: /*
412: * do login conversation
413: *
414: * return codes: SUCCESS | FAIL
415: */
416: login(nf, flds, fn)
417: register char *flds[];
418: int nf, fn;
419: {
420: register char *want, *altern;
421: int k, ok;
422:
423: if (nf < 4) {
424: syslog(LOG_ERR, "Too few log fields: %d", nf);
425: cleanup(FAIL);
426: }
427: if (setjmp(Cjbuf))
428: return FAIL;
429: AbortOn = NULL;
430: for (k = F_LOGIN; k < nf; k += 2) {
431: want = flds[k];
432: if (want == NULL)
433: want = "";
434: ok = FAIL;
435: while (ok != SUCCESS) {
436: altern = index(want, '-');
437: if (altern != NULL)
438: *altern++ = '\0';
439: if (strcmp(want, "ABORT") == 0) {
440: AbortOn = flds[k+1];
441: DEBUG(4, "ABORT ON: %s\n", AbortOn);
442: goto nextfield;
443: }
444: DEBUG(4, "wanted \"%s\"\n", want);
445: ok = expect(want, fn);
446: DEBUG(4, "got: %s\n", ok ? "?" : "that");
447: if (ok == FAIL) {
448: if (altern == NULL) {
449: logent("LOGIN", _FAILED);
450: return FAIL;
451: }
452: want = index(altern, '-');
453: if (want != NULL)
454: *want++ = '\0';
455: sendthem(altern, fn);
456: } else
457: if (ok == ABORT) {
458: char sbuf[MAXFULLNAME];
459: sprintf(sbuf, "LOGIN ABORTED on \"%s\"", AbortOn);
460: logent(sbuf, _FAILED);
461: return ABORT;
462: }
463: }
464: sleep(1);
465: if (k+1 < nf)
466: sendthem(flds[k+1], fn);
467: nextfield: ;
468: }
469: return SUCCESS;
470: }
471:
472:
473: /* conditional table generation to support odd speeds */
474: struct sg_spds {int sp_val, sp_name;} spds[] = {
475: #ifdef B50
476: { 50, B50},
477: #endif
478: #ifdef B75
479: { 75, B75},
480: #endif
481: #ifdef B110
482: { 110, B110},
483: #endif
484: #ifdef B150
485: { 150, B150},
486: #endif
487: #ifdef B200
488: { 200, B200},
489: #endif
490: #ifdef B300
491: { 300, B300},
492: #endif
493: #ifdef B600
494: {600, B600},
495: #endif
496: #ifdef B1200
497: {1200, B1200},
498: #endif
499: #ifdef B1800
500: {1800, B1800},
501: #endif
502: #ifdef B2000
503: {2000, B2000},
504: #endif
505: #ifdef B2400
506: {2400, B2400},
507: #endif
508: #ifdef B3600
509: {3600, B3600},
510: #endif
511: #ifdef B4800
512: {4800, B4800},
513: #endif
514: #ifdef B7200
515: {7200, B7200},
516: #endif
517: #ifdef B9600
518: {9600, B9600},
519: #endif
520: #ifdef B19200
521: {19200, B19200},
522: #endif
523: #ifdef EXTA
524: {19200, EXTA},
525: #endif
526: {0, 0}
527: };
528:
529: /*
530: * set speed/echo/mode...
531: *
532: * return codes: none
533: */
534: fixline(tty, spwant)
535: int tty, spwant;
536: {
537: #ifdef USG
538: struct termio ttbuf;
539: #else !USG
540: struct sgttyb ttbuf;
541: #endif !USG
542: register struct sg_spds *ps;
543: int speed = -1;
544:
545: for (ps = spds; ps->sp_val; ps++)
546: if (ps->sp_val == spwant)
547: speed = ps->sp_name;
548: if (speed < 0) {
549: syslog(LOG_ERR, "unrecognized speed: %d", speed);
550: cleanup(FAIL);
551: }
552: #ifdef USG
553: if (ioctl(tty, TCGETA, &ttbuf) < 0)
554: return FAIL;
555: /* ttbuf.sg_flags = (ANYP|RAW);
556: ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed; */
557: ttbuf.c_iflag = (ushort)0;
558: ttbuf.c_oflag = (ushort)0;
559: ttbuf.c_cflag = (speed|CS8|HUPCL|CREAD);
560: ttbuf.c_lflag = (ushort)0;
561: ttbuf.c_cc[VMIN] = 6;
562: ttbuf.c_cc[VTIME] = 1;
563: if (ioctl(tty, TCSETA, &ttbuf) < 0)
564: return FAIL;
565: #else !USG
566: if (ioctl(tty, TIOCGETP, &ttbuf) < 0)
567: return FAIL;
568: ttbuf.sg_flags = (ANYP|RAW);
569: ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
570: if (ioctl(tty, TIOCSETP, &ttbuf) < 0)
571: return FAIL;
572: #endif
573: #ifndef USG
574: if (ioctl(tty, TIOCHPCL, STBNULL) < 0)
575: return FAIL;
576: if (ioctl(tty, TIOCEXCL, STBNULL) < 0)
577: return FAIL;
578: #endif
579: linebaudrate = spwant;
580: return SUCCESS;
581: }
582:
583: #define MR 100
584:
585: /*
586: * look for expected string
587: *
588: * return codes:
589: * 0 - found
590: * FAIL - lost line or too many characters read
591: * some character - timed out
592: */
593: expect(str, fn)
594: register char *str;
595: int fn;
596: {
597: char rdvec[MR];
598: register char *rp = rdvec, *strptr;
599: int kr, cnt_char;
600: char nextch;
601: int timo = MAXMSGTIME;
602:
603: if (*str == '\0' || strcmp(str, "\"\"") == SAME)
604: return SUCCESS;
605: /* Cleanup str, convert \0xx strings to one char */
606: for (strptr = str; *strptr; strptr++) {
607: if (*strptr == '\\')
608: switch(*++strptr) {
609: case 's':
610: DEBUG(5, "BLANK\n", CNULL);
611: strptr--;
612: *strptr = ' ';
613: strcpy(&strptr[1], &strptr[4]);
614: break;
615: default:
616: strptr--; /* back up to backslash */
617: sscanf(strptr + 1,"%o", &cnt_char);
618: DEBUG(6, "BACKSLASHED %02xH\n", cnt_char);
619: *strptr = (char) (cnt_char);
620: strcpy(&strptr[1], &strptr[4]);
621: }
622: }
623:
624: strptr = index(str, '~');
625: if (strptr != NULL) {
626: *strptr++ = '\0';
627: timo = atoi(strptr);
628: if (timo <= 0)
629: timo = MAXMSGTIME;
630: }
631:
632: if (setjmp(Sjbuf))
633: return FAIL;
634: signal(SIGALRM, alarmtr);
635: alarm(timo);
636: *rp = 0;
637: while (notin(str, rdvec)) {
638: int c;
639: if(AbortOn != NULL && !notin(AbortOn, rdvec)) {
640: DEBUG(1, "Call aborted on '%s'\n", AbortOn);
641: alarm(0);
642: return ABORT;
643: }
644: kr = read(fn, &nextch, 1);
645: if (kr <= 0) {
646: alarm(0);
647: DEBUG(4, "lost line kr - %d\n, ", kr);
648: logent("LOGIN", "LOST LINE");
649: return FAIL;
650: }
651: c = nextch & 0177;
652: if (c == '\0')
653: continue;
654: DEBUG(4, (isprint(c) || isspace(c)) ? "%c" : "\\%03o", c);
655: *rp++ = c;
656: if (rp >= rdvec + MR) {
657: register char *p;
658: for (p = rdvec+MR/2; p < rp; p++)
659: *(p-MR/2) = *p;
660: rp -= MR/2;
661: }
662: *rp = '\0';
663: }
664: alarm(0);
665: return SUCCESS;
666: }
667:
668:
669: /*
670: * Determine next file descriptor that would be allocated.
671: * This permits later closing of a file whose open was interrupted.
672: * It is a UNIX kernel problem, but it has to be handled.
673: * unc!smb (Steve Bellovin) probably first discovered it.
674: */
675: getnextfd()
676: {
677: close(next_fd = open("/", 0));
678: }
679:
680: /*
681: * send line of login sequence
682: *
683: * return codes: none
684: */
685: sendthem(str, fn)
686: register char *str;
687: int fn;
688: {
689: register char *strptr;
690: int i, n, cr = 1;
691: register char c;
692: static int p_init = 0;
693:
694: DEBUG(5, "send \"%s\"\n", str);
695:
696: if (!p_init) {
697: p_init++;
698: bld_partab(P_ZERO);
699: }
700:
701: if (prefix("BREAK", str)) {
702: sscanf(&str[5], "%1d", &i);
703: if (i <= 0 || i > 10)
704: i = 3;
705: /* send break */
706: genbrk(fn, i);
707: return;
708: }
709:
710: if (prefix("PAUSE", str)) {
711: sscanf(&str[5], "%1d", &i);
712: if (i <= 0 || i > 10)
713: i = 3;
714: /* pause for a while */
715: sleep((unsigned)i);
716: return;
717: }
718:
719: if (strcmp(str, "EOT") == SAME) {
720: p_chwrite(fn, '\04');
721: return;
722: }
723:
724: /* Send a '\n' */
725: if (strcmp(str, "LF") == SAME) {
726: p_chwrite(fn, '\n');
727: return;
728: }
729:
730: /* Send a '\r' */
731: if (strcmp(str, "CR") == SAME) {
732: p_chwrite(fn, '\r');
733: return;
734: }
735:
736: /* Set parity as needed */
737: if (strcmp(str, "P_ZERO") == SAME) {
738: bld_partab(P_ZERO);
739: return;
740: }
741: if (strcmp(str, "P_ONE") == SAME) {
742: bld_partab(P_ONE);
743: return;
744: }
745: if (strcmp(str, "P_EVEN") == SAME) {
746: bld_partab(P_EVEN);
747: return;
748: }
749: if (strcmp(str, "P_ODD") == SAME) {
750: bld_partab(P_ODD);
751: return;
752: }
753:
754: /* If "", just send '\r' */
755: if (strcmp(str, "\"\"") == SAME) {
756: p_chwrite(fn, '\r');
757: return;
758: }
759:
760: strptr = str;
761: while ((c = *strptr++) != '\0') {
762: if (c == '\\') {
763: switch(*strptr++) {
764: case '\0':
765: DEBUG(5, "TRAILING BACKSLASH IGNORED\n", CNULL);
766: --strptr;
767: continue;
768: case 's':
769: DEBUG(5, "BLANK\n", CNULL);
770: c = ' ';
771: break;
772: case 'd':
773: DEBUG(5, "DELAY\n", CNULL);
774: sleep(1);
775: continue;
776: case 'n':
777: DEBUG(5, "NEW LINE\n", CNULL);
778: c = '\n';
779: break;
780: case 'r':
781: DEBUG(5, "RETURN\n", CNULL);
782: c = '\r';
783: break;
784: case 'b':
785: if (isdigit(*strptr)) {
786: i = (*strptr++ - '0');
787: if (i <= 0 || i > 10)
788: i = 3;
789: } else
790: i = 3;
791: /* send break */
792: genbrk(fn, i);
793: if (*strptr == '\0')
794: cr = 0;
795: continue;
796: case 'c':
797: if (*strptr == '\0') {
798: DEBUG(5, "NO CR\n", CNULL);
799: cr = 0;
800: } else
801: DEBUG(5, "NO CR - IGNORED NOT EOL\n", CNULL);
802: continue;
803: #define isoctal(x) ((x >= '0') && (x <= '7'))
804: default:
805: if (isoctal(strptr[-1])) {
806: i = 0;
807: n = 0;
808: --strptr;
809: while (isoctal(*strptr) && ++n <= 3)
810: i = i * 8 + (*strptr++ - '0');
811: DEBUG(5, "\\%o\n", i);
812: p_chwrite(fn, (char)i);
813: continue;
814: }
815: }
816: }
817: p_chwrite(fn, c);
818: }
819:
820: if (cr)
821: p_chwrite(fn, '\r');
822: return;
823: }
824:
825: p_chwrite(fd, c)
826: int fd;
827: char c;
828: {
829: c = par_tab[c&0177];
830: if (write(fd, &c, 1) != 1) {
831: logent(sys_errlist[errno], "BAD WRITE");
832: longjmp(Cjbuf, 2);
833: }
834: }
835:
836: /*
837: * generate parity table for use by p_chwrite.
838: */
839: bld_partab(type)
840: int type;
841: {
842: register int i, j, n;
843:
844: for (i = 0; i < sizeof(par_tab); i++) {
845: n = 0;
846: for (j = i&(sizeof(par_tab)-1); j; j = (j-1)&j)
847: n++;
848: par_tab[i] = i;
849: if (type == P_ONE
850: || (type == P_EVEN && (n&01) != 0)
851: || (type == P_ODD && (n&01) == 0))
852: par_tab[i] |= sizeof(par_tab);
853: }
854: }
855:
856: /*
857: * check for occurrence of substring "sh"
858: *
859: * return codes:
860: * 0 - found the string
861: * 1 - not in the string
862: */
863: notin(sh, lg)
864: register char *sh, *lg;
865: {
866: while (*lg != '\0') {
867: if (wprefix(sh, lg))
868: return 0;
869: else
870: lg++;
871: }
872: return 1;
873: }
874:
875: /*
876: * Allow multiple date specifications separated by ','.
877: */
878: ifdate(p)
879: register char *p;
880: {
881: register char *np;
882: register int ret, g;
883: int rtime, i;
884:
885: /* pick up retry time for failures */
886: /* global variable Retrytime is set here */
887: if ((np = index(p, ';')) == NULL) {
888: Retrytime = RETRYTIME;
889: } else {
890: i = sscanf(np+1, "%d", &rtime);
891: if (i < 1 || rtime < 0)
892: rtime = 5;
893: Retrytime = rtime * 60;
894: }
895:
896: ret = FAIL;
897: MaxGrade = '\0';
898: do {
899: np = strpbrk(p, ",|"); /* prefer , but allow | for compat */
900: if (np)
901: *np = '\0';
902: g = ifadate(p);
903: DEBUG(11,"ifadate returns %o\n", g);
904: if (g != FAIL) {
905: ret = SUCCESS;
906: if (g > MaxGrade)
907: MaxGrade = g;
908: }
909: if (np)
910: *np = ',';
911: p = np + 1;
912: } while (np);
913: if (MaxGrade == '\0')
914: MaxGrade = DefMaxGrade;
915: return ret;
916: }
917:
918: /*
919: * this routine will check a string (string)
920: * like "MoTu0800-1730" to see if the present
921: * time is within the given limits.
922: * SIDE EFFECT - Retrytime is set
923: *
924: * return codes:
925: * 0 - not within limits
926: * 1 - within limits
927: */
928:
929: ifadate(string)
930: char *string;
931: {
932: static char *days[]={
933: "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
934: };
935: time_t clock;
936: register char *s = string;
937: int i, tl, th, tn, dayok=0;
938: struct tm *localtime();
939: struct tm *tp;
940: char *p, MGrade;
941:
942: if ((p = index(s, '/')) == NULL)
943: MGrade = DefMaxGrade;
944: else
945: MGrade = p[1];
946:
947: time(&clock);
948: tp = localtime(&clock);
949: while (isascii(*s) && isalpha(*s)) {
950: for (i = 0; days[i]; i++) {
951: if (prefix(days[i], s))
952: if (tp->tm_wday == i)
953: dayok = 1;
954: }
955:
956: if (prefix("Wk", s))
957: if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
958: dayok = 1;
959: if (prefix("Any", s))
960: dayok = 1;
961: if (prefix("Evening", s)) {
962: /* Sat or Sun */
963: if (tp->tm_wday == 6 || tp->tm_wday == 0
964: || tp->tm_hour >= 17 || tp->tm_hour < 8)
965: dayok = 1;
966: }
967: if (prefix("Night", s)) {
968: if (tp->tm_wday == 6 /* Sat */
969: || tp->tm_hour >= 23 || tp->tm_hour < 8
970: /* Sunday before 5pm */
971: || (tp->tm_wday == 0 && tp->tm_hour < 17))
972: dayok = 1;
973: }
974: if (prefix("NonPeak", s)) { /* For Tymnet and PC Pursuit */
975: /* Sat or Sun */
976: if (tp->tm_wday == 6 || tp->tm_wday == 0
977: || tp->tm_hour >= 18 || tp->tm_hour < 7)
978: dayok = 1;
979: }
980: s++;
981: }
982:
983: if (dayok == 0 && s != string)
984: return FAIL;
985: i = sscanf(s, "%d-%d", &tl, &th);
986: if (i < 2)
987: return MGrade;
988: tn = tp->tm_hour * 100 + tp->tm_min;
989: if (th < tl) { /* crosses midnight */
990: if (tl <= tn || tn < th)
991: return MGrade;
992: } else {
993: if (tl <= tn && tn < th)
994: return MGrade;
995: }
996: return FAIL;
997: }
998:
999: /*
1000: * find first digit in string
1001: *
1002: * return - pointer to first digit in string or end of string
1003: */
1004: char *
1005: fdig(cp)
1006: register char *cp;
1007: {
1008: register char *c;
1009:
1010: for (c = cp; *c; c++)
1011: if (*c >= '0' && *c <= '9')
1012: break;
1013: return c;
1014: }
1015:
1016: /*
1017: * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
1018: * Strings are compared as if they contain all capital letters.
1019: */
1020: snccmp(s1, s2)
1021: register char *s1, *s2;
1022: {
1023: char c1, c2;
1024:
1025: if (islower(*s1))
1026: c1 = toupper(*s1);
1027: else
1028: c1 = *s1;
1029: if (islower(*s2))
1030: c2 = toupper(*s2);
1031: else
1032: c2 = *s2;
1033:
1034: while (c1 == c2) {
1035: if (*s1++ == '\0')
1036: return 0;
1037: s2++;
1038: if (islower(*s1))
1039: c1 = toupper(*s1);
1040: else
1041: c1 = *s1;
1042: if (islower(*s2))
1043: c2 = toupper(*s2);
1044: else
1045: c2 = *s2;
1046: }
1047: return c1 - c2;
1048: }
1049:
1050: /*
1051: * Compare strings: s1>s2: >0 s1==s2: 0 s1<s2: <0
1052: * Strings are compared as if they contain all capital letters.
1053: */
1054: sncncmp(s1, s2, n)
1055: register char *s1, *s2;
1056: register int n;
1057: {
1058: char c1, c2;
1059:
1060: if (islower(*s1))
1061: c1 = toupper(*s1);
1062: else
1063: c1 = *s1;
1064: if (islower(*s2))
1065: c2 = toupper(*s2);
1066: else
1067: c2 = *s2;
1068:
1069: while ( --n >= 0 && c1 == c2) {
1070: if (*s1++ == '\0')
1071: return 0;
1072: s2++;
1073: if (islower(*s1))
1074: c1 = toupper(*s1);
1075: else
1076: c1 = *s1;
1077: if (islower(*s2))
1078: c2 = toupper(*s2);
1079: else
1080: c2 = *s2;
1081: }
1082: return n<0 ? 0 : (c1 - c2);
1083: }
1084: /*
1085: * do chat script
1086: * occurs after local port is opened,
1087: * before 'dialing' the other machine.
1088: */
1089: dochat(dev, flds, fd)
1090: register struct Devices *dev;
1091: char *flds[];
1092: int fd;
1093: {
1094: register int i;
1095: register char *p;
1096: char bfr[sizeof(dev->D_argbfr)];
1097:
1098: if (dev->D_numargs <= 5)
1099: return(0);
1100: DEBUG(4, "dochat called %d\n", dev->D_numargs);
1101: for (i = 0; i < dev->D_numargs-5; i++) {
1102: sprintf(bfr, dev->D_arg[D_CHAT+i], flds[F_PHONE]);
1103: if (strcmp(bfr, dev->D_arg[D_CHAT+i])) {
1104: p = malloc((unsigned)strlen(bfr)+1);
1105: if (p != NULL) {
1106: strcpy(p, bfr);
1107: dev->D_arg[D_CHAT+i] = p;
1108: }
1109: }
1110: }
1111: /* following is a kludge because login() arglist is a kludge */
1112: i = login(dev->D_numargs, &dev->D_arg[D_CHAT-5], fd);
1113: /*
1114: * If login() last did a sendthem(), must pause so things can settle.
1115: * But don't bother if chat failed.
1116: */
1117: if (i == 0 && (dev->D_numargs&01))
1118: sleep(2);
1119: return(i);
1120: }
1121:
1122: /*
1123: * fix kill/echo/raw on line
1124: *
1125: * return codes: none
1126: */
1127: fixmode(tty)
1128: register int tty;
1129: {
1130: #ifdef USG
1131: struct termio ttbuf;
1132: #else !USG
1133: struct sgttyb ttbuf;
1134: #endif !USG
1135: register struct sg_spds *ps;
1136: int speed;
1137:
1138: if (IsTcpIp)
1139: return;
1140: #ifdef USG
1141: ioctl(tty, TCGETA, &ttbuf);
1142: ttbuf.c_iflag = ttbuf.c_oflag = ttbuf.c_lflag = (ushort)0;
1143: speed = ttbuf.c_cflag &= (CBAUD);
1144: ttbuf.c_cflag |= (CS8|CREAD);
1145: ttbuf.c_cc[VMIN] = 6;
1146: ttbuf.c_cc[VTIME] = 1;
1147: ioctl(tty, TCSETA, &ttbuf);
1148: #else !USG
1149: ioctl(tty, TIOCGETP, &ttbuf);
1150: ttbuf.sg_flags = (ANYP | RAW);
1151: ioctl(tty, TIOCSETP, &ttbuf);
1152: speed = ttbuf.sg_ispeed;
1153: ioctl(tty, TIOCEXCL, STBNULL);
1154: #endif !USG
1155:
1156: for (ps = spds; ps->sp_val; ps++)
1157: if (ps->sp_name == speed) {
1158: linebaudrate = ps->sp_val;
1159: DEBUG(9,"Incoming baudrate is %d\n", linebaudrate);
1160: return;
1161: }
1162: if (linebaudrate < 0) {
1163: syslog(LOG_ERR, "unrecognized speed: %d", linebaudrate);
1164: cleanup(FAIL);
1165: }
1166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.