home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tip / tip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-18  |  12.5 KB  |  603 lines

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