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, &ltchars);
 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: }

Defined functions

any defined in line 395; used 6 times
cleanup defined in line 201; used 10 times
ctrl defined in line 440; used 7 times
daemon_uid defined in line 230; used 4 times
escape defined in line 362; used 1 times
help defined in line 460; used 2 times
interp defined in line 414; used 2 times
intprompt defined in line 305; used 3 times
main defined in line 40; never used
prompt defined in line 279; used 11 times
pwrite defined in line 515; used 8 times
raw defined in line 250; used 5 times
setparity defined in line 540; used 3 times
shell_uid defined in line 240; used 2 times
sname defined in line 496; used 2 times
speed defined in line 384; used 7 times
tipin defined in line 317; used 1 times
ttysetup defined in line 479; used 4 times
unraw defined in line 263; used 4 times
user_uid defined in line 221; used 3 times

Defined variables

PNbuf defined in line 38; used 5 times
bauds defined in line 28; used 2 times
copyright defined in line 8; never used
disc defined in line 33; used 1 times
partab defined in line 508; used 5 times
promptbuf defined in line 272; used 2 times
sccsid defined in line 14; never used
uidswapped defined in line 219; used 4 times
Last modified: 1987-10-23
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4576
Valid CSS Valid XHTML 1.0 Strict