lint plus window size negotiation fixups from Torek
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
index 27e9062..7ad6544 100644 (file)
@@ -21,6 +21,8 @@ static char sccsid[] = "@(#)rlogin.c  5.11 (Berkeley) %G%";
 #include <sys/errno.h>
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <sys/errno.h>
 #include <sys/file.h>
 #include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <sys/wait.h>
 
 #include <netinet/in.h>
 #include <sys/wait.h>
 
 #include <netinet/in.h>
@@ -37,7 +39,12 @@ static char sccsid[] = "@(#)rlogin.c 5.11 (Berkeley) %G%";
 # define TIOCPKT_WINDOW 0x80
 # endif TIOCPKT_WINDOW
 
 # define TIOCPKT_WINDOW 0x80
 # endif TIOCPKT_WINDOW
 
-char   *index(), *rindex(), *malloc(), *getenv();
+/* concession to sun */
+# ifndef SIGUSR1
+# define SIGUSR1 30
+# endif SIGUSR1
+
+char   *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy();
 struct passwd *getpwuid();
 char   *name;
 int    rem;
 struct passwd *getpwuid();
 char   *name;
 int    rem;
@@ -55,16 +62,40 @@ int dosigwinch = 0;
 #define sigmask(m)     (1 << ((m)-1))
 #endif
 #ifdef sun
 #define sigmask(m)     (1 << ((m)-1))
 #endif
 #ifdef sun
-struct ttysize winsize;
 struct winsize {
        unsigned short ws_row, ws_col;
        unsigned short ws_xpixel, ws_ypixel;
 };
 struct winsize {
        unsigned short ws_row, ws_col;
        unsigned short ws_xpixel, ws_ypixel;
 };
-#else sun
-struct winsize winsize;
 #endif sun
 #endif sun
+struct winsize winsize;
 int    sigwinch(), oob();
 
 int    sigwinch(), oob();
 
+/*
+ * The following routine provides compatibility (such as it is)
+ * between 4.2BSD Suns and others.  Suns have only a `ttysize',
+ * so we convert it to a winsize.
+ */
+#ifdef sun
+int
+get_window_size(fd, wp)
+       int fd;
+       struct winsize *wp;
+{
+       struct ttysize ts;
+       int error;
+
+       if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0)
+               return (error);
+       wp->ws_row = ts.ts_lines;
+       wp->ws_col = ts.ts_cols;
+       wp->ws_xpixel = 0;
+       wp->ws_ypixel = 0;
+       return (0);
+}
+#else sun
+#define get_window_size(fd, wp)        ioctl(fd, TIOCGWINSZ, wp)
+#endif sun
+
 main(argc, argv)
        int argc;
        char **argv;
 main(argc, argv)
        int argc;
        char **argv;
@@ -128,19 +159,15 @@ another:
        }
        cp = getenv("TERM");
        if (cp)
        }
        cp = getenv("TERM");
        if (cp)
-               strcpy(term, cp);
+               (void) strcpy(term, cp);
        if (ioctl(0, TIOCGETP, &ttyb) == 0) {
        if (ioctl(0, TIOCGETP, &ttyb) == 0) {
-               strcat(term, "/");
-               strcat(term, speeds[ttyb.sg_ospeed]);
+               (void) strcat(term, "/");
+               (void) strcat(term, speeds[ttyb.sg_ospeed]);
        }
        }
-#ifdef sun
-       (void) ioctl(0, TIOCGSIZE, &winsize);
-#else sun
-       (void) ioctl(0, TIOCGWINSZ, &winsize);
-#endif sun
-       signal(SIGPIPE, lostpeer);
-       signal(SIGURG, oob);
-       oldmask = sigblock(sigmask(SIGURG));
+       (void) get_window_size(0, &winsize);
+       (void) signal(SIGPIPE, lostpeer);
+       /* will use SIGUSR1 for window size hack, so hold it off */
+       oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1));
         rem = rcmd(&host, sp->s_port, pwd->pw_name,
            name ? name : pwd->pw_name, term, 0);
         if (rem < 0)
         rem = rcmd(&host, sp->s_port, pwd->pw_name,
            name ? name : pwd->pw_name, term, 0);
         if (rem < 0)
@@ -165,7 +192,7 @@ usage:
 
 int    child;
 int    catchild();
 
 int    child;
 int    catchild();
-int    writeroob();
+int    copytochild(), writeroob();
 
 int    defflags, tabflag;
 int    deflflags;
 
 int    defflags, tabflag;
 int    deflflags;
@@ -180,20 +207,20 @@ doit(oldmask)
        int exit();
        struct sgttyb sb;
 
        int exit();
        struct sgttyb sb;
 
