386BSD 0.1 development
[unix-history] / usr / src / usr.bin / rlogin / rlogin.c
index febab79..2ba715c 100644 (file)
@@ -1,8 +1,34 @@
-/*-
+/*
  * Copyright (c) 1983, 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1983, 1990 The Regents of the University of California.
  * All rights reserved.
  *
-%sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
@@ -12,19 +38,19 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)rlogin.c   5.24 (Berkeley) %G%";
+static char sccsid[] = "@(#)rlogin.c   5.33 (Berkeley) 3/1/91";
 #endif /* not lint */
 
 /*
  * $Source: mit/rlogin/RCS/rlogin.c,v $
 #endif /* not lint */
 
 /*
  * $Source: mit/rlogin/RCS/rlogin.c,v $
- * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall Exp Locker: kfall $
+ * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall
+ *     Exp Locker: kfall $
  */
 
 /*
  * rlogin - remote login
  */
 #include <sys/param.h>
  */
 
 /*
  * rlogin - remote login
  */
 #include <sys/param.h>
-#include <sys/errno.h>
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <sys/signal.h>
 #include <sys/file.h>
 #include <sys/socket.h>
 #include <sys/signal.h>
@@ -33,23 +59,26 @@ static char sccsid[] = "@(#)rlogin.c        5.24 (Berkeley) %G%";
 #include <sys/wait.h>
 
 #include <netinet/in.h>
 #include <sys/wait.h>
 
 #include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 #include <netdb.h>
 
 #include <sgtty.h>
 #include <setjmp.h>
 #include <netdb.h>
 
 #include <sgtty.h>
 #include <setjmp.h>
-#include <errno.h>
 #include <varargs.h>
 #include <varargs.h>
+#include <errno.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <strings.h>
+#include <string.h>
 
 #ifdef KERBEROS
 
 #ifdef KERBEROS
+#include <kerberosIV/des.h>
 #include <kerberosIV/krb.h>
 
 CREDENTIALS cred;
 Key_schedule schedule;
 #include <kerberosIV/krb.h>
 
 CREDENTIALS cred;
 Key_schedule schedule;
-int use_kerberos = 1, encrypt;
+int use_kerberos = 1, doencrypt;
 char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
 extern char *krb_realmofhost();
 #endif
 char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
 extern char *krb_realmofhost();
 #endif
@@ -65,7 +94,10 @@ extern char *krb_realmofhost();
 
 extern int errno;
 int eight, litout, rem;
 
 extern int errno;
 int eight, litout, rem;
-char cmdchar;
+
+int noescape;
+u_char escapechar = '~';
+
 char *speeds[] = {
        "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200",
        "1800", "2400", "4800", "9600", "19200", "38400"
 char *speeds[] = {
        "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200",
        "1800", "2400", "4800", "9600", "19200", "38400"
@@ -98,12 +130,12 @@ main(argc, argv)
        int argoff, ch, dflag, one, uid;
        char *host, *p, *user, term[1024];
        void lostpeer();
        int argoff, ch, dflag, one, uid;
        char *host, *p, *user, term[1024];
        void lostpeer();
+       u_char getescape();
        char *getenv();
 
        argoff = dflag = 0;
        one = 1;
        host = user = NULL;
        char *getenv();
 
        argoff = dflag = 0;
        one = 1;
        host = user = NULL;
-       cmdchar = '~';
 
        if (p = rindex(argv[0], '/'))
                ++p;
 
        if (p = rindex(argv[0], '/'))
                ++p;
@@ -120,15 +152,18 @@ main(argc, argv)
        }
 
 #ifdef KERBEROS
        }
 
 #ifdef KERBEROS
-#define        OPTIONS "8KLde:k:l:x"
+#define        OPTIONS "8EKLde:k:l:x"
 #else
 #else
