Mods from DDP, et al, for LFLOW, TSPEED, and NAWS support.
authorGregory Minshall <minshall@ucbvax.Berkeley.EDU>
Tue, 21 Mar 1989 15:52:26 +0000 (07:52 -0800)
committerGregory Minshall <minshall@ucbvax.Berkeley.EDU>
Tue, 21 Mar 1989 15:52:26 +0000 (07:52 -0800)
SCCS-vsn: usr.bin/telnet/externs.h 1.14
SCCS-vsn: usr.bin/telnet/telnet.c 5.39
SCCS-vsn: usr.bin/telnet/sys_bsd.c 1.17
SCCS-vsn: usr.bin/telnet/commands.c 1.16

usr/src/usr.bin/telnet/commands.c
usr/src/usr.bin/telnet/externs.h
usr/src/usr.bin/telnet/sys_bsd.c
usr/src/usr.bin/telnet/telnet.c

index a46e81e..8e004b9 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)commands.c 1.15 (Berkeley) %G%";
+static char sccsid[] = "@(#)commands.c 1.16 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -879,14 +879,25 @@ togcrmod()
 /*VARARGS*/
 suspend()
 {
 /*VARARGS*/
 suspend()
 {
-       setcommandmode();
+    setcommandmode();
 #if    defined(unix)
 #if    defined(unix)
+    {
+       long oldrows, oldcols, newrows, newcols;
+
+       TerminalWindowSize(&oldrows, &oldcols);
        (void) kill(0, SIGTSTP);
        (void) kill(0, SIGTSTP);
+       TerminalWindowSize(&newrows, &newcols);
+       if ((oldrows != newrows) || (oldcols != newcols)) {
+           if (connected) {
+               sendnaws();
+           }
+       }
+    }
 #endif /* defined(unix) */
 #endif /* defined(unix) */
-       /* reget parameters in case they were changed */
-       TerminalSaveState();
-       setconnmode();
-       return 1;
+    /* reget parameters in case they were changed */
+    TerminalSaveState();
+    setconnmode();
+    return 1;
 }
 
 /*VARARGS*/
 }
 
 /*VARARGS*/
@@ -1079,6 +1090,7 @@ tn(argc, argv)
     struct servent *sp = 0;
     static char        hnamebuf[32];
     unsigned long inet_addr();
     struct servent *sp = 0;
     static char        hnamebuf[32];
     unsigned long inet_addr();
+    extern char *inet_ntoa();
 
 
 #if defined(MSDOS)
 
 
 #if defined(MSDOS)
@@ -1143,8 +1155,6 @@ tn(argc, argv)
 #if    !defined(htons)
            u_short htons();
 #endif /* !defined(htons) */
 #if    !defined(htons)
            u_short htons();
 #endif /* !defined(htons) */
-
-           sin.sin_port = atoi(argv[2]);
            sin.sin_port = htons(sin.sin_port);
        }
        telnetport = 0;
            sin.sin_port = htons(sin.sin_port);
        }
        telnetport = 0;
@@ -1159,7 +1169,7 @@ tn(argc, argv)
        }
        telnetport = 1;
     }
        }
        telnetport = 1;
     }
