BSD 4_3_Net_2 release
[unix-history] / usr / src / libexec / telnetd / termstat.c
index 6add78d..5b0d26c 100644 (file)
@@ -2,23 +2,37 @@
  * Copyright (c) 1989 Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1989 Regents of the University of California.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted provided
- * that: (1) source distributions retain this entire copyright notice and
- * comment, and (2) distributions including binaries display the following
- * acknowledgement:  ``This product includes software developed by the
- * University of California, Berkeley and its contributors'' in the
- * documentation or other materials provided with the distribution and in
- * all advertising materials mentioning features or use of this software.
- * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 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
-static char sccsid[] = "@(#)termstat.c 5.6 (Berkeley) 6/28/90";
+static char sccsid[] = "@(#)termstat.c 5.10 (Berkeley) 3/22/91";
 #endif /* not lint */
 
 #include "telnetd.h"
 #endif /* not lint */
 
 #include "telnetd.h"
@@ -26,13 +40,13 @@ static char sccsid[] = "@(#)termstat.c      5.6 (Berkeley) 6/28/90";
 /*
  * local variables
  */
 /*
  * local variables
  */
-#ifdef LINEMODE
-static int _terminit = 0;
-static int def_tspeed = -1, def_rspeed = -1;
+int def_tspeed = -1, def_rspeed = -1;
 #ifdef TIOCSWINSZ
 #ifdef TIOCSWINSZ
-static int def_row = 0, def_col = 0;
+int def_row = 0, def_col = 0;
 #endif
 #endif
-#endif LINEMODE
+#ifdef LINEMODE
+static int _terminit = 0;
+#endif /* LINEMODE */
 
 #if    defined(CRAY2) && defined(UNICOS5)
 int    newmap = 1;     /* nonzero if \n maps to ^M^J */
 
 #if    defined(CRAY2) && defined(UNICOS5)
 int    newmap = 1;     /* nonzero if \n maps to ^M^J */
@@ -113,9 +127,11 @@ int        newmap = 1;     /* nonzero if \n maps to ^M^J */
  *        then linemode is off, if server won't SGA, then linemode
  *        is on.
  */
  *        then linemode is off, if server won't SGA, then linemode
  *        is on.
  */