-#define        OPTIONS "8KLde:l:"
+#define        OPTIONS "8EKLde:l:"
 #endif
        while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
                switch(ch) {
                case '8':
                        eight = 1;
                        break;
 #endif
        while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
                switch(ch) {
                case '8':
                        eight = 1;
                        break;
+               case 'E':
+                       noescape = 1;
+                       break;
                case 'K':
 #ifdef KERBEROS
                        use_kerberos = 0;
                case 'K':
 #ifdef KERBEROS
                        use_kerberos = 0;
@@ -141,7 +176,7 @@ main(argc, argv)
                        dflag = 1;
                        break;
                case 'e':
                        dflag = 1;
                        break;
                case 'e':
-                       cmdchar = optarg[0];
+                       escapechar = getescape(optarg);
                        break;
 #ifdef KERBEROS
                case 'k':
                        break;
 #ifdef KERBEROS
                case 'k':
@@ -152,11 +187,13 @@ main(argc, argv)
                case 'l':
                        user = optarg;
                        break;
                case 'l':
                        user = optarg;
                        break;
+#ifdef CRYPT
 #ifdef KERBEROS
                case 'x':
 #ifdef KERBEROS
                case 'x':
-                       encrypt = 1;
+                       doencrypt = 1;
                        des_set_key(cred.session, schedule);
                        break;
                        des_set_key(cred.session, schedule);
                        break;
+#endif
 #endif
                case '?':
                default:
 #endif
                case '?':
                default:
@@ -183,11 +220,11 @@ main(argc, argv)
        sp = NULL;
 #ifdef KERBEROS
        if (use_kerberos) {
        sp = NULL;
 #ifdef KERBEROS
        if (use_kerberos) {
-               sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp");
+               sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp");
                if (sp == NULL) {
                        use_kerberos = 0;
                        warning("can't get entry for %s/tcp service",
                if (sp == NULL) {
                        use_kerberos = 0;
                        warning("can't get entry for %s/tcp service",
-                           encrypt ? "eklogin" : "klogin");
+                           doencrypt ? "eklogin" : "klogin");
                }
        }
 #endif
                }
        }
 #endif
@@ -218,10 +255,12 @@ try_connect:
                if (dest_realm == NULL)
                        dest_realm = krb_realmofhost(host);
 
                if (dest_realm == NULL)
                        dest_realm = krb_realmofhost(host);
 
-               if (encrypt)
+#ifdef CRYPT
+               if (doencrypt)
                        rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
                            dest_realm, &cred, schedule);
                else
                        rem = krcmd_mutual(&host, sp->s_port, user, term, 0,
                            dest_realm, &cred, schedule);
                else
+#endif /* CRYPT */
                        rem = krcmd(&host, sp->s_port, user, term, 0,
                            dest_realm);
                if (rem < 0) {
                        rem = krcmd(&host, sp->s_port, user, term, 0,
                            dest_realm);
                if (rem < 0) {
@@ -239,16 +278,18 @@ try_connect:
                        goto try_connect;
                }
        } else {
                        goto try_connect;
                }
        } else {
-               if (encrypt) {
+#ifdef CRYPT
+               if (doencrypt) {
                        (void)fprintf(stderr,
                            "rlogin: the -x flag requires Kerberos authentication.\n");
                        exit(1);
                }
                        (void)fprintf(stderr,
                            "rlogin: the -x flag requires Kerberos authentication.\n");
                        exit(1);
                }
+#endif /* CRYPT */
                rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
        }
 #else
        rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
                rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
        }
 #else
        rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0);
-#endif
+#endif /* KERBEROS */
 
        if (rem < 0)
                exit(1);
 
        if (rem < 0)
                exit(1);
@@ -257,6 +298,9 @@ try_connect:
            setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0)
                (void)fprintf(stderr, "rlogin: setsockopt: %s.\n",
                    strerror(errno));
            setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0)
                (void)fprintf(stderr, "rlogin: setsockopt: %s.\n",
                    strerror(errno));
+       one = IPTOS_LOWDELAY;
+       if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0)
+               perror("rlogin: setsockopt TOS (ignored)");
 
        (void)setuid(uid);
        doit(omask);
 
        (void)setuid(uid);
        doit(omask);
@@ -335,19 +379,20 @@ setsignal(sig, act)
 done(status)
        int status;
 {
 done(status)
        int status;
 {
-       int w;
+       int w, wstatus;
 
        mode(0);
        if (child > 0) {
                /* make sure catch_child does not snap it up */
                (void)signal(SIGCHLD, SIG_DFL);
                if (kill(child, SIGKILL) >= 0)
 
        mode(0);
        if (child > 0) {
                /* make sure catch_child does not snap it up */
                (void)signal(SIGCHLD, SIG_DFL);
                if (kill(child, SIGKILL) >= 0)
-                       while ((w = wait((union wait *)0)) > 0 && w != child);
+                       while ((w = wait(&wstatus)) > 0 && w != child);
        }
        exit(status);
 }
 
 int dosigwinch;
        }
        exit(status);
 }
 
 int dosigwinch;
