X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/884b937aa618f5c4c194c03ccdad046b160b8575..ec72c53815dd686317a29d9504a5055a76d2a10e:/usr/src/usr.bin/rlogin/rlogin.c diff --git a/usr/src/usr.bin/rlogin/rlogin.c b/usr/src/usr.bin/rlogin/rlogin.c index 08f8d8f873..68e4ace425 100644 --- a/usr/src/usr.bin/rlogin/rlogin.c +++ b/usr/src/usr.bin/rlogin/rlogin.c @@ -11,13 +11,14 @@ char copyright[] = #endif not lint #ifndef lint -static char sccsid[] = "@(#)rlogin.c 5.3.1.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)rlogin.c 5.9 (Berkeley) %G%"; #endif not lint /* * rlogin - remote login */ #include +#include #include #include #include @@ -29,8 +30,12 @@ static char sccsid[] = "@(#)rlogin.c 5.3.1.1 (Berkeley) %G%"; #include #include #include -#include #include +#include + +# ifndef TIOCPKT_WINDOW +# define TIOCPKT_WINDOW 0x80 +# endif TIOCPKT_WINDOW char *index(), *rindex(), *malloc(), *getenv(); struct passwd *getpwuid(); @@ -45,10 +50,9 @@ char *speeds[] = char term[256] = "network"; extern int errno; int lostpeer(); -int nosigwin; -jmp_buf winsizechanged; +int dosigwinch = 0; struct winsize winsize; -int sigwinch(); +int sigwinch(), oob(); main(argc, argv) int argc; @@ -58,7 +62,7 @@ main(argc, argv) struct sgttyb ttyb; struct passwd *pwd; struct servent *sp; - int uid, options = 0; + int uid, options = 0, oldmask; int on = 1; host = rindex(argv[0], '/'); @@ -97,11 +101,6 @@ another: argv++, argc--; goto another; } - if (argc > 0 && !strcmp(*argv, "-w")) { - nosigwin++; - argv++, argc--; - goto another; - } if (host == 0) goto usage; if (argc > 0) @@ -123,12 +122,10 @@ another: strcat(term, "/"); strcat(term, speeds[ttyb.sg_ospeed]); } - if (!nosigwin && ioctl(0, TIOCGWINSZ, &winsize) == 0) { - cp = index(term, '\0'); - sprintf(cp, "/%u,%u,%u,%u", winsize.ws_row, winsize.ws_col, - winsize.ws_xpixel, winsize.ws_ypixel); - } + (void) ioctl(0, TIOCGWINSZ, &winsize); signal(SIGPIPE, lostpeer); + signal(SIGURG, oob); + oldmask = sigblock(sigmask(SIGURG)); rem = rcmd(&host, sp->s_port, pwd->pw_name, name ? name : pwd->pw_name, term, 0); if (rem < 0) @@ -141,11 +138,11 @@ another: perror("rlogin: setuid"); exit(1); } - doit(); + doit(oldmask); /*NOTREACHED*/ usage: fprintf(stderr, - "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ] [ -w ]\n"); + "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n"); exit(1); } @@ -153,6 +150,7 @@ usage: int child; int catchild(); +int writeroob(); int defflags, tabflag; int deflflags; @@ -162,7 +160,7 @@ struct ltchars defltc; struct tchars notc = { -1, -1, -1, -1, -1, -1 }; struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; -doit() +doit(oldmask) { int exit(); struct sgttyb sb; @@ -178,37 +176,55 @@ doit() notc.t_startc = deftc.t_startc; notc.t_stopc = deftc.t_stopc; ioctl(0, TIOCGLTC, (char *)&defltc); - signal(SIGINT, exit); + signal(SIGINT, SIG_IGN); signal(SIGHUP, exit); signal(SIGQUIT, exit); child = fork(); if (child == -1) { perror("rlogin: fork"); - done(); + done(1); } - signal(SIGINT, SIG_IGN); - mode(1); if (child == 0) { - reader(); + mode(1); + sigsetmask(oldmask); + if (reader() == 0) { + prf("Connection closed."); + exit(0); + } sleep(1); prf("\007Connection closed."); exit(3); } + signal(SIGURG, writeroob); + sigsetmask(oldmask); signal(SIGCHLD, catchild); - if (!nosigwin) - signal(SIGWINCH, sigwinch); writer(); prf("Closed connection."); - done(); + done(0); } -done() +done(status) + int status; { mode(0); if (child > 0 && kill(child, SIGKILL) >= 0) wait((int *)0); - exit(0); + exit(status); +} + +/* + * This is called when the reader process gets the out-of-band (urgent) + * request to turn on the window-changing protocol. + */ +writeroob() +{ + + if (dosigwinch == 0) { + sendwindow(); + signal(SIGWINCH, sigwinch); + } + dosigwinch = 1; } catchild() @@ -224,7 +240,7 @@ again: * if the child (reader) dies, just quit */ if (pid < 0 || pid == child && !WIFSTOPPED(status)) - done(); + done(status.w_termsig | status.w_retcode); goto again; } @@ -241,33 +257,6 @@ writer() register bol = 1; /* beginning of line */ register local = 0; - /* - * Handle SIGWINCH's with in-band signaling of new - * window size. It seems reasonable that we flush - * pending input and not force out of band signal - * as this most likely will occur from an input device - * other than the keyboard (e.g. a mouse). - * - * The hack of using 0377 to signal an in-band signal - * is pretty bad, but otherwise we'd be forced to - * either get complicated (use MSG_OOB) or go to a - * serious (telnet-style) protocol. - */ - if (setjmp(winsizechanged)) { - char obuf[4 + sizeof (struct winsize)]; - struct winsize *wp = (struct winsize *)(obuf+4); - - obuf[0] = 0377; /* XXX */ - obuf[1] = 0377; /* XXX */ - obuf[2] = 's'; /* XXX */ - obuf[3] = 's'; /* XXX */ - wp->ws_row = htons(winsize.ws_row); - wp->ws_col = htons(winsize.ws_col); - wp->ws_xpixel = htons(winsize.ws_xpixel); - wp->ws_ypixel = htons(winsize.ws_ypixel); - (void) write(rem, obuf, 4+sizeof (*wp)); - } - for (;;) { n = read(0, &c, 1); if (n <= 0) { @@ -275,8 +264,6 @@ writer() continue; break; } - if (!eight) - c &= 0177; /* * If we're at the beginning of the line * and recognize a command character, then @@ -312,6 +299,7 @@ writer() break; } bol = c == defkill || c == deftc.t_eofc || + c == deftc.t_intrc || c == defltc.t_suspc || c == '\r' || c == '\n'; } } @@ -340,8 +328,6 @@ register char c; stop(cmdc) char cmdc; { - struct winsize ws; - mode(0); signal(SIGCHLD, SIG_IGN); kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); @@ -354,40 +340,130 @@ sigwinch() { struct winsize ws; - if (!nosigwin && ioctl(0, TIOCGWINSZ, &ws) == 0 && + if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 && bcmp(&ws, &winsize, sizeof (ws))) { winsize = ws; - longjmp(winsizechanged, 1); + sendwindow(); } } +/* + * Send the window size to the server via the magic escape + */ +sendwindow() +{ + char obuf[4 + sizeof (struct winsize)]; + struct winsize *wp = (struct winsize *)(obuf+4); + + obuf[0] = 0377; + obuf[1] = 0377; + obuf[2] = 's'; + obuf[3] = 's'; + wp->ws_row = htons(winsize.ws_row); + wp->ws_col = htons(winsize.ws_col); + wp->ws_xpixel = htons(winsize.ws_xpixel); + wp->ws_ypixel = htons(winsize.ws_ypixel); + (void) write(rem, obuf, sizeof(obuf)); +} + +/* + * reader: read from remote: line -> 1 + */ +#define READING 1 +#define WRITING 2 + +char rcvbuf[8 * 1024]; +int rcvcnt; +int rcvstate; +jmp_buf rcvtop; + oob() { - int out = 1+1, atmark; + int out = FWRITE, atmark, n; + int rcvd = 0; char waste[BUFSIZ], mark; + struct sgttyb sb; - ioctl(1, TIOCFLUSH, (char *)&out); - for (;;) { - if (ioctl(rem, SIOCATMARK, &atmark) < 0) { - perror("ioctl"); - break; - } - if (atmark) - break; - if (read(rem, waste, sizeof (waste)) <= 0) - break; + while (recv(rem, &mark, 1, MSG_OOB) < 0) + switch (errno) { + + case EWOULDBLOCK: + /* + * Urgent data not here yet. + * It may not be possible to send it yet + * if we are blocked for output + * and our input buffer is full. + */ + if (rcvcnt < sizeof(rcvbuf)) { + n = read(rem, rcvbuf + rcvcnt, + sizeof(rcvbuf) - rcvcnt); + if (n <= 0) + return; + rcvd += n; + } else { + n = read(rem, waste, sizeof(waste)); + if (n <= 0) + return; + } + continue; + + default: + return; } - recv(rem, &mark, 1, MSG_OOB); - if (mark & TIOCPKT_NOSTOP) { + if (mark & TIOCPKT_WINDOW) { + /* + * Let server know about window size changes + */ + kill(getppid(), SIGURG); + } + if (!eight && (mark & TIOCPKT_NOSTOP)) { + ioctl(0, TIOCGETP, (char *)&sb); + sb.sg_flags &= ~CBREAK; + sb.sg_flags |= RAW; + ioctl(0, TIOCSETN, (char *)&sb); notc.t_stopc = -1; notc.t_startc = -1; ioctl(0, TIOCSETC, (char *)¬c); } - if (mark & TIOCPKT_DOSTOP) { + if (!eight && (mark & TIOCPKT_DOSTOP)) { + ioctl(0, TIOCGETP, (char *)&sb); + sb.sg_flags &= ~RAW; + sb.sg_flags |= CBREAK; + ioctl(0, TIOCSETN, (char *)&sb); notc.t_stopc = deftc.t_stopc; notc.t_startc = deftc.t_startc; ioctl(0, TIOCSETC, (char *)¬c); } + if (mark & TIOCPKT_FLUSHWRITE) { + ioctl(1, TIOCFLUSH, (char *)&out); + for (;;) { + if (ioctl(rem, SIOCATMARK, &atmark) < 0) { + perror("ioctl"); + break; + } + if (atmark) + break; + n = read(rem, waste, sizeof (waste)); + if (n <= 0) + break; + } + /* + * Don't want any pending data to be output, + * so clear the recv buffer. + * If we were hanging on a write when interrupted, + * don't want it to restart. If we were reading, + * restart anyway. + */ + rcvcnt = 0; + longjmp(rcvtop, 1); + } + /* + * If we filled the receive buffer while a read was pending, + * longjmp to the top to restart appropriately. Don't abort + * a pending write, however, or we won't know how much was written. + */ + if (rcvd && rcvstate == READING) + longjmp(rcvtop, 1); } /* @@ -395,23 +471,35 @@ oob() */ reader() { - char rb[BUFSIZ]; - register int cnt; + int pid = getpid(); + int n, remaining; + char *bufp = rcvbuf; - signal(SIGURG, oob); signal(SIGTTOU, SIG_IGN); - { int pid = getpid(); - fcntl(rem, F_SETOWN, pid); } + fcntl(rem, F_SETOWN, pid); + (void) setjmp(rcvtop); for (;;) { - cnt = read(rem, rb, sizeof (rb)); - if (cnt == 0) - break; - if (cnt < 0) { + while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { + rcvstate = WRITING; + n = write(1, bufp, remaining); + if (n < 0) { + if (errno != EINTR) + return (-1); + continue; + } + bufp += n; + } + bufp = rcvbuf; + rcvcnt = 0; + rcvstate = READING; + rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); + if (rcvcnt == 0) + return (0); + if (rcvcnt < 0) { if (errno == EINTR) continue; - break; + return (-1); } - write(1, rb, cnt); } } @@ -459,10 +547,10 @@ mode(f) } /*VARARGS*/ -prf(f, a1, a2, a3) +prf(f, a1, a2, a3, a4, a5) char *f; { - fprintf(stderr, f, a1, a2, a3); + fprintf(stderr, f, a1, a2, a3, a4, a5); fprintf(stderr, CRLF); } @@ -470,5 +558,5 @@ lostpeer() { signal(SIGPIPE, SIG_IGN); prf("\007Connection closed."); - done(); + done(1); }