-    printf("Trying...\n");
+    printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
     do {
        net = socket(AF_INET, SOCK_STREAM, 0);
        if (net < 0) {
     do {
        net = socket(AF_INET, SOCK_STREAM, 0);
        if (net < 0) {
@@ -1174,7 +1184,6 @@ tn(argc, argv)
 #if    defined(h_addr)         /* In 4.3, this is a #define */
            if (host && host->h_addr_list[1]) {
                int oerrno = errno;
 #if    defined(h_addr)         /* In 4.3, this is a #define */
            if (host && host->h_addr_list[1]) {
                int oerrno = errno;
-               extern char *inet_ntoa();
 
                fprintf(stderr, "telnet: connect to address %s: ",
                                                inet_ntoa(sin.sin_addr));
 
                fprintf(stderr, "telnet: connect to address %s: ",
                                                inet_ntoa(sin.sin_addr));
@@ -1183,15 +1192,13 @@ tn(argc, argv)
                host->h_addr_list++;
                memcpy((caddr_t)&sin.sin_addr, 
                        host->h_addr_list[0], host->h_length);
                host->h_addr_list++;
                memcpy((caddr_t)&sin.sin_addr, 
                        host->h_addr_list[0], host->h_length);
-               fprintf(stderr, "Trying %s...\n",
-                       inet_ntoa(sin.sin_addr));
                (void) NetClose(net);
                continue;
            }
 #endif /* defined(h_addr) */
            perror("telnet: Unable to connect to remote host");
            return 0;
                (void) NetClose(net);
                continue;
            }
 #endif /* defined(h_addr) */
            perror("telnet: Unable to connect to remote host");
            return 0;
-           }
+       }
        connected++;
     } while (connected == 0);
     (void) call(status, "status", "notmuch", 0);
        connected++;
     } while (connected == 0);
     (void) call(status, "status", "notmuch", 0);
@@ -1318,8 +1325,8 @@ command(top)
     setcommandmode();
     if (!top) {
        putchar('\n');
     setcommandmode();
     if (!top) {
        putchar('\n');
-    } else {
 #if    defined(unix)
 #if    defined(unix)
+    } else {
        signal(SIGINT, SIG_DFL);
        signal(SIGQUIT, SIG_DFL);
 #endif /* defined(unix) */
        signal(SIGINT, SIG_DFL);
        signal(SIGQUIT, SIG_DFL);
 #endif /* defined(unix) */
@@ -1334,6 +1341,9 @@ command(top)
        if (line[0] == 0)
            break;
        makeargv();
        if (line[0] == 0)
            break;
        makeargv();
+       if (margv[0] == 0) {
+           break;
+       }
        c = getcmd(margv[0]);
        if (Ambiguous(c)) {
            printf("?Ambiguous command\n");
        c = getcmd(margv[0]);
        if (Ambiguous(c)) {
            printf("?Ambiguous command\n");
index 502b2f4..8b0f656 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)externs.h   1.13 (Berkeley) %G%
+ *     @(#)externs.h   1.14 (Berkeley) %G%
  */
 
 #include <stdio.h>
  */
 
 #include <stdio.h>
@@ -34,6 +34,7 @@ extern int
     globalmode,                /* Mode tty should be in */
     In3270,                    /* Are we in 3270 mode? */
     telnetport,                /* Are we connected to the telnet port? */
     globalmode,                /* Mode tty should be in */
     In3270,                    /* Are we in 3270 mode? */
     telnetport,                /* Are we connected to the telnet port? */
+    localflow,         /* Flow control handled locally */
     localchars,                /* we recognize interrupt/quit */
     donelclchars,              /* the user has set "localchars" */
     showoptions,
     localchars,                /* we recognize interrupt/quit */
     donelclchars,              /* the user has set "localchars" */
     showoptions,
@@ -78,6 +79,7 @@ extern void
     init_3270(),
     printoption(),
     printsub(),
     init_3270(),
     printoption(),
     printsub(),
+    sendnaws(),
     setconnmode(),
     setcommandmode(),
     setneturg(),
     setconnmode(),
     setcommandmode(),
     setneturg(),
index ffd7da4..e4b2bbc 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)sys_bsd.c  1.16 (Berkeley) %G%";
+static char sccsid[] = "@(#)sys_bsd.c  1.17 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -218,7 +218,7 @@ register int f;
                sb.sg_flags |= ECHO|CRMOD;
            }
            sb.sg_erase = sb.sg_kill = -1;
                sb.sg_flags |= ECHO|CRMOD;
            }
            sb.sg_erase = sb.sg_kill = -1;
-           if (f == 6) {
+           if (localflow || (f == 6)) {
                tc = &tc3;
                tc3 = notc;
                    /* get XON, XOFF characters */
                tc = &tc3;
                tc3 = notc;
                    /* get XON, XOFF characters */
@@ -301,6 +301,46 @@ register int f;
     }
 }
 
     }
 }
 
