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