|
|
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.