+void
+TerminalSpeeds(ispeed, ospeed)
+long *ispeed;
+long *ospeed;
+{
+    /*
+     * The order here is important.  The index of each speed needs to
+     * correspond with the sgtty structure value for that speed.
+     *
+     * Additionally, the search algorithm assumes the table is in
+     * ascending sequence.
+     */
+    static int ttyspeeds[] = {
+           0, 50, 75, 110, 134, 150, 200, 300,
+           600, 1200, 1800, 2400, 4800, 9600, 19200, 38400 };
+#define NUMSPEEDS sizeof ttyspeeds/sizeof ttyspeeds[0]
+
+    if ((ottyb.sg_ospeed < 0) || (ottyb.sg_ospeed > NUMSPEEDS) ||
+       (ottyb.sg_ispeed < 0) || (ottyb.sg_ispeed > NUMSPEEDS)) {
+       ExitString("Invalid terminal speed.");
+       /*NOTREACHED*/
+    } else {
+       *ispeed = ttyspeeds[ottyb.sg_ispeed];
+       *ospeed = ttyspeeds[ottyb.sg_ospeed];
+    }
+}
+
+int
+TerminalWindowSize(rows, cols)
+long *rows, *cols;
+{
+    struct winsize ws;
+
+    if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) < 0) {
+       return 0;
+    }
+    *rows = ws.ws_row;
+    *cols = ws.ws_col;
+    return 1;
+}
 
 int
 NetClose(fd)
 
 int
 NetClose(fd)
@@ -371,6 +411,14 @@ intr2()
     }
 }
 
     }
 }
 
+static void
+sendwin()
+{
+    if (connected) {
+       sendnaws();
+    }
+}
+
 static void
 doescape()
 {
 static void
 doescape()
 {
@@ -383,6 +431,7 @@ sys_telnet_init()
     (void) signal(SIGINT, (int (*)())intr);
     (void) signal(SIGQUIT, (int (*)())intr2);
     (void) signal(SIGPIPE, (int (*)())deadpeer);
     (void) signal(SIGINT, (int (*)())intr);
     (void) signal(SIGQUIT, (int (*)())intr2);
     (void) signal(SIGPIPE, (int (*)())deadpeer);
+    (void) signal(SIGWINCH, (int (*)())sendwin);
 
     setconnmode();
 
 
     setconnmode();
 
index 0d1d528..ea90378 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)telnet.c   5.38 (Berkeley) %G%";
+static char sccsid[] = "@(#)telnet.c   5.39 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -84,6 +84,7 @@ int
        flushout,       /* flush output */
        autoflush = 0,  /* flush output when interrupting? */
        autosynch,      /* send interrupt characters with SYNCH? */
        flushout,       /* flush output */
        autoflush = 0,  /* flush output when interrupting? */
        autosynch,      /* send interrupt characters with SYNCH? */
+       localflow,      /* we handle flow control locally */
        localchars,     /* we recognize interrupt/quit */
        donelclchars,   /* the user has set "localchars" */
        donebinarytoggle,       /* the user has put us in binary */
        localchars,     /* we recognize interrupt/quit */
        donelclchars,   /* the user has set "localchars" */
        donebinarytoggle,       /* the user has put us in binary */
@@ -145,7 +146,7 @@ init_telnet()
     ClearArray(hisopts);
     ClearArray(myopts);
 
     ClearArray(hisopts);
     ClearArray(myopts);
 
-    connected = In3270 = ISend = donebinarytoggle = 0;
+    connected = In3270 = ISend = localflow = donebinarytoggle = 0;
 
     SYNCHing = 0;
 
 
     SYNCHing = 0;
 
@@ -307,9 +308,12 @@ dooption(option)
                break;
 
 #      if defined(TN3270)
                break;
 
 #      if defined(TN3270)
-       case TELOPT_EOR:
-       case TELOPT_BINARY:
+       case TELOPT_EOR:                /* end of record */
+       case TELOPT_BINARY:             /* binary mode */
 #      endif   /* defined(TN3270) */
 #      endif   /* defined(TN3270) */
+       case TELOPT_NAWS:               /* window size */
+       case TELOPT_TSPEED:             /* terminal speed */
+       case TELOPT_LFLOW:              /* local flow control */
        case TELOPT_TTYPE:              /* terminal type option */
        case TELOPT_SGA:                /* no big deal */
                fmt = will;
        case TELOPT_TTYPE:              /* terminal type option */
        case TELOPT_SGA:                /* no big deal */
                fmt = will;
@@ -334,6 +338,8 @@ dooption(option)
  *     Currently we recognize:
  *
  *             Terminal type, send request.
  *     Currently we recognize:
  *
  *             Terminal type, send request.
+ *             Terminal speed (send request).
+ *             Local flow control (is request).
  */
 
 static void
  */
 
 static void
@@ -373,7 +379,34 @@ suboption()
                /*NOTREACHED*/
            }
        }
                /*NOTREACHED*/
            }
        }
