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