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