+       void
 localstat()
 {
        void netflush();
 localstat()
 {
        void netflush();
+       int need_will_echo = 0;
 
 #if    defined(CRAY2) && defined(UNICOS5)
        /*
 
 #if    defined(CRAY2) && defined(UNICOS5)
        /*
@@ -123,7 +139,7 @@ localstat()
         * neighborhood.
         */
        newmap = tty_isnewmap();
         * neighborhood.
         */
        newmap = tty_isnewmap();
-#endif defined(CRAY2) && defined(UNICOS5)
+#endif /* defined(CRAY2) && defined(UNICOS5) */
 
        /*
         * Check for state of BINARY options.
 
        /*
         * Check for state of BINARY options.
@@ -170,6 +186,26 @@ localstat()
                tty_setlinemode(uselinemode);
        }
 
                tty_setlinemode(uselinemode);
        }
 
+#if    defined(ENCRYPT)
+       /*
+        * If the terminal is not echoing, but editing is enabled,
+        * something like password input is going to happen, so
+        * if we the other side is not currently sending encrypted
+        * data, ask the other side to start encrypting.
+        */
+       if (his_state_is_will(TELOPT_ENCRYPT)) {
+               static int enc_passwd = 0;
+               if (uselinemode && !tty_isecho() && tty_isediting()
+                   && (enc_passwd == 0) && !decrypt_input) {
+                       encrypt_send_request_start();
+                       enc_passwd = 1;
+               } else if (enc_passwd) {
+                       encrypt_send_request_end();
+                       enc_passwd = 0;
+               }
+       }
+#endif
+
        /*
         * Do echo mode handling as soon as we know what the
         * linemode is going to be.
        /*
         * Do echo mode handling as soon as we know what the
         * linemode is going to be.
@@ -179,11 +215,21 @@ localstat()
         * client should do local echoing.  The state machine will
         * not send anything if it is unnecessary, so don't worry
         * about that here.
         * client should do local echoing.  The state machine will
         * not send anything if it is unnecessary, so don't worry
         * about that here.
+        *
+        * If we need to send the WILL ECHO (because echo is off),
+        * then delay that until after we have changed the MODE.
+        * This way, when the user is turning off both editing
+        * and echo, the client will get editing turned off first.
+        * This keeps the client from going into encryption mode
+        * and then right back out if it is doing auto-encryption
+        * when passwords are being typed.
         */
         */
-       if (tty_isecho() && uselinemode)
-               send_wont(TELOPT_ECHO, 1);
-       else
-               send_will(TELOPT_ECHO, 1);
+       if (uselinemode) {
+               if (tty_isecho())
+                       send_wont(TELOPT_ECHO, 1);
+               else
+                       need_will_echo = 1;
+       }
 
        /*
         * If linemode is being turned off, send appropriate
 
        /*
         * If linemode is being turned off, send appropriate
@@ -191,13 +237,14 @@ localstat()
         */
         if (!uselinemode && linemode) {
 # ifdef        KLUDGELINEMODE
         */
         if (!uselinemode && linemode) {
 # ifdef        KLUDGELINEMODE
-               if (lmodetype == REAL_LINEMODE)
+               if (lmodetype == REAL_LINEMODE) {
 # endif        /* KLUDGELINEMODE */
                        send_dont(TELOPT_LINEMODE, 1);
 # ifdef        KLUDGELINEMODE
 # endif        /* KLUDGELINEMODE */
                        send_dont(TELOPT_LINEMODE, 1);
 # ifdef        KLUDGELINEMODE
-               else if (lmodetype == KLUDGE_LINEMODE)
+               else if (lmodetype == KLUDGE_LINEMODE)
                        send_will(TELOPT_SGA, 1);
 # endif        /* KLUDGELINEMODE */
                        send_will(TELOPT_SGA, 1);
 # endif        /* KLUDGELINEMODE */
+               send_will(TELOPT_ECHO, 1);
                linemode = uselinemode;
                goto done;
        }
                linemode = uselinemode;
                goto done;
        }
@@ -260,7 +307,7 @@ localstat()
                goto done;
 # endif        /* KLUDGELINEMODE */
 
                goto done;
 # endif        /* KLUDGELINEMODE */
 
-       if (linemode) {
+       if (linemode && his_state_is_will(TELOPT_LINEMODE)) {
                /*
                 * If edit mode changed, send edit mode.
                 */
                /*
                 * If edit mode changed, send edit mode.
                 */
@@ -281,10 +328,12 @@ localstat()
                 */
                start_slc(0);
                check_slc();
                 */
                start_slc(0);
                check_slc();
-               end_slc(0);
+               (void) end_slc(0);
        }
 
 done:
        }
 
 done:
+       if (need_will_echo)
+               send_will(TELOPT_ECHO, 1);
        /*
         * Some things should be deferred until after the pty state has
         * been set by the local process.  Do those things that have been
        /*
         * Some things should be deferred until after the pty state has
         * been set by the local process.  Do those things that have been
@@ -311,8 +360,9 @@ done:
  * at a time, and if using kludge linemode, then only linemode may be
  * affected.
  */
  * at a time, and if using kludge linemode, then only linemode may be
  * affected.
  */
+       void
 clientstat(code, parm1, parm2)
 clientstat(code, parm1, parm2)
-register int code, parm1, parm2;
+       register int code, parm1, parm2;
 {
        void netflush();
 
 {
        void netflush();
 
@@ -401,6 +451,17 @@ register int code, parm1, parm2;
                 useeditmode &= ~MODE_ACK;
 
                 if (changed = (useeditmode ^ editmode)) {
                 useeditmode &= ~MODE_ACK;
 
                 if (changed = (useeditmode ^ editmode)) {
+                       /*
+                        * This check is for a timing problem.  If the
+                        * state of the tty has changed (due to the user
+                        * application) we need to process that info
+                        * before we write in the state contained in the
+                        * ack!!!  This gets out the new MODE request,
+                        * and when the ack to that command comes back
+                        * we'll set it and be in the right mode.
+                        */
+                       if (ack)
+                               localstat();
                        if (changed & MODE_EDIT)
                                tty_setedit(useeditmode & MODE_EDIT);
 
                        if (changed & MODE_EDIT)
                                tty_setedit(useeditmode & MODE_EDIT);
 
@@ -436,16 +497,15 @@ register int code, parm1, parm2;
            {
                struct winsize ws;
 
            {
                struct winsize ws;
 
+               def_col = parm1;
+               def_row = parm2;
 #ifdef LINEMODE
                /*
                 * Defer changing window size until after terminal is
                 * initialized.
                 */
 #ifdef LINEMODE
                /*
                 * Defer changing window size until after terminal is
                 * initialized.
                 */
-               if (terminit() == 0) {
-                       def_col = parm1;
-                       def_row = parm2;
+               if (terminit() == 0)
                        return;
                        return;
-               }
 #endif /* LINEMODE */
 
                /*
 #endif /* LINEMODE */
 
                /*
@@ -462,21 +522,23 @@ register int code, parm1, parm2;
        
        case TELOPT_TSPEED:
            {
        
        case TELOPT_TSPEED:
            {
+               def_tspeed = parm1;
+               def_rspeed = parm2;
 #ifdef LINEMODE
                /*
                 * Defer changing the terminal speed.
                 */
 #ifdef LINEMODE
                /*
                 * Defer changing the terminal speed.
                 */
-               if (terminit() == 0) {
-                       def_tspeed = parm1;
-                       def_rspeed = parm2;
+               if (terminit() == 0)
                        return;
                        return;
-               }
 #endif /* LINEMODE */
                /*
                 * Change terminal speed as requested by client.
 #endif /* LINEMODE */
                /*
                 * Change terminal speed as requested by client.
+                * We set the receive speed first, so that if we can't
+                * store seperate receive and transmit speeds, the transmit
+                * speed will take precedence.
                 */
                 */
-               tty_tspeed(parm1);
                tty_rspeed(parm2);
                tty_rspeed(parm2);
+               tty_tspeed(parm1);
                set_termbuf();
 
                break;
                set_termbuf();
 
                break;
@@ -500,11 +562,13 @@ register int code, parm1, parm2;
 }  /* end of clientstat */
 
 #if    defined(CRAY2) && defined(UNICOS5)
 }  /* end of clientstat */
 
 #if    defined(CRAY2) && defined(UNICOS5)
+       void
 termstat()
 {
        needtermstat = 1;
 }
 
 termstat()
 {
        needtermstat = 1;
 }
 
+       void
 _termstat()
 {
        needtermstat = 0;
 _termstat()
 {
        needtermstat = 0;
@@ -523,6 +587,7 @@ _termstat()
  * function is called when the pty state has been processed for the first time. 
  * It calls other functions that do things that were deferred in each module.
  */
  * function is called when the pty state has been processed for the first time. 
  * It calls other functions that do things that were deferred in each module.
  */
+       void
 defer_terminit()
 {
 
 defer_terminit()
 {
 
@@ -538,6 +603,7 @@ defer_terminit()
        if (def_col || def_row) {
                struct winsize ws;
 
        if (def_col || def_row) {
                struct winsize ws;
 
+               bzero((char *)&ws, sizeof(ws));
                ws.ws_col = def_col;
                ws.ws_row = def_row;
                (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
                ws.ws_col = def_col;
                ws.ws_row = def_row;
                (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
@@ -556,7 +622,8 @@ defer_terminit()
  *
  * Returns true if the pty state has been processed yet.
  */
  *
  * Returns true if the pty state has been processed yet.
  */
-int terminit()
+       int
+terminit()
 {
        return _terminit;
 
 {
        return _terminit;