home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / tip / tip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-09  |  13.5 KB  |  681 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 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.8 (Berkeley) 9/2/88";
  28. #endif /* not lint */
  29.  
  30. /*
  31.  * tip - UNIX link to other systems
  32.  *  tip [-psv] [-speed] system-name [data]
  33.  * or
  34.  *  cu phone-number [-s speed] [-l line] [-a acu]
  35.  */
  36. #include "tip.h"
  37. #include <sys/stat.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, 38400, -1
  45. };
  46.  
  47. int    page;
  48. int    disc = NTTYDISC;        /* tip normally runs this way */
  49. sigfunc_t    intprompt();
  50. sigfunc_t    timeout();
  51. sigfunc_t    cleanup();
  52. char    *login();
  53. char    *sname();
  54. char    PNbuf[256];            /* This limits the size of a number */
  55.  
  56. main(argc, argv)
  57.     char *argv[];
  58. {
  59.     int uuid;
  60.     char *system = NOSTR;
  61.     char *data = NOSTR;
  62.     register int i;
  63.     register char *p;
  64.     char sbuf[12];
  65.  
  66.     uid = getuid();
  67.     gid = getgid();
  68.     euid = geteuid();    /* should be root */
  69.     egid = getegid();
  70.     uuid = euid;
  71.     
  72.     if (equal(sname(argv[0]), "cu")) {
  73.         setreuid(uid, uuid);
  74.         cumode = 1;
  75.         cumain(argc, argv);
  76.         goto cucommon;
  77.     }
  78.  
  79.     if (argc < 2) {
  80.         fprintf(stderr, "usage: tip [-psv] [-speed] [system-name] [data]\n");
  81.         exit(1);
  82.     }
  83.  
  84.     for (; argc > 1; argv++, argc--) {
  85.         if (argv[1][0] != '-') {
  86.             if (system)
  87.                 data = argv[1];
  88.             else
  89.                 system = argv[1];
  90.         }
  91.         else switch (argv[1][1]) {
  92.  
  93.         case 'p':
  94.             page++;
  95.             break;
  96.         case 's':
  97.             slip++;
  98.             break;
  99.         case 'v':
  100.             vflag++;
  101.             boolean(value(VERBOSE)) = 1;
  102.             break;
  103.         case 'd':
  104.             debug++;
  105.             break;
  106.  
  107.         case '0': case '1': case '2': case '3': case '4':
  108.         case '5': case '6': case '7': case '8': case '9':
  109.             BR = atoi(&argv[1][1]);
  110.             break;
  111.  
  112.         default:
  113.             fprintf(stderr, "tip: %s, unknown option\n", argv[1]);
  114.             break;
  115.         }
  116.     }
  117.     if (system != NOSTR && isdigit(*system)) {
  118.         /*
  119.          * System name is really a phone number...
  120.          * Copy the number then stomp on the original (in case the
  121.          * number is private, we don't want 'ps' or 'w' to find it).
  122.          */
  123.         if (strlen(system) > sizeof PNbuf - 1) {
  124.             fprintf(stderr,
  125.                 "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.     signal(SIGINT, cleanup);
  137.     signal(SIGQUIT, cleanup);
  138.     signal(SIGHUP, cleanup);
  139.     signal(SIGTERM, cleanup);
  140.     signal(SIGPIPE, 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.     setreuid(uid, uuid);
  152.     euid = uuid;
  153.  
  154.     if (!isatty(0) && !slip && !page)
  155.         fprintf(stderr, "tip: warning: input is not a tty\n");
  156.  
  157.     setbuf(stdout, NULL);
  158. #ifdef ACULOG
  159.     loginit();
  160. #endif
  161.     /*
  162.      * Kludge, their's no easy way to get the initialization
  163.      *   in the right order, so force it here
  164.      */
  165.     if ((PH = getenv("PHONES")) == NOSTR)
  166.         PH = "/etc/phones";
  167.     vinit();                /* init variables */
  168.     setparity("none");            /* set the parity table */
  169.     if ((i = speed(number(value(BAUDRATE)))) == NULL) {
  170.         printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
  171.         (void)uu_unlock(uucplock);
  172.         exit(3);
  173.     }
  174.     if (slip) {
  175.         if (CC == NOSTR) {
  176.             printf("tip: must supply cc with slip\n");
  177.             uu_unlock(uucplock);
  178.             exit(3);
  179.         }
  180. #ifdef notdef
  181.         if (SA == NOSTR) {
  182.             printf("tip: local addr not set\n");
  183.             uu_unlock(uucplock);
  184.             exit(3);
  185.         }
  186.         if (DA == NOSTR) {
  187.             printf("tip: destination addr not set\n");
  188.             uu_unlock(uucplock);
  189.             exit(3);
  190.         }
  191. #endif
  192.     }
  193.  
  194.     /*
  195.      * Now that we have the logfile and the ACU open
  196.      *  return to the real uid and gid.  These things will
  197.      *  be closed on exit.  Swap real and effective uid's
  198.      *  so we can get the original permissions back
  199.      *  for removing the uucp lock.
  200.      */
  201.     user_uid();
  202.  
  203.     /*
  204.      * Hardwired connections require the
  205.      *  line speed set before they make any transmissions
  206.      *  (this is particularly true of things like a DF03-AC)
  207.      */
  208.     if (HW)
  209.         ttysetup(i);
  210.     if (p = lconnect()) {
  211.         printf("\07%s\n[EOT]\n", p);
  212.         daemon_uid();
  213.         (void)uu_unlock(uucplock);
  214.         exit(1);
  215.     }
  216.     if (!HW)
  217.         ttysetup(i);
  218.  
  219.     if (LS != NOSTR) {
  220.         fprintf(stderr, "[Logging in...]\r\n");
  221.         if (p = login()) {
  222.             printf("\07%s\n[EOT]\n", p);
  223.             daemon_uid();
  224.             (void)uu_unlock(uucplock);
  225.             exit(1);
  226.         }
  227.     }
  228.  
  229. cucommon:
  230.     /*
  231.      * From here down the code is shared with
  232.      * the "cu" version of tip.
  233.      */
  234.     ioctl(0, TIOCGETP, (char *)&defarg);
  235.     ioctl(0, TIOCGETC, (char *)&defchars);
  236.     ioctl(0, TIOCGLTC, (char *)&deflchars);
  237.     ioctl(0, TIOCGETD, (char *)&odisc);
  238.     arg = defarg;
  239.     arg.sg_flags = ANYP | CBREAK;
  240.     tchars = defchars;
  241.     tchars.t_intrc = tchars.t_quitc = -1;
  242.     ltchars = deflchars;
  243.     ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
  244.         = ltchars.t_lnextc = -1;
  245.  
  246.     if (page) {
  247.         i = sendpage(data);
  248.         daemon_uid();
  249.         (void)uu_unlock(uucplock);
  250.         exit(i);
  251.     }
  252.     if (slip) {
  253.         i = runslip();
  254.         cleanup();
  255.         exit(i);
  256.     }
  257.     raw();
  258.  
  259.     pipe(fildes); pipe(repdes);
  260.     signal(SIGALRM, timeout);
  261.  
  262.     /*
  263.      * Everything's set up now:
  264.      *    connection established (hardwired or dialup)
  265.      *    line conditioned (baud rate, mode, etc.)
  266.      *    internal data structures (variables)
  267.      * so, fork one process for local side and one for remote.
  268.      */
  269.     printf(cumode ? "Connected\r\n" : "\07connected\r\n");
  270.     if (pid = fork())
  271.         tipin();
  272.     else
  273.         tipout();
  274.     /*NOTREACHED*/
  275. }
  276.  
  277. sigfunc_t
  278. cleanup()
  279. {
  280.  
  281.     daemon_uid();
  282.     (void)uu_unlock(uucplock);
  283.     if (pid) {
  284.         if (pid && kill(pid, SIGTERM) < 0 && errno != ESRCH)
  285.             perror("tip: child kill");
  286.         if (!slip)
  287.             unraw();
  288.     } else if (odisc && !slip)
  289.         ioctl(0, TIOCSETD, (char *)&odisc);
  290.     exit(0);
  291. }
  292.  
  293. /*
  294.  * Muck with user ID's.  We are setuid to the owner of the lock
  295.  * directory when we start.  user_uid() reverses real and effective
  296.  * ID's after startup, to run with the user's permissions.
  297.  * daemon_uid() switches back to the privileged uid for unlocking.
  298.  * Finally, to avoid running a shell with the wrong real uid,
  299.  * shell_uid() sets real and effective uid's to the user's real ID.
  300.  */
  301. static int uidswapped;
  302.  
  303. user_uid()
  304. {
  305.     if (uidswapped == 0) {
  306.         setregid(egid, gid);
  307.         setreuid(euid, uid);
  308.         uidswapped = 1;
  309.     }
  310. }
  311.  
  312. daemon_uid()
  313. {
  314.     if (uidswapped) {
  315.         setreuid(uid, euid);
  316.         setregid(gid, egid);
  317.         uidswapped = 0;
  318.     }
  319. }
  320.  
  321. shell_uid()
  322. {
  323.     setreuid(uid, uid);
  324.     setregid(gid, gid);
  325. }
  326.  
  327. /*
  328.  * put the controlling keyboard into raw mode
  329.  */
  330. raw()
  331. {
  332.     if(ioctl(0, TIOCSETP, &arg) < 0)
  333.         perror("TIOCSETP");
  334.     if(ioctl(0, TIOCSETC, &tchars) < 0)
  335.         perror("TIOCSETC");
  336.     if(ioctl(0, TIOCSLTC, <chars) < 0)
  337.         perror("TIOCSLTC");
  338.     if(ioctl(0, TIOCSETD, (char *)&disc) < 0)
  339.         perror("TIOCSETD");
  340. }
  341.  
  342.  
  343. /*
  344.  * return keyboard to normal mode
  345.  */
  346. unraw()
  347. {
  348.     if (ioctl(0, TIOCSETD, (char *)&odisc) < 0)
  349.         perror("TIOCSETD");
  350.     if (ioctl(0, TIOCSETP, (char *)&defarg) < 0)
  351.         perror("TIOCSETP");
  352.     if (ioctl(0, TIOCSETC, (char *)&defchars) < 0)
  353.         perror("TIOCSETC");
  354.     if (ioctl(0, TIOCSLTC, (char *)&deflchars) < 0)
  355.         perror("TIOCSLTC");
  356. }
  357.  
  358. static    jmp_buf promptbuf;
  359.  
  360. /*
  361.  * Print string ``s'', then read a string
  362.  *  in from the terminal.  Handles signals & allows use of
  363.  *  normal erase and kill characters.
  364.  */
  365. prompt(s, p)
  366.     char *s;
  367.     register char *p;
  368. {
  369.     register char *b = p;
  370.     sigfunc_t (*oint)(), (*oquit)();
  371.  
  372.     stoprompt = 0;
  373.     oint = signal(SIGINT, intprompt);
  374.     oquit = signal(SIGQUIT, SIG_IGN);
  375.     unraw();
  376.     printf("%s", s);
  377.     if (setjmp(promptbuf) == 0)
  378.         while ((*p = getchar()) != EOF && *p != '\n')
  379.             p++;
  380.     *p = '\0';
  381.  
  382.     raw();
  383.     signal(SIGINT, oint);
  384.     signal(SIGQUIT, oint);
  385.     return (stoprompt || p == b);
  386. }
  387.  
  388. /*
  389.  * Interrupt service routine during prompting
  390.  */
  391. sigfunc_t
  392. intprompt()
  393. {
  394.     signal(SIGINT, SIG_IGN);
  395.     stoprompt = 1;
  396.     printf("\r\n");
  397.     longjmp(promptbuf, 1);
  398. }
  399.  
  400. tipin()
  401. {
  402.     char gch, bol = 1;
  403.  
  404.     /*
  405.      * Kinda klugey here...
  406.      *   check for scripting being turned on from the .tiprc file,
  407.      *   but be careful about just using setscript(), as we may
  408.      *   send a SIGEMT before tipout has a chance to set up catching
  409.      *   it; so wait a second, then setscript()
  410.      */
  411.     if (boolean(value(SCRIPT))) {
  412.         sleep(1);
  413.         setscript();
  414.     }
  415.  
  416.     while (1) {
  417.         gch = getchar()&0177;
  418.         if ((gch == character(value(ESCAPE))) && bol) {
  419.             if (!(gch = escape()))
  420.                 continue;
  421.         } else if (!cumode && gch == character(value(RAISECHAR))) {
  422.             boolean(value(RAISE)) = !boolean(value(RAISE));
  423.             continue;
  424.         } else if (gch == '\r') {
  425.             bol = 1;
  426.             pwrite(FD, &gch, 1);
  427.             if (boolean(value(HALFDUPLEX)))
  428.                 printf("\r\n");
  429.             continue;
  430.         } else if (!cumode && gch == character(value(FORCE)))
  431.             gch = getchar()&0177;
  432.         bol = any(gch, value(EOL));
  433.         if (boolean(value(RAISE)) && islower(gch))
  434.             gch = toupper(gch);
  435.         pwrite(FD, &gch, 1);
  436.         if (boolean(value(HALFDUPLEX)))
  437.             printf("%c", gch);
  438.     }
  439. }
  440.  
  441. /*
  442.  * Escape handler --
  443.  *  called on recognition of ``escapec'' at the beginning of a line
  444.  */
  445. escape()
  446. {
  447.     register char gch;
  448.     register esctable_t *p;
  449.     char c = character(value(ESCAPE));
  450.     extern esctable_t etable[];
  451.  
  452.     gch = (getchar()&0177);
  453.     for (p = etable; p->e_char; p++)
  454.         if (p->e_char == gch) {
  455.             if ((p->e_flags&PRIV) && uid)
  456.                 continue;
  457.             printf("%s", ctrl(c));
  458.             (*p->e_func)(gch);
  459.             return (0);
  460.         }
  461.     /* ESCAPE ESCAPE forces ESCAPE */
  462.     if (c != gch)
  463.         pwrite(FD, &c, 1);
  464.     return (gch);
  465. }
  466.  
  467. speed(n)
  468.     int n;
  469. {
  470.     register int *p;
  471.  
  472.     for (p = bauds; *p != -1;  p++)
  473.         if (*p == n)
  474.             return (p - bauds);
  475.     return (NULL);
  476. }
  477.  
  478. any(c, p)
  479.     register char c, *p;
  480. {
  481.     while (p && *p)
  482.         if (*p++ == c)
  483.             return (1);
  484.     return (0);
  485. }
  486.  
  487. size(s)
  488.     register char    *s;
  489. {
  490.     register int i = 0;
  491.  
  492.     while (s && *s++)
  493.         i++;
  494.     return (i);
  495. }
  496.  
  497. char *
  498. interp(s)
  499.     register char *s;
  500. {
  501.     static char buf[256];
  502.     register char *p = buf, c, *q;
  503.  
  504.     while (c = *s++) {
  505.         for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++)
  506.             if (*q++ == c) {
  507.                 *p++ = '\\'; *p++ = *q;
  508.                 goto next;
  509.             }
  510.         if (c < 040) {
  511.             *p++ = '^'; *p++ = c + 'A'-1;
  512.         } else if (c == 0177) {
  513.             *p++ = '^'; *p++ = '?';
  514.         } else
  515.             *p++ = c;
  516.     next:
  517.         ;
  518.     }
  519.     *p = '\0';
  520.     return (buf);
  521. }
  522.  
  523. char *
  524. ctrl(c)
  525.     char c;
  526. {
  527.     static char s[3];
  528.  
  529.     if (c < 040 || c == 0177) {
  530.         s[0] = '^';
  531.         s[1] = c == 0177 ? '?' : c+'A'-1;
  532.         s[2] = '\0';
  533.     } else {
  534.         s[0] = c;
  535.         s[1] = '\0';
  536.     }
  537.     return (s);
  538. }
  539.  
  540. /*
  541.  * Help command
  542.  */
  543. help(c)
  544.     char c;
  545. {
  546.     register esctable_t *p;
  547.     extern esctable_t etable[];
  548.  
  549.     printf("%c\r\n", c);
  550.     for (p = etable; p->e_char; p++) {
  551.         if ((p->e_flags&PRIV) && uid)
  552.             continue;
  553.         printf("%2s", ctrl(character(value(ESCAPE))));
  554.         printf("%-2s %c   %s\r\n", ctrl(p->e_char),
  555.             p->e_flags&EXP ? '*': ' ', p->e_help);
  556.     }
  557. }
  558.  
  559. /*
  560.  * Set up the "remote" tty's state
  561.  */
  562. ttysetup(speed)
  563.     int speed;
  564. {
  565.     unsigned bits = LDECCTQ;
  566.  
  567.     arg.sg_ispeed = arg.sg_ospeed = speed;
  568.     arg.sg_flags = RAW | ANYP;
  569.     if (ioctl(FD, TIOCSETD, (char *)&disc) < 0)
  570.         perror("TIOCSETD");
  571.     if (boolean(value(TAND)))
  572.         arg.sg_flags |= TANDEM;
  573.     if (boolean(value(HWFC))) {
  574.         int lflags;
  575.  
  576.         if (ioctl(FD, TIOCLGET, &lflags) < 0)
  577.             perror("TIOCLGET");
  578.         lflags |= LMDMBUF;
  579.         if (ioctl(FD, TIOCLSET, &lflags) < 0)
  580.             perror("TIOCLSET");
  581.     }
  582.     if (boolean(value(DTRHUP))) {
  583.         ioctl(FD, TIOCSDTR, 0);
  584.         ioctl(FD, TIOCHPCL, 0);
  585.     }
  586.     ioctl(FD, TIOCSETP, (char *)&arg);
  587. }
  588.  
  589. /*
  590.  * Return "simple" name from a file name,
  591.  * strip leading directories.
  592.  */
  593. char *
  594. sname(s)
  595.     register char *s;
  596. {
  597.     register char *p = s;
  598.  
  599.     while (*s)
  600.         if (*s++ == '/')
  601.             p = s;
  602.     return (p);
  603. }
  604.  
  605. static char partab[0200];
  606.  
  607. /*
  608.  * Do a write to the remote machine with the correct parity.
  609.  * We are doing 8 bit wide output, so we just generate a character
  610.  * with the right parity and output it.
  611.  */
  612. pwrite(fd, buf, n)
  613.     int fd;
  614.     char *buf;
  615.     register int n;
  616. {
  617.     register int i;
  618.     register char *bp;
  619.  
  620.     bp = buf;
  621.     for (i = 0; i < n; i++) {
  622.         *bp = partab[(*bp) & 0177];
  623.         bp++;
  624.     }
  625.     if (write(fd, buf, n) < 0) {
  626.         if (errno == EIO)
  627.             abort("Lost carrier.");
  628.         /* this is questionable */
  629.         perror("write");
  630.         putc('\r', stderr);
  631.     }
  632. }
  633.  
  634. /*
  635.  * Build a parity table with appropriate high-order bit.
  636.  */
  637. setparity(defparity)
  638.     char *defparity;
  639. {
  640.     register int i;
  641.     char *parity;
  642.     extern char evenpartab[];
  643.  
  644.     if (value(PARITY) == NOSTR)
  645.         value(PARITY) = defparity;
  646.     parity = value(PARITY);
  647.     for (i = 0; i < 0200; i++)
  648.         partab[i] = evenpartab[i];
  649.     if (equal(parity, "even"))
  650.         return;
  651.     if (equal(parity, "odd")) {
  652.         for (i = 0; i < 0200; i++)
  653.             partab[i] ^= 0200;    /* reverse bit 7 */
  654.         return;
  655.     }
  656.     if (equal(parity, "none") || equal(parity, "zero")) {
  657.         for (i = 0; i < 0200; i++)
  658.             partab[i] &= ~0200;    /* turn off bit 7 */
  659.         return;
  660.     }
  661.     if (equal(parity, "one")) {
  662.         for (i = 0; i < 0200; i++)
  663.             partab[i] |= 0200;    /* turn on bit 7 */
  664.         return;
  665.     }
  666.     fprintf(stderr, "%s: unknown parity value\n", PA);
  667.     fflush(stderr);
  668. }
  669.  
  670. /* The uid could be determined by stat()-ing ACULOG */
  671. getuucpuid()
  672. {
  673.     struct passwd *pw;
  674.  
  675.     if ((pw = getpwnam("uucp")) == NULL) {
  676.         fprintf(stderr, "tip: unable to get uucp uid\n");
  677.         exit(1);
  678.     }
  679.     return(pw->pw_uid);
  680. }
  681.