-       ioctl(0, TIOCGETP, (char *)&sb);
+       (void) ioctl(0, TIOCGETP, (char *)&sb);
        defflags = sb.sg_flags;
        tabflag = defflags & TBDELAY;
        defflags &= ECHO | CRMOD;
        deferase = sb.sg_erase;
        defkill = sb.sg_kill;
        defflags = sb.sg_flags;
        tabflag = defflags & TBDELAY;
        defflags &= ECHO | CRMOD;
        deferase = sb.sg_erase;
        defkill = sb.sg_kill;
-       ioctl(0, TIOCLGET, (char *)&deflflags);
-       ioctl(0, TIOCGETC, (char *)&deftc);
+       (void) ioctl(0, TIOCLGET, (char *)&deflflags);
+       (void) ioctl(0, TIOCGETC, (char *)&deftc);
        notc.t_startc = deftc.t_startc;
        notc.t_stopc = deftc.t_stopc;
        notc.t_startc = deftc.t_startc;
        notc.t_stopc = deftc.t_stopc;
-       ioctl(0, TIOCGLTC, (char *)&defltc);
-       signal(SIGINT, SIG_IGN);
-       signal(SIGHUP, exit);
-       signal(SIGQUIT, exit);
+       (void) ioctl(0, TIOCGLTC, (char *)&defltc);
+       (void) signal(SIGINT, SIG_IGN);
+       setsignal(SIGHUP, exit);
+       setsignal(SIGQUIT, exit);
        child = fork();
        if (child == -1) {
                perror("rlogin: fork");
        child = fork();
        if (child == -1) {
                perror("rlogin: fork");
@@ -201,8 +228,7 @@ doit(oldmask)
        }
        if (child == 0) {
                mode(1);
        }
        if (child == 0) {
                mode(1);
-               sigsetmask(oldmask);
-               if (reader() == 0) {
+               if (reader(oldmask) == 0) {
                        prf("Connection closed.");
                        exit(0);
                }
                        prf("Connection closed.");
                        exit(0);
                }
@@ -210,24 +236,60 @@ doit(oldmask)
                prf("\007Connection closed.");
                exit(3);
        }
                prf("\007Connection closed.");
                exit(3);
        }
-       signal(SIGURG, writeroob);
-       sigsetmask(oldmask);
-       signal(SIGCHLD, catchild);
+
+       /*
+        * We may still own the socket, and may have a pending SIGURG
+        * (or might receive one soon) that we really want to send to
+        * the reader.  Set a trap that simply copies such signals to
+        * the child.
+        */
+       (void) signal(SIGURG, copytochild);
+       (void) signal(SIGUSR1, writeroob);
+       (void) sigsetmask(oldmask);
+       (void) signal(SIGCHLD, catchild);
        writer();
        prf("Closed connection.");
        done(0);
 }
 
        writer();
        prf("Closed connection.");
        done(0);
 }
 
+/*
+ * Trap a signal, unless it is being ignored.
+ */
+setsignal(sig, act)
+       int sig, (*act)();
+{
+       int omask = sigblock(sigmask(sig));
+
+       if (signal(sig, act) == SIG_IGN)
+               (void) signal(sig, SIG_IGN);
+       (void) sigsetmask(omask);
+}
+
 done(status)
        int status;
 {
 done(status)
        int status;
 {
+       int w;
 
        mode(0);
 
        mode(0);
-       if (child > 0 && kill(child, SIGKILL) >= 0)
-               wait((int *)0);
+       if (child > 0) {
+               /* make sure catchild does not snap it up */
+               (void) signal(SIGCHLD, SIG_DFL);
+               if (kill(child, SIGKILL) >= 0)
+                       while ((w = wait((union wait *)0)) > 0 && w != child)
+                               /*void*/;
+       }
        exit(status);
 }
 
        exit(status);
 }
 
+/*
+ * Copy SIGURGs to the child process.
+ */
+copytochild()
+{
+
+       (void) kill(child, SIGURG);
+}
+
 /*
  * This is called when the reader process gets the out-of-band (urgent)
  * request to turn on the window-changing protocol.
 /*
  * This is called when the reader process gets the out-of-band (urgent)
  * request to turn on the window-changing protocol.
@@ -237,7 +299,7 @@ writeroob()
 
        if (dosigwinch == 0) {
                sendwindow();
 
        if (dosigwinch == 0) {
                sendwindow();
-               signal(SIGWINCH, sigwinch);
+               (void) signal(SIGWINCH, sigwinch);
        }
        dosigwinch = 1;
 }
        }
        dosigwinch = 1;
 }
@@ -248,14 +310,14 @@ catchild()
        int pid;
 
 again:
        int pid;
 
 again:
-       pid = wait3(&status, WNOHANG|WUNTRACED, 0);
+       pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
        if (pid == 0)
                return;
        /*
         * if the child (reader) dies, just quit
         */
        if (pid < 0 || pid == child && !WIFSTOPPED(status))
        if (pid == 0)
                return;
        /*
         * if the child (reader) dies, just quit
         */
        if (pid < 0 || pid == child && !WIFSTOPPED(status))