+       break;
+    case TELOPT_TSPEED:
+       if ((subbuffer[1]&0xff) == TELQUAL_SEND) {
+           long *ospeed,*ispeed;
+           char speedbuf[41];
+           char *getenv();
+           int len;
 
 
+           TerminalSpeeds(&ispeed, &ospeed);
+
+           sprintf(speedbuf, "%d,%d", ospeed, ispeed);
+           len = strlen(speedbuf);
+
+           if ((len + 4+2) < NETROOM()) {
+               printring(&netoring, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TSPEED,
+                   TELQUAL_IS, speedbuf, IAC, SE);
+           }
+       }
+       break;
+    case TELOPT_LFLOW:
+       if ((subbuffer[1]&0xff) == 1) {
+           localflow = 1;
+       } else if ((subbuffer[1]&0xff) == 0) {
+           localflow = 0;
+       }
+       setcommandmode();
+       setconnmode();
+       break;
     default:
        break;
     }
     default:
        break;
     }
@@ -577,6 +610,13 @@ telrcv()
            if (!myopts[c])
                dooption(c);
            SetIn3270();
            if (!myopts[c])
                dooption(c);
            SetIn3270();
+           if (c == TELOPT_NAWS) {
+               sendnaws();
+           } else if (c == TELOPT_LFLOW) {
+               localflow = 1;
+               setcommandmode();
+               setconnmode();
+           }
            telrcv_state = TS_DATA;
            continue;
 
            telrcv_state = TS_DATA;
            continue;
 
@@ -810,6 +850,15 @@ telnet()
        if (!myopts[TELOPT_TTYPE]) {
            dooption(TELOPT_TTYPE);
        }
        if (!myopts[TELOPT_TTYPE]) {
            dooption(TELOPT_TTYPE);
        }
+       if (!myopts[TELOPT_NAWS]) {
+           dooption(TELOPT_NAWS);
+       }
+       if (!myopts[TELOPT_TSPEED]) {
+           dooption(TELOPT_TSPEED);
+       }
+       if (!myopts[TELOPT_LFLOW]) {
+           dooption(TELOPT_LFLOW);
+       }
     }
 #   endif /* !defined(TN3270) */
 
     }
 #   endif /* !defined(TN3270) */
 
@@ -1050,3 +1099,34 @@ sendbrk()
        dosynch();
     }
 }
        dosynch();
     }
 }
+/*
+ * Send a window size update to the remote system.
+ */
+
+void
+sendnaws()
+{
+    long rows, cols;
+
+#define        NETADDCHAR(x) \
+    { \
+       if (((x) & 0xff) == 0xff) { \
+           NET2ADD(IAC, IAC) \
+       } else { \
+           NETADD(x) \
+       } \
+    }
+#define        NETADDSHORT(x)  { NETADDCHAR(x >> 8); NETADDCHAR(x & 0xff) }
+
+    if (TerminalWindowSize(&rows, &cols) == 0) {       /* Failed */
+       return;
+    }
+
+    if (NETROOM() >= 3 + 8 + 2) {
+       NET2ADD(IAC, SB);
+       NETADD(TELOPT_NAWS);
+       NETADDSHORT(cols);
+       NETADDSHORT(rows);
+       NET2ADD(IAC, SE);
+    }
+}