|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)tip.c 4.16 (Berkeley) 6/28/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * tip - UNIX link to other systems ! 7: * tip [-v] [-speed] system-name ! 8: * or ! 9: * cu phone-number [-s speed] [-l line] [-a acu] ! 10: */ ! 11: #include "tip.h" ! 12: ! 13: /* ! 14: * Baud rate mapping table ! 15: */ ! 16: int bauds[] = { ! 17: 0, 50, 75, 110, 134, 150, 200, 300, 600, ! 18: 1200, 1800, 2400, 4800, 9600, 19200, -1 ! 19: }; ! 20: ! 21: int disc = OTTYDISC; /* tip normally runs this way */ ! 22: int intprompt(); ! 23: int timeout(); ! 24: int cleanup(); ! 25: char *sname(); ! 26: extern char *sprintf(); ! 27: ! 28: main(argc, argv) ! 29: char *argv[]; ! 30: { ! 31: char *system = NOSTR; ! 32: register int i; ! 33: register char *p; ! 34: char sbuf[12]; ! 35: ! 36: if (equal(sname(argv[0]), "cu")) { ! 37: cumain(argc, argv); ! 38: cumode = 1; ! 39: goto cucommon; ! 40: } ! 41: ! 42: if (argc > 4) { ! 43: fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); ! 44: exit(1); ! 45: } ! 46: if (!isatty(0)) { ! 47: fprintf(stderr, "tip: must be interactive\n"); ! 48: exit(1); ! 49: } ! 50: ! 51: for (; argc > 1; argv++, argc--) { ! 52: if (argv[1][0] != '-') ! 53: system = argv[1]; ! 54: else switch (argv[1][1]) { ! 55: ! 56: case 'v': ! 57: vflag++; ! 58: break; ! 59: ! 60: case '0': case '1': case '2': case '3': case '4': ! 61: case '5': case '6': case '7': case '8': case '9': ! 62: BR = atoi(&argv[1][1]); ! 63: break; ! 64: ! 65: default: ! 66: fprintf(stderr, "tip: %s, unknown option\n", argv[1]); ! 67: break; ! 68: } ! 69: } ! 70: ! 71: if (system == NOSTR) ! 72: goto notnumber; ! 73: for (p = system; *p; p++) ! 74: if (isalpha(*p)) ! 75: goto notnumber; ! 76: PN = system; /* system name is really a phone number */ ! 77: system = sprintf(sbuf, "tip%d", BR); ! 78: ! 79: notnumber: ! 80: signal(SIGINT, cleanup); ! 81: signal(SIGQUIT, cleanup); ! 82: signal(SIGHUP, cleanup); ! 83: signal(SIGTERM, cleanup); ! 84: ! 85: if ((i = hunt(system)) == 0) { ! 86: printf("all ports busy\n"); ! 87: exit(3); ! 88: } ! 89: if (i == -1) { ! 90: printf("link down\n"); ! 91: delock(uucplock); ! 92: exit(3); ! 93: } ! 94: setbuf(stdout, NULL); ! 95: loginit(); ! 96: /* ! 97: * Now that we have the logfile and the ACU open ! 98: * return to the real uid and gid. These things will ! 99: * be closed on exit. Note that we can't run as root, ! 100: * because locking mechanism on the tty and the accounting ! 101: * will be bypassed. ! 102: */ ! 103: setgid(getgid()); ! 104: setuid(getuid()); ! 105: ! 106: /* ! 107: * Kludge, their's no easy way to get the initialization ! 108: * in the right order, so force it here ! 109: */ ! 110: if ((PH = getenv("PHONES")) == NOSTR) ! 111: PH = "/etc/phones"; ! 112: vinit(); /* init variables */ ! 113: setparity("even"); /* set the parity table */ ! 114: if ((i = speed(number(value(BAUDRATE)))) == NULL) { ! 115: printf("tip: bad baud rate %d\n", number(value(BAUDRATE))); ! 116: delock(uucplock); ! 117: exit(3); ! 118: } ! 119: ! 120: /* ! 121: * Hardwired connections require the ! 122: * line speed set before they make any transmissions ! 123: * (this is particularly true of things like a DF03-AC) ! 124: */ ! 125: if (HW) ! 126: ttysetup(i); ! 127: if (p = connect()) { ! 128: printf("\07%s\n[EOT]\n", p); ! 129: delock(uucplock); ! 130: exit(1); ! 131: } ! 132: if (!HW) ! 133: ttysetup(i); ! 134: cucommon: ! 135: /* ! 136: * From here down the code is shared with ! 137: * the "cu" version of tip. ! 138: */ ! 139: ioctl(0, TIOCGETP, (char *)&defarg); ! 140: ioctl(0, TIOCGETC, (char *)&defchars); ! 141: ioctl(0, TIOCGLTC, (char *)&deflchars); ! 142: ioctl(0, TIOCGETD, (char *)&odisc); ! 143: arg = defarg; ! 144: arg.sg_flags = ANYP | CBREAK; ! 145: tchars = defchars; ! 146: tchars.t_intrc = tchars.t_quitc = -1; ! 147: ltchars = deflchars; ! 148: ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc ! 149: = ltchars.t_lnextc = -1; ! 150: raw(); ! 151: ! 152: pipe(fildes); pipe(repdes); ! 153: signal(SIGALRM, timeout); ! 154: ! 155: /* ! 156: * Everything's set up now: ! 157: * connection established (hardwired or diaulup) ! 158: * line conditioned (baud rate, mode, etc.) ! 159: * internal data structures (variables) ! 160: * so, fork one process for local side and one for remote. ! 161: */ ! 162: printf(cumode ? "Connected\r\n" : "\07connected\r\n"); ! 163: if (pid = fork()) ! 164: tipin(); ! 165: else ! 166: tipout(); ! 167: /*NOTREACHED*/ ! 168: } ! 169: ! 170: cleanup() ! 171: { ! 172: ! 173: delock(uucplock); ! 174: if (odisc) ! 175: ioctl(0, TIOCSETD, (char *)&odisc); ! 176: exit(0); ! 177: } ! 178: ! 179: /* ! 180: * put the controlling keyboard into raw mode ! 181: */ ! 182: raw() ! 183: { ! 184: ! 185: ioctl(0, TIOCSETP, &arg); ! 186: ioctl(0, TIOCSETC, &tchars); ! 187: ioctl(0, TIOCSLTC, <chars); ! 188: ioctl(0, TIOCSETD, (char *)&disc); ! 189: } ! 190: ! 191: ! 192: /* ! 193: * return keyboard to normal mode ! 194: */ ! 195: unraw() ! 196: { ! 197: ! 198: ioctl(0, TIOCSETD, (char *)&odisc); ! 199: ioctl(0, TIOCSETP, (char *)&defarg); ! 200: ioctl(0, TIOCSETC, (char *)&defchars); ! 201: ioctl(0, TIOCSLTC, (char *)&deflchars); ! 202: } ! 203: ! 204: static jmp_buf promptbuf; ! 205: ! 206: /* ! 207: * Print string ``s'', then read a string ! 208: * in from the terminal. Handles signals & allows use of ! 209: * normal erase and kill characters. ! 210: */ ! 211: prompt(s, p) ! 212: char *s; ! 213: register char *p; ! 214: { ! 215: register char *b = p; ! 216: int (*oint)(), (*oquit)(); ! 217: ! 218: stoprompt = 0; ! 219: oint = signal(SIGINT, intprompt); ! 220: oint = signal(SIGQUIT, SIG_IGN); ! 221: unraw(); ! 222: printf("%s", s); ! 223: if (setjmp(promptbuf) == 0) ! 224: while ((*p = getchar()) != EOF && *p != '\n') ! 225: p++; ! 226: *p = '\0'; ! 227: ! 228: raw(); ! 229: signal(SIGINT, oint); ! 230: signal(SIGQUIT, oint); ! 231: return (stoprompt || p == b); ! 232: } ! 233: ! 234: /* ! 235: * Interrupt service routine during prompting ! 236: */ ! 237: intprompt() ! 238: { ! 239: ! 240: signal(SIGINT, SIG_IGN); ! 241: stoprompt = 1; ! 242: printf("\r\n"); ! 243: longjmp(promptbuf, 1); ! 244: } ! 245: ! 246: /* ! 247: * ****TIPIN TIPIN**** ! 248: */ ! 249: tipin() ! 250: { ! 251: char gch, bol = 1; ! 252: ! 253: /* ! 254: * Kinda klugey here... ! 255: * check for scripting being turned on from the .tiprc file, ! 256: * but be careful about just using setscript(), as we may ! 257: * send a SIGEMT before tipout has a chance to set up catching ! 258: * it; so wait a second, then setscript() ! 259: */ ! 260: if (boolean(value(SCRIPT))) { ! 261: sleep(1); ! 262: setscript(); ! 263: } ! 264: ! 265: while (1) { ! 266: gch = getchar()&0177; ! 267: if ((gch == character(value(ESCAPE))) && bol) { ! 268: if (!(gch = escape())) ! 269: continue; ! 270: } else if (!cumode && gch == character(value(RAISECHAR))) { ! 271: boolean(value(RAISE)) = !boolean(value(RAISE)); ! 272: continue; ! 273: } else if (gch == '\r') { ! 274: bol = 1; ! 275: pwrite(FD, &gch, 1); ! 276: if (boolean(value(HALFDUPLEX))) ! 277: printf("\r\n"); ! 278: continue; ! 279: } else if (!cumode && gch == character(value(FORCE))) ! 280: gch = getchar()&0177; ! 281: bol = any(gch, value(EOL)); ! 282: if (boolean(value(RAISE)) && islower(gch)) ! 283: gch = toupper(gch); ! 284: pwrite(FD, &gch, 1); ! 285: if (boolean(value(HALFDUPLEX))) ! 286: printf("%c", gch); ! 287: } ! 288: } ! 289: ! 290: /* ! 291: * Escape handler -- ! 292: * called on recognition of ``escapec'' at the beginning of a line ! 293: */ ! 294: escape() ! 295: { ! 296: register char gch; ! 297: register esctable_t *p; ! 298: char c = character(value(ESCAPE)); ! 299: extern esctable_t etable[]; ! 300: ! 301: gch = (getchar()&0177); ! 302: for (p = etable; p->e_char; p++) ! 303: if (p->e_char == gch) { ! 304: if ((p->e_flags&PRIV) && getuid()) ! 305: continue; ! 306: printf("%s", ctrl(c)); ! 307: (*p->e_func)(gch); ! 308: return (0); ! 309: } ! 310: /* ESCAPE ESCAPE forces ESCAPE */ ! 311: if (c != gch) ! 312: pwrite(FD, &c, 1); ! 313: return (gch); ! 314: } ! 315: ! 316: speed(n) ! 317: int n; ! 318: { ! 319: register int *p; ! 320: ! 321: for (p = bauds; *p != -1; p++) ! 322: if (*p == n) ! 323: return (p - bauds); ! 324: return (NULL); ! 325: } ! 326: ! 327: any(c, p) ! 328: register char c, *p; ! 329: { ! 330: while (p && *p) ! 331: if (*p++ == c) ! 332: return (1); ! 333: return (0); ! 334: } ! 335: ! 336: size(s) ! 337: register char *s; ! 338: { ! 339: register int i = 0; ! 340: ! 341: while (s && *s++) ! 342: i++; ! 343: return (i); ! 344: } ! 345: ! 346: char * ! 347: interp(s) ! 348: register char *s; ! 349: { ! 350: static char buf[256]; ! 351: register char *p = buf, c, *q; ! 352: ! 353: while (c = *s++) { ! 354: for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) ! 355: if (*q++ == c) { ! 356: *p++ = '\\'; *p++ = *q; ! 357: goto next; ! 358: } ! 359: if (c < 040) { ! 360: *p++ = '^'; *p++ = c + 'A'-1; ! 361: } else if (c == 0177) { ! 362: *p++ = '^'; *p++ = '?'; ! 363: } else ! 364: *p++ = c; ! 365: next: ! 366: ; ! 367: } ! 368: *p = '\0'; ! 369: return (buf); ! 370: } ! 371: ! 372: char * ! 373: ctrl(c) ! 374: char c; ! 375: { ! 376: static char s[3]; ! 377: ! 378: if (c < 040 || c == 0177) { ! 379: s[0] = '^'; ! 380: s[1] = c == 0177 ? '?' : c+'A'-1; ! 381: s[2] = '\0'; ! 382: } else { ! 383: s[0] = c; ! 384: s[1] = '\0'; ! 385: } ! 386: return (s); ! 387: } ! 388: ! 389: /* ! 390: * Help command ! 391: */ ! 392: help(c) ! 393: char c; ! 394: { ! 395: register esctable_t *p; ! 396: extern esctable_t etable[]; ! 397: ! 398: printf("%c\r\n", c); ! 399: for (p = etable; p->e_char; p++) { ! 400: if ((p->e_flags&PRIV) && getuid()) ! 401: continue; ! 402: printf("%2s", ctrl(character(value(ESCAPE)))); ! 403: printf("%-2s %c %s\r\n", ctrl(p->e_char), ! 404: p->e_flags&EXP ? '*': ' ', p->e_help); ! 405: } ! 406: } ! 407: ! 408: /* ! 409: * Set up the "remote" tty's state ! 410: */ ! 411: ttysetup(speed) ! 412: int speed; ! 413: { ! 414: unsigned bits = LDECCTQ; ! 415: ! 416: arg.sg_ispeed = arg.sg_ospeed = speed; ! 417: arg.sg_flags = RAW; ! 418: if (boolean(value(TAND))) ! 419: arg.sg_flags |= TANDEM; ! 420: ioctl(FD, TIOCSETP, (char *)&arg); ! 421: ioctl(FD, TIOCLBIS, (char *)&bits); ! 422: } ! 423: ! 424: /* ! 425: * Return "simple" name from a file name, ! 426: * strip leading directories. ! 427: */ ! 428: char * ! 429: sname(s) ! 430: register char *s; ! 431: { ! 432: register char *p = s; ! 433: ! 434: while (*s) ! 435: if (*s++ == '/') ! 436: p = s; ! 437: return (p); ! 438: } ! 439: ! 440: static char partab[0200]; ! 441: ! 442: /* ! 443: * Do a write to the remote machine with the correct parity. ! 444: * We are doing 8 bit wide output, so we just generate a character ! 445: * with the right parity and output it. ! 446: */ ! 447: pwrite(fd, buf, n) ! 448: int fd; ! 449: char *buf; ! 450: register int n; ! 451: { ! 452: register int i; ! 453: register char *bp; ! 454: ! 455: bp = buf; ! 456: for (i = 0; i < n; i++) { ! 457: *bp = partab[(*bp) & 0177]; ! 458: bp++; ! 459: } ! 460: write(fd, buf, n); ! 461: } ! 462: ! 463: /* ! 464: * Build a parity table with appropriate high-order bit. ! 465: */ ! 466: setparity(defparity) ! 467: char *defparity; ! 468: { ! 469: register int i; ! 470: char *parity; ! 471: extern char evenpartab[]; ! 472: ! 473: if (value(PARITY) == NOSTR) ! 474: value(PARITY) = defparity; ! 475: parity = value(PARITY); ! 476: for (i = 0; i < 0200; i++) ! 477: partab[i] = evenpartab[i]; ! 478: if (equal(parity, "even")) ! 479: return; ! 480: if (equal(parity, "odd")) { ! 481: for (i = 0; i < 0200; i++) ! 482: partab[i] ^= 0200; /* reverse bit 7 */ ! 483: return; ! 484: } ! 485: if (equal(parity, "none") || equal(parity, "zero")) { ! 486: for (i = 0; i < 0200; i++) ! 487: partab[i] &= ~0200; /* turn off bit 7 */ ! 488: return; ! 489: } ! 490: if (equal(parity, "one")) { ! 491: for (i = 0; i < 0200; i++) ! 492: partab[i] |= 0200; /* turn on bit 7 */ ! 493: return; ! 494: } ! 495: fprintf(stderr, "%s: unknown parity value\n", PA); ! 496: fflush(stderr); ! 497: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.