-               done(status.w_termsig | status.w_retcode);
+               done((int)(status.w_termsig | status.w_retcode));
        goto again;
 }
 
        goto again;
 }
 
@@ -307,7 +369,7 @@ writer()
                                continue;
                        }
                        if (c != cmdchar)
                                continue;
                        }
                        if (c != cmdchar)
-                               write(rem, &cmdchar, 1);
+                               (void) write(rem, &cmdchar, 1);
                }
                if (write(rem, &c, 1) == 0) {
                        prf("line gone");
                }
                if (write(rem, &c, 1) == 0) {
                        prf("line gone");
@@ -337,44 +399,30 @@ register char c;
                *p++ = c;
        *p++ = '\r';
        *p++ = '\n';
                *p++ = c;
        *p++ = '\r';
        *p++ = '\n';
-       write(1, buf, p - buf);
+       (void) write(1, buf, p - buf);
 }
 
 stop(cmdc)
        char cmdc;
 {
        mode(0);
 }
 
 stop(cmdc)
        char cmdc;
 {
        mode(0);
-       signal(SIGCHLD, SIG_IGN);
-       kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
-       signal(SIGCHLD, catchild);
+       (void) signal(SIGCHLD, SIG_IGN);
+       (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
+       (void) signal(SIGCHLD, catchild);
        mode(1);
        sigwinch();                     /* check for size changes */
 }
 
        mode(1);
        sigwinch();                     /* check for size changes */
 }
 
-#ifdef sun
-sigwinch()
-{
-       struct ttysize ws;
-
-       if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
-           bcmp(&ws, &winsize, sizeof (ws))) {
-               winsize = ws;
-               sendwindow();
-       }
-}
-
-#else sun
 sigwinch()
 {
        struct winsize ws;
 
 sigwinch()
 {
        struct winsize ws;
 
-       if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
+       if (dosigwinch && get_window_size(0, &ws) == 0 &&
            bcmp(&ws, &winsize, sizeof (ws))) {
                winsize = ws;
                sendwindow();
        }
 }
            bcmp(&ws, &winsize, sizeof (ws))) {
                winsize = ws;
                sendwindow();
        }
 }
-#endif
 
 /*
  * Send the window size to the server via the magic escape
 
 /*
  * Send the window size to the server via the magic escape
@@ -388,17 +436,10 @@ sendwindow()
        obuf[1] = 0377;
        obuf[2] = 's';
        obuf[3] = 's';
        obuf[1] = 0377;
        obuf[2] = 's';
        obuf[3] = 's';
-#ifdef sun
-       wp->ws_row = htons(winsize.ts_lines);
-       wp->ws_col = htons(winsize.ts_cols);
-       wp->ws_xpixel = 0;
-       wp->ws_ypixel = 0;
-#else sun
        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);
        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);
-#endif sun
        (void) write(rem, obuf, sizeof(obuf));
 }
 
        (void) write(rem, obuf, sizeof(obuf));
 }
 
@@ -451,28 +492,28 @@ oob()
                /*
                 * Let server know about window size changes
                 */
                /*
                 * Let server know about window size changes
                 */
