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