+void sigwinch();
 
 /*
  * This is called when the reader process gets the out-of-band (urgent)
 
 /*
  * This is called when the reader process gets the out-of-band (urgent)
@@ -356,8 +401,6 @@ int dosigwinch;
 void
 writeroob()
 {
 void
 writeroob()
 {
-       void sigwinch();
-
        if (dosigwinch == 0) {
                sendwindow();
                (void)signal(SIGWINCH, sigwinch);
        if (dosigwinch == 0) {
                sendwindow();
                (void)signal(SIGWINCH, sigwinch);
@@ -372,7 +415,8 @@ catch_child()
        int pid;
 
        for (;;) {
        int pid;
 
        for (;;) {
-               pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0);
+               pid = wait3((int *)&status,
+                   WNOHANG|WUNTRACED, (struct rusage *)0);
                if (pid == 0)
                        return;
                /* if the child (reader) dies, just quit */
                if (pid == 0)
                        return;
                /* if the child (reader) dies, just quit */
@@ -384,14 +428,14 @@ catch_child()
 
 /*
  * writer: write to remote: 0 -> line.
 
 /*
  * writer: write to remote: 0 -> line.
- * ~.  terminate
- * ~^Z suspend rlogin process.
- * ~^Y  suspend rlogin process, but leave reader alone.
+ * ~.                          terminate
+ * ~^Z                         suspend rlogin process.
+ * ~<delayed-suspend char>     suspend rlogin process, but leave reader alone.
  */
 writer()
 {
  */
 writer()
 {
-       char c;
        register int bol, local, n;
        register int bol, local, n;
+       char c;
 
        bol = 1;                        /* beginning of line */
        local = 0;
 
        bol = 1;                        /* beginning of line */
        local = 0;
@@ -411,8 +455,7 @@ writer()
                 */
                if (bol) {
                        bol = 0;
                 */
                if (bol) {
                        bol = 0;
-                       if (c == cmdchar) {
-                               bol = 0;
+                       if (!noescape && c == escapechar) {
                                local = 1;
                                continue;
                        }
                                local = 1;
                                continue;
                        }
@@ -428,23 +471,26 @@ writer()
                                stop(c);
                                continue;
                        }
                                stop(c);
                                continue;
                        }
-                       if (c != cmdchar) {
+                       if (c != escapechar)
+#ifdef CRYPT
 #ifdef KERBEROS
 #ifdef KERBEROS
-                               if (encrypt) {
-                                       (void)des_write(rem, &cmdchar, 1);
-                               else
+                               if (doencrypt)
+                                       (void)des_write(rem, &escapechar, 1);
+                               else
 #endif
 #endif
-                                       (void)write(rem, &cmdchar, 1);
-                       }
+#endif
+                                       (void)write(rem, &escapechar, 1);
                }
 
                }
 
+#ifdef CRYPT
 #ifdef KERBEROS
 #ifdef KERBEROS
-               if (encrypt) {
+               if (doencrypt) {
                        if (des_write(rem, &c, 1) == 0) {
                                msg("line gone");
                                break;
                        }
                } else
                        if (des_write(rem, &c, 1) == 0) {
                                msg("line gone");
                                break;
                        }
                } else
+#endif
 #endif
                        if (write(rem, &c, 1) == 0) {
                                msg("line gone");
 #endif
                        if (write(rem, &c, 1) == 0) {
                                msg("line gone");
@@ -464,7 +510,7 @@ register char c;
 
        p = buf;
        c &= 0177;
 
        p = buf;
        c &= 0177;
-       *p++ = cmdchar;
+       *p++ = escapechar;
        if (c < ' ') {
                *p++ = '^';
                *p++ = c + '@';
        if (c < ' ') {
                *p++ = '^';
                *p++ = c + '@';
@@ -475,7 +521,7 @@ register char c;
                *p++ = c;
        *p++ = '\r';
        *p++ = '\n';
                *p++ = c;
        *p++ = '\r';
        *p++ = '\n';
-       (void)write(1, buf, p - buf);
+       (void)write(STDOUT_FILENO, buf, p - buf);
 }
 
 stop(cmdc)
 }
 
 stop(cmdc)
@@ -519,10 +565,12 @@ sendwindow()
        wp->ws_xpixel = htons(winsize.ws_xpixel);
        wp->ws_ypixel = htons(winsize.ws_ypixel);
 
        wp->ws_xpixel = htons(winsize.ws_xpixel);
        wp->ws_ypixel = htons(winsize.ws_ypixel);
 
+#ifdef CRYPT
 #ifdef KERBEROS
 #ifdef KERBEROS
-       if(encrypt)
+       if(doencrypt)
                (void)des_write(rem, obuf, sizeof(obuf));
        else
                (void)des_write(rem, obuf, sizeof(obuf));
        else
+#endif
 #endif
                (void)write(rem, obuf, sizeof(obuf));
 }
 #endif
                (void)write(rem, obuf, sizeof(obuf));
 }
@@ -544,7 +592,7 @@ oob()
        int atmark, n, out, rcvd;
        char waste[BUFSIZ], mark;
 
        int atmark, n, out, rcvd;
        char waste[BUFSIZ], mark;
 
-       out = FWRITE;
+       out = O_RDWR;
        rcvd = 0;
        while (recv(rem, &mark, 1, MSG_OOB) < 0)
                switch (errno) {
        rcvd = 0;
        while (recv(rem, &mark, 1, MSG_OOB) < 0)
                switch (errno) {
@@ -649,7 +697,7 @@ reader(omask)
        for (;;) {
                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
                        rcvstate = WRITING;
        for (;;) {
                while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
                        rcvstate = WRITING;
-                       n = write(1, bufp, remaining);
+                       n = write(STDOUT_FILENO, bufp, remaining);
                        if (n < 0) {
                                if (errno != EINTR)
                                        return(-1);
                        if (n < 0) {
                                if (errno != EINTR)
                                        return(-1);
@@ -661,10 +709,12 @@ reader(omask)
                rcvcnt = 0;
                rcvstate = READING;
 
                rcvcnt = 0;
                rcvstate = READING;
 
+#ifdef CRYPT
 #ifdef KERBEROS
 #ifdef KERBEROS
-               if (encrypt)
+               if (doencrypt)
                        rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
                else
                        rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf));
                else
+#endif
 #endif
                        rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
                if (rcvcnt == 0)
 #endif
                        rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
                if (rcvcnt == 0)
@@ -762,9 +812,13 @@ usage()
        (void)fprintf(stderr,
            "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n",
 #ifdef KERBEROS
        (void)fprintf(stderr,
            "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n",
 #ifdef KERBEROS
-           "8Lx", " [-k realm] ");
+#ifdef CRYPT
+           "8ELx", " [-k realm] ");
 #else
 #else
-           "8L", " ");
+           "8EL", " [-k realm] ");
+#endif
+#else
+           "8EL", " ");
 #endif
        exit(1);
 }
 #endif
        exit(1);
 }
@@ -774,7 +828,6 @@ usage()
  * Suns and others.  Suns have only a `ttysize', so we convert it to a winsize.
  */
 #ifdef sun
  * 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;
 get_window_size(fd, wp)
        int fd;
        struct winsize *wp;
@@ -791,3 +844,27 @@ get_window_size(fd, wp)
        return(0);
 }
 #endif
        return(0);
 }
 #endif
+
+u_char
+getescape(p)
+       register char *p;
+{
+       long val;
+       int len;
+
+       if ((len = strlen(p)) == 1)     /* use any single char, including '\' */
+               return((u_char)*p);
+                                       /* otherwise, \nnn */
+       if (*p == '\\' && len >= 2 && len <= 4) {
+               val = strtol(++p, (char **)NULL, 8);
+               for (;;) {
+                       if (!*++p)
+                               return((u_char)val);
+                       if (*p < '0' || *p > '8')
+                               break;
+               }
+       }
+       msg("illegal option value -- e");
+       usage();
+       /* NOTREACHED */
+}