-               kill(ppid, SIGURG);
+               (void) kill(ppid, SIGUSR1);
        }
        if (!eight && (mark & TIOCPKT_NOSTOP)) {
        }
        if (!eight && (mark & TIOCPKT_NOSTOP)) {
-               ioctl(0, TIOCGETP, (char *)&sb);
+               (void) ioctl(0, TIOCGETP, (char *)&sb);
                sb.sg_flags &= ~CBREAK;
                sb.sg_flags |= RAW;
                sb.sg_flags &= ~CBREAK;
                sb.sg_flags |= RAW;
-               ioctl(0, TIOCSETN, (char *)&sb);
+               (void) ioctl(0, TIOCSETN, (char *)&sb);
                notc.t_stopc = -1;
                notc.t_startc = -1;
                notc.t_stopc = -1;
                notc.t_startc = -1;
-               ioctl(0, TIOCSETC, (char *)&notc);
+               (void) ioctl(0, TIOCSETC, (char *)&notc);
        }
        if (!eight && (mark & TIOCPKT_DOSTOP)) {
        }
        if (!eight && (mark & TIOCPKT_DOSTOP)) {
-               ioctl(0, TIOCGETP, (char *)&sb);
+               (void) ioctl(0, TIOCGETP, (char *)&sb);
                sb.sg_flags &= ~RAW;
                sb.sg_flags |= CBREAK;
                sb.sg_flags &= ~RAW;
                sb.sg_flags |= CBREAK;
-               ioctl(0, TIOCSETN, (char *)&sb);
+               (void) ioctl(0, TIOCSETN, (char *)&sb);
                notc.t_stopc = deftc.t_stopc;
                notc.t_startc = deftc.t_startc;
                notc.t_stopc = deftc.t_stopc;
                notc.t_startc = deftc.t_startc;
-               ioctl(0, TIOCSETC, (char *)&notc);
+               (void) ioctl(0, TIOCSETC, (char *)&notc);
        }
        if (mark & TIOCPKT_FLUSHWRITE) {
        }
        if (mark & TIOCPKT_FLUSHWRITE) {
-               ioctl(1, TIOCFLUSH, (char *)&out);
+               (void) ioctl(1, TIOCFLUSH, (char *)&out);
                for (;;) {
                        if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
                                perror("ioctl");
                for (;;) {
                        if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
                                perror("ioctl");
@@ -494,6 +535,11 @@ oob()
                rcvcnt = 0;
                longjmp(rcvtop, 1);
        }
                rcvcnt = 0;
                longjmp(rcvtop, 1);
        }
+
+       /*
+        * oob does not do FLUSHREAD (alas!)
+        */
+
        /*
         * If we filled the receive buffer while a read was pending,
         * longjmp to the top to restart appropriately.  Don't abort
        /*
         * If we filled the receive buffer while a read was pending,
         * longjmp to the top to restart appropriately.  Don't abort
@@ -506,7 +552,8 @@ oob()
 /*
  * reader: read from remote: line -> 1
  */
 /*
  * reader: read from remote: line -> 1
  */
-reader()
+reader(oldmask)
+       int oldmask;
 {
 #if !defined(BSD) || BSD < 43
        int pid = -getpid();
 {
 #if !defined(BSD) || BSD < 43
        int pid = -getpid();
@@ -516,10 +563,12 @@ reader()
        int n, remaining;
        char *bufp = rcvbuf;
 
        int n, remaining;
        char *bufp = rcvbuf;
 
-       signal(SIGTTOU, SIG_IGN);
-       fcntl(rem, F_SETOWN, pid);
+       (void) signal(SIGTTOU, SIG_IGN);
+       (void) signal(SIGURG, oob);
        ppid = getppid();
        ppid = getppid();
+       (void) fcntl(rem, F_SETOWN, pid);
        (void) setjmp(rcvtop);
        (void) setjmp(rcvtop);
+       (void) sigsetmask(oldmask);
        for (;;) {
                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
                        rcvstate = WRITING;
        for (;;) {
                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
                        rcvstate = WRITING;
@@ -553,8 +602,8 @@ mode(f)
        struct sgttyb sb;
        int     lflags;
 
        struct sgttyb sb;
        int     lflags;
 
-       ioctl(0, TIOCGETP, (char *)&sb);
-       ioctl(0, TIOCLGET, (char *)&lflags);
+       (void) ioctl(0, TIOCGETP, (char *)&sb);
+       (void) ioctl(0, TIOCLGET, (char *)&lflags);
        switch (f) {
 
        case 0:
        switch (f) {
 
        case 0:
@@ -583,23 +632,25 @@ mode(f)
        default:
                return;
        }
        default:
                return;
        }
-       ioctl(0, TIOCSLTC, (char *)ltc);
-       ioctl(0, TIOCSETC, (char *)tc);
-       ioctl(0, TIOCSETN, (char *)&sb);
-       ioctl(0, TIOCLSET, (char *)&lflags);
+       (void) ioctl(0, TIOCSLTC, (char *)ltc);
+       (void) ioctl(0, TIOCSETC, (char *)tc);
+       (void) ioctl(0, TIOCSETN, (char *)&sb);
+       (void) ioctl(0, TIOCLSET, (char *)&lflags);
 }
 
 /*VARARGS*/
 prf(f, a1, a2, a3, a4, a5)
        char *f;
 {
 }
 
 /*VARARGS*/
 prf(f, a1, a2, a3, a4, a5)
        char *f;
 {
+
        fprintf(stderr, f, a1, a2, a3, a4, a5);
        fprintf(stderr, CRLF);
 }
 
 lostpeer()
 {
        fprintf(stderr, f, a1, a2, a3, a4, a5);
        fprintf(stderr, CRLF);
 }
 
 lostpeer()
 {
-       signal(SIGPIPE, SIG_IGN);
+
+       (void) signal(SIGPIPE, SIG_IGN);
        prf("\007Connection closed.");
        done(1);
 }
        prf("\007Connection closed.");
        done(1);
 }