LCOV - code coverage report
Current view: top level - telnet - telnet.c (source / functions) Hit Total Coverage
Test: GNU inetutils Lines: 63 1020 6.2 %
Date: 2015-05-12 15:20:19 Functions: 5 58 8.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
       3             :   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
       4             :   2015 Free Software Foundation, Inc.
       5             : 
       6             :   This file is part of GNU Inetutils.
       7             : 
       8             :   GNU Inetutils is free software: you can redistribute it and/or modify
       9             :   it under the terms of the GNU General Public License as published by
      10             :   the Free Software Foundation, either version 3 of the License, or (at
      11             :   your option) any later version.
      12             : 
      13             :   GNU Inetutils is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :   General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU General Public License
      19             :   along with this program.  If not, see `http://www.gnu.org/licenses/'. */
      20             : 
      21             : /*
      22             :  * Copyright (c) 1988, 1990, 1993
      23             :  *      The Regents of the University of California.  All rights reserved.
      24             :  *
      25             :  * Redistribution and use in source and binary forms, with or without
      26             :  * modification, are permitted provided that the following conditions
      27             :  * are met:
      28             :  * 1. Redistributions of source code must retain the above copyright
      29             :  *    notice, this list of conditions and the following disclaimer.
      30             :  * 2. Redistributions in binary form must reproduce the above copyright
      31             :  *    notice, this list of conditions and the following disclaimer in the
      32             :  *    documentation and/or other materials provided with the distribution.
      33             :  * 3. Neither the name of the University nor the names of its contributors
      34             :  *    may be used to endorse or promote products derived from this software
      35             :  *    without specific prior written permission.
      36             :  *
      37             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      38             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      39             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      40             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      41             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      42             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      43             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      44             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      45             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      46             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      47             :  * SUCH DAMAGE.
      48             :  */
      49             : 
      50             : #include <config.h>
      51             : 
      52             : #include <sys/types.h>
      53             : 
      54             : #if defined unix || defined __unix || defined __unix__
      55             : # include <signal.h>
      56             : /* By the way, we need to include curses.h before telnet.h since,
      57             :  * among other things, telnet.h #defines 'DO', which is a variable
      58             :  * declared in curses.h.
      59             :  */
      60             : #endif /* unix || __unix || __unix__ */
      61             : 
      62             : #include <arpa/telnet.h>
      63             : 
      64             : #include <ctype.h>
      65             : #include <stdlib.h>
      66             : 
      67             : #include <libinetutils.h>
      68             : 
      69             : #include "ring.h"
      70             : 
      71             : #include "defines.h"
      72             : #include "externs.h"
      73             : #include "types.h"
      74             : #include "general.h"
      75             : 
      76             : #ifdef HAVE_TERMCAP_TGETENT
      77             : # include <termcap.h>
      78             : #elif defined HAVE_CURSES_TGETENT
      79             : # include <curses.h>
      80             : # include <term.h>
      81             : #endif
      82             : 
      83             : #ifdef AUTHENTICATION
      84             : # include <libtelnet/auth.h>
      85             : #endif
      86             : #ifdef ENCRYPTION
      87             : # include <libtelnet/encrypt.h>
      88             : #endif
      89             : #if defined AUTHENTICATION || defined ENCRYPTION
      90             : # include <libtelnet/misc.h>
      91             : #endif
      92             : 
      93             : 
      94             : #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
      95             : 
      96             : static unsigned char subbuffer[SUBBUFSIZE], *subpointer, *subend;       /* buffer for sub-options */
      97             : #define SB_CLEAR()      subpointer = subbuffer;
      98             : #define SB_TERM()       { subend = subpointer; SB_CLEAR(); }
      99             : #define SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
     100             :                                 *subpointer++ = (c); \
     101             :                         }
     102             : 
     103             : #define SB_GET()        ((*subpointer++)&0xff)
     104             : #define SB_PEEK()       ((*subpointer)&0xff)
     105             : #define SB_EOF()        (subpointer >= subend)
     106             : #define SB_LEN()        (subend - subpointer)
     107             : 
     108             : char options[256] = { 0 };              /* The combined options */
     109             : char do_dont_resp[256] = { 0 };
     110             : char will_wont_resp[256] = { 0 };
     111             : 
     112             : int eight = 0, autologin = 0,   /* Autologin anyone? */
     113             :   skiprc = 0, connected, showoptions, In3270,   /* Are we in 3270 mode? */
     114             :   ISend,                        /* trying to send network data in */
     115             :   debug = 0, crmod, netdata,    /* Print out network data flow */
     116             :   crlf,                         /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
     117             : #if defined TN3270
     118             :   noasynchtty = 0,              /* User specified "-noasynch" on command line */
     119             :   noasynchnet = 0,              /* User specified "-noasynch" on command line */
     120             :   askedSGA = 0,                 /* We have talked about suppress go ahead */
     121             : #endif
     122             :   /* defined(TN3270) */
     123             :   telnetport, SYNCHing,         /* we are in TELNET SYNCH mode */
     124             :   flushout,                     /* flush output */
     125             :   autoflush = 0,                /* flush output when interrupting? */
     126             :   autosynch,                    /* send interrupt characters with SYNCH? */
     127             :   localflow,                    /* we handle flow control locally */
     128             :   restartany,                   /* if flow control enabled, restart on any character */
     129             :   localchars,                   /* we recognize interrupt/quit */
     130             :   donelclchars,                 /* the user has set "localchars" */
     131             :   donebinarytoggle,             /* the user has put us in binary */
     132             :   dontlecho,                    /* do we suppress local echoing right now? */
     133             :   globalmode;
     134             : 
     135             : char *prompt = 0;
     136             : 
     137             : cc_t escape;
     138             : cc_t rlogin;
     139             : #ifdef  KLUDGELINEMODE
     140             : cc_t echoc;
     141             : #endif
     142             : 
     143             : /*
     144             :  * Telnet receiver states for fsm
     145             :  */
     146             : #define TS_DATA         0
     147             : #define TS_IAC          1
     148             : #define TS_WILL         2
     149             : #define TS_WONT         3
     150             : #define TS_DO           4
     151             : #define TS_DONT         5
     152             : #define TS_CR           6
     153             : #define TS_SB           7       /* sub-option collection */
     154             : #define TS_SE           8       /* looking for sub-option end */
     155             : 
     156             : static int telrcv_state;
     157             : #ifdef  OLD_ENVIRON
     158             : unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
     159             : #else
     160             : # define telopt_environ TELOPT_NEW_ENVIRON
     161             : #endif
     162             : 
     163             : jmp_buf toplevel;
     164             : jmp_buf peerdied;
     165             : 
     166             : int flushline;
     167             : int linemode;
     168             : 
     169             : #ifdef  KLUDGELINEMODE
     170             : int kludgelinemode = 1;
     171             : #endif
     172             : 
     173             : /*
     174             :  * The following are some clocks used to decide how to interpret
     175             :  * the relationship between various variables.
     176             :  */
     177             : 
     178             : Clocks clocks;
     179             : 
     180             : 
     181             : 
     182             : /*
     183             :  * Initialize telnet environment.
     184             :  */
     185             : 
     186             : void
     187           3 : init_telnet (void)
     188             : {
     189           3 :   env_init ();
     190             : 
     191           3 :   SB_CLEAR ();
     192             : 
     193           3 :   connected = In3270 = ISend = localflow = donebinarytoggle = 0;
     194             : #if defined AUTHENTICATION || defined ENCRYPTION
     195             :   auth_encrypt_connect (connected);
     196             : #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION)  */
     197           3 :   restartany = -1;
     198             : 
     199           3 :   SYNCHing = 0;
     200             : 
     201             :   /* Don't change NetTrace */
     202             : 
     203           3 :   escape = CONTROL (']');
     204           3 :   rlogin = _POSIX_VDISABLE;
     205             : #ifdef  KLUDGELINEMODE
     206           3 :   echoc = CONTROL ('E');
     207             : #endif
     208             : 
     209           3 :   flushline = 1;
     210           3 :   telrcv_state = TS_DATA;
     211           3 : }
     212             : 
     213             : /*
     214             :  * These routines are in charge of sending option negotiations
     215             :  * to the other side.
     216             :  *
     217             :  * The basic idea is that we send the negotiation if either side
     218             :  * is in disagreement as to what the current state should be.
     219             :  */
     220             : 
     221             : void
     222           0 : send_do (register int c, register int init)
     223             : {
     224           0 :   if (init)
     225             :     {
     226           0 :       if (((do_dont_resp[c] == 0) && my_state_is_do (c)) ||
     227           0 :           my_want_state_is_do (c))
     228           0 :         return;
     229           0 :       set_my_want_state_do (c);
     230           0 :       do_dont_resp[c]++;
     231             :     }
     232           0 :   NET2ADD (IAC, DO);
     233           0 :   NETADD (c);
     234           0 :   printoption ("SENT", DO, c);
     235             : }
     236             : 
     237             : void
     238           0 : send_dont (register int c, register int init)
     239             : {
     240           0 :   if (init)
     241             :     {
     242           0 :       if (((do_dont_resp[c] == 0) && my_state_is_dont (c)) ||
     243           0 :           my_want_state_is_dont (c))
     244           0 :         return;
     245           0 :       set_my_want_state_dont (c);
     246           0 :       do_dont_resp[c]++;
     247             :     }
     248           0 :   NET2ADD (IAC, DONT);
     249           0 :   NETADD (c);
     250           0 :   printoption ("SENT", DONT, c);
     251             : }
     252             : 
     253             : void
     254           0 : send_will (register int c, register int init)
     255             : {
     256           0 :   if (init)
     257             :     {
     258           0 :       if (((will_wont_resp[c] == 0) && my_state_is_will (c)) ||
     259           0 :           my_want_state_is_will (c))
     260           0 :         return;
     261           0 :       set_my_want_state_will (c);
     262           0 :       will_wont_resp[c]++;
     263             :     }
     264           0 :   NET2ADD (IAC, WILL);
     265           0 :   NETADD (c);
     266           0 :   printoption ("SENT", WILL, c);
     267             : }
     268             : 
     269             : void
     270           0 : send_wont (register int c, register int init)
     271             : {
     272           0 :   if (init)
     273             :     {
     274           0 :       if (((will_wont_resp[c] == 0) && my_state_is_wont (c)) ||
     275           0 :           my_want_state_is_wont (c))
     276           0 :         return;
     277           0 :       set_my_want_state_wont (c);
     278           0 :       will_wont_resp[c]++;
     279             :     }
     280           0 :   NET2ADD (IAC, WONT);
     281           0 :   NETADD (c);
     282           0 :   printoption ("SENT", WONT, c);
     283             : }
     284             : 
     285             : 
     286             : void
     287           0 : willoption (int option)
     288             : {
     289           0 :   int new_state_ok = 0;
     290             : 
     291           0 :   if (do_dont_resp[option])
     292             :     {
     293           0 :       --do_dont_resp[option];
     294           0 :       if (do_dont_resp[option] && my_state_is_do (option))
     295           0 :         --do_dont_resp[option];
     296             :     }
     297             : 
     298           0 :   if ((do_dont_resp[option] == 0) && my_want_state_is_dont (option))
     299             :     {
     300             : 
     301           0 :       switch (option)
     302             :         {
     303             : 
     304             :         case TELOPT_ECHO:
     305             : #if defined TN3270
     306             :           /*
     307             :            * The following is a pain in the rear-end.
     308             :            * Various IBM servers (some versions of Wiscnet,
     309             :            * possibly Fibronics/Spartacus, and who knows who
     310             :            * else) will NOT allow us to send "DO SGA" too early
     311             :            * in the setup proceedings.  On the other hand,
     312             :            * 4.2 servers (telnetd) won't set SGA correctly.
     313             :            * So, we are stuck.  Empirically (but, based on
     314             :            * a VERY small sample), the IBM servers don't send
     315             :            * out anything about ECHO, so we postpone our sending
     316             :            * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
     317             :            * DO send).
     318             :            */
     319             :           {
     320             :             if (askedSGA == 0)
     321             :               {
     322             :                 askedSGA = 1;
     323             :                 if (my_want_state_is_dont (TELOPT_SGA))
     324             :                   send_do (TELOPT_SGA, 1);
     325             :               }
     326             :           }
     327             :           /* Fall through */
     328             :         case TELOPT_EOR:
     329             : #endif /* defined(TN3270) */
     330             :         case TELOPT_BINARY:
     331             :         case TELOPT_SGA:
     332           0 :           settimer (modenegotiated);
     333             :           /* FALL THROUGH */
     334             :         case TELOPT_STATUS:
     335             : #if defined AUTHENTICATION
     336             :         case TELOPT_AUTHENTICATION:
     337             : #endif
     338             : #ifdef  ENCRYPTION
     339             :         case TELOPT_ENCRYPT:
     340             : #endif /* ENCRYPTION */
     341           0 :           new_state_ok = 1;
     342           0 :           break;
     343             : 
     344             :         case TELOPT_TM:
     345           0 :           if (flushout)
     346           0 :             flushout = 0;
     347             :           /*
     348             :            * Special case for TM.  If we get back a WILL,
     349             :            * pretend we got back a WONT.
     350             :            */
     351           0 :           set_my_want_state_dont (option);
     352           0 :           set_my_state_dont (option);
     353           0 :           return;               /* Never reply to TM will's/wont's */
     354             : 
     355             :         case TELOPT_LINEMODE:
     356             :         default:
     357           0 :           break;
     358             :         }
     359             : 
     360           0 :       if (new_state_ok)
     361             :         {
     362           0 :           set_my_want_state_do (option);
     363           0 :           send_do (option, 0);
     364           0 :           setconnmode (0);      /* possibly set new tty mode */
     365             :         }
     366             :       else
     367             :         {
     368           0 :           do_dont_resp[option]++;
     369           0 :           send_dont (option, 0);
     370             :         }
     371             :     }
     372           0 :   set_my_state_do (option);
     373             : #ifdef  ENCRYPTION
     374             :   if (option == TELOPT_ENCRYPT)
     375             :     encrypt_send_support ();
     376             : #endif /* ENCRYPTION */
     377             : }
     378             : 
     379             : void
     380           0 : wontoption (int option)
     381             : {
     382           0 :   if (do_dont_resp[option])
     383             :     {
     384           0 :       --do_dont_resp[option];
     385           0 :       if (do_dont_resp[option] && my_state_is_dont (option))
     386           0 :         --do_dont_resp[option];
     387             :     }
     388             : 
     389           0 :   if ((do_dont_resp[option] == 0) && my_want_state_is_do (option))
     390             :     {
     391             : 
     392           0 :       switch (option)
     393             :         {
     394             : 
     395             : #ifdef  KLUDGELINEMODE
     396             :         case TELOPT_SGA:
     397           0 :           if (!kludgelinemode)
     398           0 :             break;
     399             :           /* FALL THROUGH */
     400             : #endif
     401             :         case TELOPT_ECHO:
     402           0 :           settimer (modenegotiated);
     403           0 :           break;
     404             : 
     405             :         case TELOPT_TM:
     406           0 :           if (flushout)
     407           0 :             flushout = 0;
     408           0 :           set_my_want_state_dont (option);
     409           0 :           set_my_state_dont (option);
     410           0 :           return;               /* Never reply to TM will's/wont's */
     411             : 
     412             :         default:
     413           0 :           break;
     414             :         }
     415           0 :       set_my_want_state_dont (option);
     416           0 :       if (my_state_is_do (option))
     417           0 :         send_dont (option, 0);
     418           0 :       setconnmode (0);          /* Set new tty mode */
     419             :     }
     420           0 :   else if (option == TELOPT_TM)
     421             :     {
     422             :       /*
     423             :        * Special case for TM.
     424             :        */
     425           0 :       if (flushout)
     426           0 :         flushout = 0;
     427           0 :       set_my_want_state_dont (option);
     428             :     }
     429           0 :   set_my_state_dont (option);
     430             : }
     431             : 
     432             : static void
     433           0 : dooption (int option)
     434             : {
     435           0 :   int new_state_ok = 0;
     436             : 
     437           0 :   if (will_wont_resp[option])
     438             :     {
     439           0 :       --will_wont_resp[option];
     440           0 :       if (will_wont_resp[option] && my_state_is_will (option))
     441           0 :         --will_wont_resp[option];
     442             :     }
     443             : 
     444           0 :   if (will_wont_resp[option] == 0)
     445             :     {
     446           0 :       if (my_want_state_is_wont (option))
     447             :         {
     448             : 
     449           0 :           switch (option)
     450             :             {
     451             : 
     452             :             case TELOPT_TM:
     453             :               /*
     454             :                * Special case for TM.  We send a WILL, but pretend
     455             :                * we sent WONT.
     456             :                */
     457           0 :               send_will (option, 0);
     458           0 :               set_my_want_state_wont (TELOPT_TM);
     459           0 :               set_my_state_wont (TELOPT_TM);
     460           0 :               return;
     461             : 
     462             : #if defined TN3270
     463             :             case TELOPT_EOR:    /* end of record */
     464             : #endif /* defined(TN3270) */
     465             :             case TELOPT_BINARY: /* binary mode */
     466             :             case TELOPT_NAWS:   /* window size */
     467             :             case TELOPT_TSPEED: /* terminal speed */
     468             :             case TELOPT_LFLOW:  /* local flow control */
     469             :             case TELOPT_TTYPE:  /* terminal type option */
     470             :             case TELOPT_SGA:    /* no big deal */
     471             : #ifdef  ENCRYPTION
     472             :             case TELOPT_ENCRYPT:        /* encryption variable option */
     473             : #endif /* ENCRYPTION */
     474           0 :               new_state_ok = 1;
     475           0 :               break;
     476             : 
     477             :             case TELOPT_NEW_ENVIRON:    /* New environment variable option */
     478             : #ifdef  OLD_ENVIRON
     479             :               if (my_state_is_will (TELOPT_OLD_ENVIRON))
     480             :                 send_wont (TELOPT_OLD_ENVIRON, 1);      /* turn off the old */
     481             :               goto env_common;
     482             :             case TELOPT_OLD_ENVIRON:    /* Old environment variable option */
     483             :               if (my_state_is_will (TELOPT_NEW_ENVIRON))
     484             :                 break;          /* Don't enable if new one is in use! */
     485             :             env_common:
     486             :               telopt_environ = option;
     487             : #endif
     488           0 :               new_state_ok = 1;
     489           0 :               break;
     490             : 
     491             : #if defined AUTHENTICATION
     492             :             case TELOPT_AUTHENTICATION:
     493             :               if (autologin)
     494             :                 new_state_ok = 1;
     495             :               break;
     496             : #endif
     497             : 
     498             :             case TELOPT_XDISPLOC:       /* X Display location */
     499           0 :               if (env_getvalue ("DISPLAY"))
     500           0 :                 new_state_ok = 1;
     501           0 :               break;
     502             : 
     503             :             case TELOPT_LINEMODE:
     504             : #ifdef  KLUDGELINEMODE
     505           0 :               kludgelinemode = 0;
     506           0 :               send_do (TELOPT_SGA, 1);
     507             : #endif
     508           0 :               set_my_want_state_will (TELOPT_LINEMODE);
     509           0 :               send_will (option, 0);
     510           0 :               set_my_state_will (TELOPT_LINEMODE);
     511           0 :               slc_init ();
     512           0 :               return;
     513             : 
     514             :             case TELOPT_ECHO:   /* We're never going to echo... */
     515             :             default:
     516           0 :               break;
     517             :             }
     518             : 
     519           0 :           if (new_state_ok)
     520             :             {
     521           0 :               set_my_want_state_will (option);
     522           0 :               send_will (option, 0);
     523           0 :               setconnmode (0);  /* Set new tty mode */
     524             :             }
     525             :           else
     526             :             {
     527           0 :               will_wont_resp[option]++;
     528           0 :               send_wont (option, 0);
     529             :             }
     530             :         }
     531             :       else
     532             :         {
     533             :           /*
     534             :            * Handle options that need more things done after the
     535             :            * other side has acknowledged the option.
     536             :            */
     537           0 :           switch (option)
     538             :             {
     539             :             case TELOPT_LINEMODE:
     540             : #ifdef  KLUDGELINEMODE
     541           0 :               kludgelinemode = 0;
     542           0 :               send_do (TELOPT_SGA, 1);
     543             : #endif
     544           0 :               set_my_state_will (option);
     545           0 :               slc_init ();
     546           0 :               send_do (TELOPT_SGA, 0);
     547           0 :               return;
     548             :             }
     549             :         }
     550             :     }
     551           0 :   set_my_state_will (option);
     552             : }
     553             : 
     554             : static void
     555           0 : dontoption (int option)
     556             : {
     557             : 
     558           0 :   if (will_wont_resp[option])
     559             :     {
     560           0 :       --will_wont_resp[option];
     561           0 :       if (will_wont_resp[option] && my_state_is_wont (option))
     562           0 :         --will_wont_resp[option];
     563             :     }
     564             : 
     565           0 :   if ((will_wont_resp[option] == 0) && my_want_state_is_will (option))
     566             :     {
     567           0 :       switch (option)
     568             :         {
     569             :         case TELOPT_LINEMODE:
     570           0 :           linemode = 0;         /* put us back to the default state */
     571           0 :           break;
     572             : #ifdef  OLD_ENVIRON
     573             :         case TELOPT_NEW_ENVIRON:
     574             :           /*
     575             :            * The new environ option wasn't recognized, try
     576             :            * the old one.
     577             :            */
     578             :           send_will (TELOPT_OLD_ENVIRON, 1);
     579             :           telopt_environ = TELOPT_OLD_ENVIRON;
     580             :           break;
     581             : #endif
     582             :         }
     583             :       /* we always accept a DONT */
     584           0 :       set_my_want_state_wont (option);
     585           0 :       if (my_state_is_will (option))
     586           0 :         send_wont (option, 0);
     587           0 :       setconnmode (0);          /* Set new tty mode */
     588             :     }
     589           0 :   set_my_state_wont (option);
     590           0 : }
     591             : 
     592             : int
     593           0 : is_unique (register char *name, register char **as, register char **ae)
     594             : {
     595             :   register char **ap;
     596             :   register int n;
     597             : 
     598           0 :   n = strlen (name) + 1;
     599           0 :   for (ap = as; ap < ae; ap++)
     600           0 :     if (strncasecmp (*ap, name, n) == 0)
     601           0 :       return (0);
     602           0 :   return (1);
     603             : }
     604             : 
     605             : /*
     606             :  * Given a buffer returned by tgetent(), this routine will turn
     607             :  * the pipe separated list of names in the buffer into an array
     608             :  * of pointers to null terminated names.  We toss out any bad,
     609             :  * duplicate, or verbose names (names with spaces).
     610             :  */
     611             : 
     612             : static char *name_unknown = "UNKNOWN";
     613             : static char *unknown[] = { 0, 0 };
     614             : 
     615             : char **
     616           0 : mklist (char *buf, char *name)
     617             : {
     618             :   register int n;
     619             :   register char c, *cp, **argvp, *cp2, **argv, **avt;
     620             : 
     621           0 :   if (name)
     622             :     {
     623           0 :       if ((int) strlen (name) > 40)
     624             :         {
     625           0 :           name = 0;
     626           0 :           unknown[0] = name_unknown;
     627             :         }
     628             :       else
     629             :         {
     630           0 :           unknown[0] = name;
     631           0 :           upcase (name);
     632             :         }
     633             :     }
     634             :   else
     635           0 :     unknown[0] = name_unknown;
     636             : 
     637             :   /*
     638             :    * An empty capability buffer finishes the analysis.
     639             :    */
     640           0 :   if (!buf || !*buf)
     641           0 :     return (unknown);
     642             : 
     643             :   /*
     644             :    * Count the number of alias names.
     645             :    * Stop at the first field separator, a colon.
     646             :    */
     647           0 :   for (n = 1, cp = buf; *cp && *cp != ':'; cp++)
     648             :     {
     649           0 :       if (*cp == '|')
     650           0 :         n++;
     651             :     }
     652             : 
     653             :   /*
     654             :    * Allocate an array to hold the name pointers.
     655             :    */
     656           0 :   argv = (char **) malloc ((n + 3) * sizeof (char *));
     657           0 :   if (argv == 0)
     658           0 :     return (unknown);
     659             : 
     660             :   /*
     661             :    * Fill the array of pointers with the established aliases.
     662             :    * Reserve the first slot for the preferred name.
     663             :    */
     664           0 :   argvp = argv + 1;
     665           0 :   *argv = *argvp = 0;
     666           0 :   n = 0;                /* Positive: name uses white space.  */
     667             : 
     668           0 :   for (cp = cp2 = buf; (c = *cp); cp++)
     669             :     {
     670           0 :       if (c == '|' || c == ':')         /* Delimiters */
     671             :         {
     672           0 :           *cp++ = '\0';
     673             :           /*
     674             :            * Skip entries that have spaces or are over 40
     675             :            * characters long.  If this is our environment
     676             :            * name, then put it up front.  Otherwise, as
     677             :            * long as this is not a duplicate name (case
     678             :            * insensitive) add it to the list.
     679             :            */
     680           0 :           if (n || (cp - cp2 > 41))
     681             :             ;                   /* Ignore the just scanned name.  */
     682           0 :           else if (name && (strncasecmp (name, cp2, cp - cp2) == 0))
     683           0 :             *argv = cp2;        /* Preferred name, exact match.  */
     684           0 :           else if (is_unique (cp2, argv + 1, argvp))
     685             :             {
     686           0 :               *argvp++ = cp2;
     687           0 :               *argvp = 0;       /* Prevent looking forward.  */
     688             :             }
     689             : 
     690             :           /* Abort parsing at first field delimiter.  */
     691           0 :           if (c == ':')
     692           0 :             break;
     693             : 
     694             :           /*
     695             :            * Skip multiple delimiters. Reset CP2 to
     696             :            * the beginning of the next name. Reset N,
     697             :            * the flag for names with spaces.
     698             :            */
     699           0 :           while ((c = *cp) == '|')
     700           0 :             cp++;
     701             : 
     702           0 :           cp2 = cp;             /* Proceed to next alias name.  */
     703           0 :           n = 0;
     704             :         }
     705             :       /*
     706             :        * Skip entries with spaces or non-ascii values.
     707             :        * Convert lower case letters to upper case.
     708             :        */
     709           0 :       if ((c == ' ') || !isascii (c))
     710           0 :         n = 1;
     711           0 :       else if (islower (c))
     712           0 :         *cp = toupper (c);
     713             :     }
     714             : 
     715             :   /*
     716             :    * Check for an old V6 2 character name.  If the second
     717             :    * name points to the beginning of the buffer, and is
     718             :    * only 2 characters long, move it to the end of the array.
     719             :    */
     720           0 :   if ((argv[1] == buf) && (strlen (argv[1]) == 2))
     721             :     {
     722           0 :       --argvp;
     723           0 :       for (avt = &argv[1]; avt < argvp; avt++)
     724           0 :         *avt = *(avt + 1);
     725           0 :       *argvp++ = buf;
     726             :     }
     727             : 
     728             :   /*
     729             :    * Duplicate last name, for TTYPE option, and null
     730             :    * terminate the array.  If we didn't find a match on
     731             :    * our terminal name, put that name at the beginning.
     732             :    */
     733           0 :   cp = *(argvp - 1);
     734           0 :   *argvp++ = cp;
     735           0 :   *argvp = 0;
     736             : 
     737           0 :   if (*argv == 0)
     738             :     {
     739           0 :       if (name)
     740           0 :         *argv = name;
     741             :       else
     742             :         {
     743           0 :           --argvp;
     744           0 :           for (avt = argv; avt < argvp; avt++)
     745           0 :             *avt = *(avt + 1);
     746             :         }
     747             :     }
     748           0 :   if (*argv)
     749           0 :     return (argv);
     750             :   else
     751           0 :     return (unknown);
     752             : }
     753             : 
     754             : /* Claimed to be ignored by contemporary implementations,
     755             :  * but still modified by FreeBSD and NetBSD.
     756             :  * mklist will examine this buffer, so erase it
     757             :  * to cover corner cases.
     758             :  */
     759             : char termbuf[2048] = { 0 };
     760             : 
     761             : static int
     762           0 : init_term (char *tname, int *errp)
     763             : {
     764           0 :   int err = -1;
     765             : 
     766             : #ifdef HAVE_TGETENT
     767           0 :   err = tgetent (termbuf, tname);
     768           0 :   if (err == 1)
     769             :     {
     770           0 :       termbuf[sizeof (termbuf) - 1] = '\0';
     771           0 :       if (errp)
     772           0 :         *errp = 1;
     773           0 :       return (0);
     774             :     }
     775             : #endif /* HAVE_TGETENT */
     776           0 :   if (errp)
     777           0 :     *errp = 0;
     778           0 :   return (-1);
     779             : }
     780             : 
     781             : int resettermname = 1;
     782             : 
     783             : char *
     784           0 : gettermname (void)
     785             : {
     786             :   char *tname;
     787             :   static char **tnamep = 0;
     788             :   static char **next;
     789             :   int err;
     790             : 
     791           0 :   if (resettermname)
     792             :     {
     793           0 :       resettermname = 0;
     794           0 :       if (tnamep && tnamep != unknown)
     795           0 :         free (tnamep);
     796           0 :       if ((tname = (char *) env_getvalue ("TERM")) &&
     797           0 :           (init_term (tname, &err) == 0))
     798             :         {
     799           0 :           tnamep = mklist (termbuf, tname);
     800             :         }
     801             :       else
     802             :         {
     803           0 :           if (tname && ((int) strlen (tname) <= 40))
     804             :             {
     805           0 :               unknown[0] = tname;
     806           0 :               upcase (tname);
     807             :             }
     808             :           else
     809           0 :             unknown[0] = name_unknown;
     810           0 :           tnamep = unknown;
     811             :         }
     812           0 :       next = tnamep;
     813             :     }
     814           0 :   if (*next == 0)
     815           0 :     next = tnamep;
     816           0 :   return (*next++);
     817             : }
     818             : 
     819             : /*
     820             :  * suboption()
     821             :  *
     822             :  *      Look at the sub-option buffer, and try to be helpful to the other
     823             :  * side.
     824             :  *
     825             :  *      Currently we recognize:
     826             :  *
     827             :  *              Terminal type, send request.
     828             :  *              Terminal speed (send request).
     829             :  *              Local flow control (is request).
     830             :  *              Linemode
     831             :  */
     832             : 
     833             : static void
     834           0 : suboption (void)
     835             : {
     836             :   unsigned char subchar;
     837             : 
     838           0 :   printsub ('<', subbuffer, SB_LEN () + 2);
     839           0 :   switch (subchar = SB_GET ())
     840             :     {
     841             :     case TELOPT_TTYPE:
     842           0 :       if (my_want_state_is_wont (TELOPT_TTYPE))
     843           0 :         return;
     844           0 :       if (SB_EOF () || SB_GET () != TELQUAL_SEND)
     845             :         {
     846           0 :           return;
     847             :         }
     848             :       else
     849             :         {
     850             :           char *name;
     851             :           unsigned char temp[50];
     852             :           int len;
     853             : 
     854             : #if defined TN3270
     855             :           if (tn3270_ttype ())
     856             :             {
     857             :               return;
     858             :             }
     859             : #endif /* defined(TN3270) */
     860           0 :           name = gettermname ();
     861           0 :           len = strlen (name) + 4 + 2;
     862           0 :           if (len < NETROOM ())
     863             :             {
     864           0 :               sprintf ((char *) temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
     865             :                        TELQUAL_IS, name, IAC, SE);
     866           0 :               ring_supply_data (&netoring, temp, len);
     867           0 :               printsub ('>', &temp[2], len - 2);
     868             :             }
     869             :           else
     870             :             {
     871           0 :               ExitString ("No room in buffer for terminal type.\n", 1);
     872             :             }
     873             :         }
     874           0 :       break;
     875             :     case TELOPT_TSPEED:
     876           0 :       if (my_want_state_is_wont (TELOPT_TSPEED))
     877           0 :         return;
     878           0 :       if (SB_EOF ())
     879           0 :         return;
     880           0 :       if (SB_GET () == TELQUAL_SEND)
     881             :         {
     882             :           long ospeed, ispeed;
     883             :           unsigned char temp[50];
     884             :           int len;
     885             : 
     886           0 :           TerminalSpeeds (&ispeed, &ospeed);
     887             : 
     888           0 :           sprintf ((char *) temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED,
     889             :                    TELQUAL_IS, (int) ospeed, (int) ispeed, IAC, SE);
     890           0 :           len = strlen ((char *) temp + 4) + 4; /* temp[3] is 0 ... */
     891             : 
     892           0 :           if (len < NETROOM ())
     893             :             {
     894           0 :               ring_supply_data (&netoring, temp, len);
     895           0 :               printsub ('>', temp + 2, len - 2);
     896             :             }
     897             : /*@*/
     898             :           else
     899           0 :             printf ("lm_will: not enough room in buffer\n");
     900             :         }
     901           0 :       break;
     902             :     case TELOPT_LFLOW:
     903           0 :       if (my_want_state_is_wont (TELOPT_LFLOW))
     904           0 :         return;
     905           0 :       if (SB_EOF ())
     906           0 :         return;
     907           0 :       switch (SB_GET ())
     908             :         {
     909             :         case LFLOW_RESTART_ANY:
     910           0 :           restartany = 1;
     911           0 :           break;
     912             :         case LFLOW_RESTART_XON:
     913           0 :           restartany = 0;
     914           0 :           break;
     915             :         case LFLOW_ON:
     916           0 :           localflow = 1;
     917           0 :           break;
     918             :         case LFLOW_OFF:
     919           0 :           localflow = 0;
     920           0 :           break;
     921             :         default:
     922           0 :           return;
     923             :         }
     924           0 :       setcommandmode ();
     925           0 :       setconnmode (0);
     926           0 :       break;
     927             : 
     928             :     case TELOPT_LINEMODE:
     929           0 :       if (my_want_state_is_wont (TELOPT_LINEMODE))
     930           0 :         return;
     931           0 :       if (SB_EOF ())
     932           0 :         return;
     933           0 :       switch (SB_GET ())
     934             :         {
     935             :         case WILL:
     936           0 :           lm_will (subpointer, SB_LEN ());
     937           0 :           break;
     938             :         case WONT:
     939           0 :           lm_wont (subpointer, SB_LEN ());
     940           0 :           break;
     941             :         case DO:
     942           0 :           lm_do (subpointer, SB_LEN ());
     943           0 :           break;
     944             :         case DONT:
     945           0 :           lm_dont (subpointer, SB_LEN ());
     946           0 :           break;
     947             :         case LM_SLC:
     948           0 :           slc (subpointer, SB_LEN ());
     949           0 :           break;
     950             :         case LM_MODE:
     951           0 :           lm_mode (subpointer, SB_LEN (), 0);
     952           0 :           break;
     953             :         default:
     954           0 :           break;
     955             :         }
     956           0 :       break;
     957             : 
     958             : #ifdef  OLD_ENVIRON
     959             :     case TELOPT_OLD_ENVIRON:
     960             : #endif
     961             :     case TELOPT_NEW_ENVIRON:
     962           0 :       if (SB_EOF ())
     963           0 :         return;
     964           0 :       switch (SB_PEEK ())
     965             :         {
     966             :         case TELQUAL_IS:
     967             :         case TELQUAL_INFO:
     968           0 :           if (my_want_state_is_dont (subchar))
     969           0 :             return;
     970           0 :           break;
     971             :         case TELQUAL_SEND:
     972           0 :           if (my_want_state_is_wont (subchar))
     973             :             {
     974           0 :               return;
     975             :             }
     976           0 :           break;
     977             :         default:
     978           0 :           return;
     979             :         }
     980           0 :       env_opt (subpointer, SB_LEN ());
     981           0 :       break;
     982             : 
     983             :     case TELOPT_XDISPLOC:
     984           0 :       if (my_want_state_is_wont (TELOPT_XDISPLOC))
     985           0 :         return;
     986           0 :       if (SB_EOF ())
     987           0 :         return;
     988           0 :       if (SB_GET () == TELQUAL_SEND)
     989             :         {
     990             :           unsigned char temp[50], *dp;
     991             :           int len;
     992             : 
     993           0 :           if ((dp = env_getvalue ("DISPLAY")) == NULL)
     994             :             {
     995             :               /*
     996             :                * Something happened, we no longer have a DISPLAY
     997             :                * variable.  So, turn off the option.
     998             :                */
     999           0 :               send_wont (TELOPT_XDISPLOC, 1);
    1000           0 :               break;
    1001             :             }
    1002           0 :           sprintf ((char *) temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
    1003             :                    TELQUAL_IS, dp, IAC, SE);
    1004           0 :           len = strlen ((char *) temp + 4) + 4; /* temp[3] is 0 ... */
    1005             : 
    1006           0 :           if (len < NETROOM ())
    1007             :             {
    1008           0 :               ring_supply_data (&netoring, temp, len);
    1009           0 :               printsub ('>', temp + 2, len - 2);
    1010             :             }
    1011             : /*@*/
    1012             :           else
    1013           0 :             printf ("lm_will: not enough room in buffer\n");
    1014             :         }
    1015           0 :       break;
    1016             : 
    1017             : #if defined AUTHENTICATION
    1018             :     case TELOPT_AUTHENTICATION:
    1019             :       {
    1020             :         if (!autologin)
    1021             :           break;
    1022             :         if (SB_EOF ())
    1023             :           return;
    1024             :         switch (SB_GET ())
    1025             :           {
    1026             :           case TELQUAL_IS:
    1027             :             if (my_want_state_is_dont (TELOPT_AUTHENTICATION))
    1028             :               return;
    1029             :             auth_is (subpointer, SB_LEN ());
    1030             :             break;
    1031             :           case TELQUAL_SEND:
    1032             :             if (my_want_state_is_wont (TELOPT_AUTHENTICATION))
    1033             :               return;
    1034             :             auth_send (subpointer, SB_LEN ());
    1035             :             break;
    1036             :           case TELQUAL_REPLY:
    1037             :             if (my_want_state_is_wont (TELOPT_AUTHENTICATION))
    1038             :               return;
    1039             :             auth_reply (subpointer, SB_LEN ());
    1040             :             break;
    1041             :           case TELQUAL_NAME:
    1042             :             if (my_want_state_is_dont (TELOPT_AUTHENTICATION))
    1043             :               return;
    1044             :             auth_name (subpointer, SB_LEN ());
    1045             :             break;
    1046             :           }
    1047             :       }
    1048             :       break;
    1049             : #endif
    1050             : #ifdef  ENCRYPTION
    1051             :     case TELOPT_ENCRYPT:
    1052             :       if (SB_EOF ())
    1053             :         return;
    1054             :       switch (SB_GET ())
    1055             :         {
    1056             :         case ENCRYPT_START:
    1057             :           if (my_want_state_is_dont (TELOPT_ENCRYPT))
    1058             :             return;
    1059             :           encrypt_start (subpointer, SB_LEN ());
    1060             :           break;
    1061             :         case ENCRYPT_END:
    1062             :           if (my_want_state_is_dont (TELOPT_ENCRYPT))
    1063             :             return;
    1064             :           encrypt_end ();
    1065             :           break;
    1066             :         case ENCRYPT_SUPPORT:
    1067             :           if (my_want_state_is_wont (TELOPT_ENCRYPT))
    1068             :             return;
    1069             :           encrypt_support (subpointer, SB_LEN ());
    1070             :           break;
    1071             :         case ENCRYPT_REQSTART:
    1072             :           if (my_want_state_is_wont (TELOPT_ENCRYPT))
    1073             :             return;
    1074             :           encrypt_request_start (subpointer, SB_LEN ());
    1075             :           break;
    1076             :         case ENCRYPT_REQEND:
    1077             :           if (my_want_state_is_wont (TELOPT_ENCRYPT))
    1078             :             return;
    1079             :           /*
    1080             :            * We can always send an REQEND so that we cannot
    1081             :            * get stuck encrypting.  We should only get this
    1082             :            * if we have been able to get in the correct mode
    1083             :            * anyhow.
    1084             :            */
    1085             :           encrypt_request_end ();
    1086             :           break;
    1087             :         case ENCRYPT_IS:
    1088             :           if (my_want_state_is_dont (TELOPT_ENCRYPT))
    1089             :             return;
    1090             :           encrypt_is (subpointer, SB_LEN ());
    1091             :           break;
    1092             :         case ENCRYPT_REPLY:
    1093             :           if (my_want_state_is_wont (TELOPT_ENCRYPT))
    1094             :             return;
    1095             :           encrypt_reply (subpointer, SB_LEN ());
    1096             :           break;
    1097             :         case ENCRYPT_ENC_KEYID:
    1098             :           if (my_want_state_is_dont (TELOPT_ENCRYPT))
    1099             :             return;
    1100             :           encrypt_enc_keyid (subpointer, SB_LEN ());
    1101             :           break;
    1102             :         case ENCRYPT_DEC_KEYID:
    1103             :           if (my_want_state_is_wont (TELOPT_ENCRYPT))
    1104             :             return;
    1105             :           encrypt_dec_keyid (subpointer, SB_LEN ());
    1106             :           break;
    1107             :         default:
    1108             :           break;
    1109             :         }
    1110             :       break;
    1111             : #endif /* ENCRYPTION */
    1112             :     default:
    1113           0 :       break;
    1114             :     }
    1115             : }
    1116             : 
    1117             : static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
    1118             : 
    1119             : void
    1120           0 : lm_will (unsigned char *cmd, int len)
    1121             : {
    1122           0 :   if (len < 1)
    1123             :     {
    1124           0 :       /*@ */ printf ("lm_will: no command!!!\n");
    1125             :       /* Should not happen... */
    1126           0 :       return;
    1127             :     }
    1128           0 :   switch (cmd[0])
    1129             :     {
    1130             :     case LM_FORWARDMASK:        /* We shouldn't ever get this... */
    1131             :     default:
    1132           0 :       str_lm[3] = DONT;
    1133           0 :       str_lm[4] = cmd[0];
    1134           0 :       if (NETROOM () > (int) sizeof (str_lm))
    1135             :         {
    1136           0 :           ring_supply_data (&netoring, str_lm, sizeof (str_lm));
    1137           0 :           printsub ('>', &str_lm[2], sizeof (str_lm) - 2);
    1138             :         }
    1139             : /*@*/
    1140             :       else
    1141           0 :         printf ("lm_will: not enough room in buffer\n");
    1142           0 :       break;
    1143             :     }
    1144             : }
    1145             : 
    1146             : void
    1147           0 : lm_wont (unsigned char *cmd, int len)
    1148             : {
    1149           0 :   if (len < 1)
    1150             :     {
    1151           0 :       /*@ */ printf ("lm_wont: no command!!!\n");
    1152             :       /* Should not happen... */
    1153           0 :       return;
    1154             :     }
    1155           0 :   switch (cmd[0])
    1156             :     {
    1157             :     case LM_FORWARDMASK:        /* We shouldn't ever get this... */
    1158             :     default:
    1159             :       /* We are always DONT, so don't respond */
    1160           0 :       return;
    1161             :     }
    1162             : }
    1163             : 
    1164             : void
    1165           0 : lm_do (unsigned char *cmd, int len)
    1166             : {
    1167           0 :   if (len < 1)
    1168             :     {
    1169           0 :       /*@ */ printf ("lm_do: no command!!!\n");
    1170             :       /* Should not happen... */
    1171           0 :       return;
    1172             :     }
    1173           0 :   switch (cmd[0])
    1174             :     {
    1175             :     case LM_FORWARDMASK:
    1176             :     default:
    1177           0 :       str_lm[3] = WONT;
    1178           0 :       str_lm[4] = cmd[0];
    1179           0 :       if (NETROOM () > (int) sizeof (str_lm))
    1180             :         {
    1181           0 :           ring_supply_data (&netoring, str_lm, sizeof (str_lm));
    1182           0 :           printsub ('>', &str_lm[2], sizeof (str_lm) - 2);
    1183             :         }
    1184             : /*@*/
    1185             :       else
    1186           0 :         printf ("lm_do: not enough room in buffer\n");
    1187           0 :       break;
    1188             :     }
    1189             : }
    1190             : 
    1191             : void
    1192           0 : lm_dont (unsigned char *cmd, int len)
    1193             : {
    1194           0 :   if (len < 1)
    1195             :     {
    1196           0 :       /*@ */ printf ("lm_dont: no command!!!\n");
    1197             :       /* Should not happen... */
    1198           0 :       return;
    1199             :     }
    1200           0 :   switch (cmd[0])
    1201             :     {
    1202             :     case LM_FORWARDMASK:
    1203             :     default:
    1204             :       /* we are always WONT, so don't respond */
    1205           0 :       break;
    1206             :     }
    1207             : }
    1208             : 
    1209             : static unsigned char str_lm_mode[] = {
    1210             :   IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
    1211             : };
    1212             : 
    1213             : void
    1214           0 : lm_mode (unsigned char *cmd, int len, int init)
    1215             : {
    1216           0 :   if (len != 1)
    1217           0 :     return;
    1218           0 :   if ((linemode & MODE_MASK & ~MODE_ACK) == *cmd)
    1219           0 :     return;
    1220           0 :   if (*cmd & MODE_ACK)
    1221           0 :     return;
    1222           0 :   linemode = *cmd & (MODE_MASK & ~MODE_ACK);
    1223           0 :   str_lm_mode[4] = linemode;
    1224           0 :   if (!init)
    1225           0 :     str_lm_mode[4] |= MODE_ACK;
    1226           0 :   if (NETROOM () > (int) sizeof (str_lm_mode))
    1227             :     {
    1228           0 :       ring_supply_data (&netoring, str_lm_mode, sizeof (str_lm_mode));
    1229           0 :       printsub ('>', &str_lm_mode[2], sizeof (str_lm_mode) - 2);
    1230             :     }
    1231             : /*@*/
    1232             :   else
    1233           0 :     printf ("lm_mode: not enough room in buffer\n");
    1234           0 :   setconnmode (0);              /* set changed mode */
    1235             : }
    1236             : 
    1237             : 
    1238             : 
    1239             : /*
    1240             :  * slc()
    1241             :  * Handle special character suboption of LINEMODE.
    1242             :  */
    1243             : 
    1244             : struct spc
    1245             : {
    1246             :   cc_t val;
    1247             :   cc_t *valp;
    1248             :   char flags;                   /* Current flags & level */
    1249             :   char mylevel;                 /* Maximum level & flags */
    1250             : } spc_data[NSLC + 1];
    1251             : 
    1252             : #define SLC_IMPORT      0
    1253             : #define SLC_EXPORT      1
    1254             : #define SLC_RVALUE      2
    1255             : static int slc_mode = SLC_EXPORT;
    1256             : 
    1257             : void
    1258           0 : slc_init (void)
    1259             : {
    1260             :   register struct spc *spcp;
    1261             : 
    1262           0 :   localchars = 1;
    1263           0 :   for (spcp = spc_data; spcp < &spc_data[NSLC + 1]; spcp++)
    1264             :     {
    1265           0 :       spcp->val = 0;
    1266           0 :       spcp->valp = 0;
    1267           0 :       spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
    1268             :     }
    1269             : 
    1270             : #define initfunc(func, flags) { \
    1271             :                                         spcp = &spc_data[func]; \
    1272             :                                         if ((spcp->valp = tcval(func))) { \
    1273             :                                             spcp->val = *spcp->valp; \
    1274             :                                             spcp->mylevel = SLC_VARIABLE|flags; \
    1275             :                                         } else { \
    1276             :                                             spcp->val = 0; \
    1277             :                                             spcp->mylevel = SLC_DEFAULT; \
    1278             :                                         } \
    1279             :                                     }
    1280             : 
    1281           0 :   initfunc (SLC_SYNCH, 0);
    1282             :   /* No BRK */
    1283           0 :   initfunc (SLC_AO, 0);
    1284           0 :   initfunc (SLC_AYT, 0);
    1285             :   /* No EOR */
    1286           0 :   initfunc (SLC_ABORT, SLC_FLUSHIN | SLC_FLUSHOUT);
    1287           0 :   initfunc (SLC_EOF, 0);
    1288             : #ifndef SYSV_TERMIO
    1289           0 :   initfunc (SLC_SUSP, SLC_FLUSHIN);
    1290             : #endif
    1291           0 :   initfunc (SLC_EC, 0);
    1292           0 :   initfunc (SLC_EL, 0);
    1293             : #ifndef SYSV_TERMIO
    1294           0 :   initfunc (SLC_EW, 0);
    1295           0 :   initfunc (SLC_RP, 0);
    1296           0 :   initfunc (SLC_LNEXT, 0);
    1297             : #endif
    1298           0 :   initfunc (SLC_XON, 0);
    1299           0 :   initfunc (SLC_XOFF, 0);
    1300             : #ifdef  SYSV_TERMIO
    1301             :   spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
    1302             :   spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
    1303             : #endif
    1304           0 :   initfunc (SLC_FORW1, 0);
    1305             : #ifdef  USE_TERMIO
    1306           0 :   initfunc (SLC_FORW2, 0);
    1307             :   /* No FORW2 */
    1308             : #endif
    1309             : 
    1310           0 :   initfunc (SLC_IP, SLC_FLUSHIN | SLC_FLUSHOUT);
    1311             : #undef  initfunc
    1312             : 
    1313           0 :   if (slc_mode == SLC_EXPORT)
    1314           0 :     slc_export ();
    1315             :   else
    1316           0 :     slc_import (1);
    1317             : 
    1318           0 : }
    1319             : 
    1320             : void
    1321           0 : slcstate (void)
    1322             : {
    1323           0 :   printf ("Special characters are %s values\n",
    1324           0 :           slc_mode == SLC_IMPORT ? "remote default" :
    1325           0 :           slc_mode == SLC_EXPORT ? "local" : "remote");
    1326           0 : }
    1327             : 
    1328             : void
    1329           0 : slc_mode_export (void)
    1330             : {
    1331           0 :   slc_mode = SLC_EXPORT;
    1332           0 :   if (my_state_is_will (TELOPT_LINEMODE))
    1333           0 :     slc_export ();
    1334           0 : }
    1335             : 
    1336             : void
    1337           0 : slc_mode_import (int def)
    1338             : {
    1339           0 :   slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
    1340           0 :   if (my_state_is_will (TELOPT_LINEMODE))
    1341           0 :     slc_import (def);
    1342           0 : }
    1343             : 
    1344             : unsigned char slc_import_val[] = {
    1345             :   IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
    1346             : };
    1347             : unsigned char slc_import_def[] = {
    1348             :   IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
    1349             : };
    1350             : 
    1351             : void
    1352           0 : slc_import (int def)
    1353             : {
    1354           0 :   if (NETROOM () > (int) sizeof (slc_import_val))
    1355             :     {
    1356           0 :       if (def)
    1357             :         {
    1358           0 :           ring_supply_data (&netoring, slc_import_def,
    1359             :                             sizeof (slc_import_def));
    1360           0 :           printsub ('>', &slc_import_def[2], sizeof (slc_import_def) - 2);
    1361             :         }
    1362             :       else
    1363             :         {
    1364           0 :           ring_supply_data (&netoring, slc_import_val,
    1365             :                             sizeof (slc_import_val));
    1366           0 :           printsub ('>', &slc_import_val[2], sizeof (slc_import_val) - 2);
    1367             :         }
    1368             :     }
    1369             : /*@*/
    1370             :   else
    1371           0 :     printf ("slc_import: not enough room\n");
    1372           0 : }
    1373             : 
    1374             : void
    1375           0 : slc_export (void)
    1376             : {
    1377             :   register struct spc *spcp;
    1378             : 
    1379           0 :   TerminalDefaultChars ();
    1380             : 
    1381           0 :   slc_start_reply ();
    1382           0 :   for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
    1383             :     {
    1384           0 :       if (spcp->mylevel != SLC_NOSUPPORT)
    1385             :         {
    1386           0 :           if (spcp->val == (cc_t) (_POSIX_VDISABLE))
    1387           0 :             spcp->flags = SLC_NOSUPPORT;
    1388             :           else
    1389           0 :             spcp->flags = spcp->mylevel;
    1390           0 :           if (spcp->valp)
    1391           0 :             spcp->val = *spcp->valp;
    1392           0 :           slc_add_reply (spcp - spc_data, spcp->flags, spcp->val);
    1393             :         }
    1394             :     }
    1395           0 :   slc_end_reply ();
    1396           0 :   slc_update ();
    1397           0 :   setconnmode (1);              /* Make sure the character values are set */
    1398           0 : }
    1399             : 
    1400             : void
    1401           0 : slc (register unsigned char *cp, int len)
    1402             : {
    1403             :   register struct spc *spcp;
    1404             :   register int func, level;
    1405             : 
    1406           0 :   slc_start_reply ();
    1407             : 
    1408           0 :   for (; len >= 3; len -= 3, cp += 3)
    1409             :     {
    1410             : 
    1411           0 :       func = cp[SLC_FUNC];
    1412             : 
    1413           0 :       if (func == 0)
    1414             :         {
    1415             :           /*
    1416             :            * Client side: always ignore 0 function.
    1417             :            */
    1418           0 :           continue;
    1419             :         }
    1420           0 :       if (func > NSLC)
    1421             :         {
    1422           0 :           if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
    1423           0 :             slc_add_reply (func, SLC_NOSUPPORT, 0);
    1424           0 :           continue;
    1425             :         }
    1426             : 
    1427           0 :       spcp = &spc_data[func];
    1428             : 
    1429           0 :       level = cp[SLC_FLAGS] & (SLC_LEVELBITS | SLC_ACK);
    1430             : 
    1431           0 :       if ((cp[SLC_VALUE] == (unsigned char) spcp->val) &&
    1432           0 :           ((level & SLC_LEVELBITS) == (spcp->flags & SLC_LEVELBITS)))
    1433             :         {
    1434           0 :           continue;
    1435             :         }
    1436             : 
    1437           0 :       if (level == (SLC_DEFAULT | SLC_ACK))
    1438             :         {
    1439             :           /*
    1440             :            * This is an error condition, the SLC_ACK
    1441             :            * bit should never be set for the SLC_DEFAULT
    1442             :            * level.  Our best guess to recover is to
    1443             :            * ignore the SLC_ACK bit.
    1444             :            */
    1445           0 :           cp[SLC_FLAGS] &= ~SLC_ACK;
    1446             :         }
    1447             : 
    1448           0 :       if (level == ((spcp->flags & SLC_LEVELBITS) | SLC_ACK))
    1449             :         {
    1450           0 :           spcp->val = (cc_t) cp[SLC_VALUE];
    1451           0 :           spcp->flags = cp[SLC_FLAGS];       /* include SLC_ACK */
    1452           0 :           continue;
    1453             :         }
    1454             : 
    1455           0 :       level &= ~SLC_ACK;
    1456             : 
    1457           0 :       if (level <= (spcp->mylevel & SLC_LEVELBITS))
    1458             :         {
    1459           0 :           spcp->flags = cp[SLC_FLAGS] | SLC_ACK;
    1460           0 :           spcp->val = (cc_t) cp[SLC_VALUE];
    1461             :         }
    1462           0 :       if (level == SLC_DEFAULT)
    1463             :         {
    1464           0 :           if ((spcp->mylevel & SLC_LEVELBITS) != SLC_DEFAULT)
    1465           0 :             spcp->flags = spcp->mylevel;
    1466             :           else
    1467           0 :             spcp->flags = SLC_NOSUPPORT;
    1468             :         }
    1469           0 :       slc_add_reply (func, spcp->flags, spcp->val);
    1470             :     }
    1471           0 :   slc_end_reply ();
    1472           0 :   if (slc_update ())
    1473           0 :     setconnmode (1);            /* set the  new character values */
    1474           0 : }
    1475             : 
    1476             : void
    1477           0 : slc_check (void)
    1478             : {
    1479             :   register struct spc *spcp;
    1480             : 
    1481           0 :   slc_start_reply ();
    1482           0 :   for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
    1483             :     {
    1484           0 :       if (spcp->valp && spcp->val != *spcp->valp)
    1485             :         {
    1486           0 :           spcp->val = *spcp->valp;
    1487           0 :           if (spcp->val == (cc_t) (_POSIX_VDISABLE))
    1488           0 :             spcp->flags = SLC_NOSUPPORT;
    1489             :           else
    1490           0 :             spcp->flags = spcp->mylevel;
    1491           0 :           slc_add_reply (spcp - spc_data, spcp->flags, spcp->val);
    1492             :         }
    1493             :     }
    1494           0 :   slc_end_reply ();
    1495           0 :   setconnmode (1);
    1496           0 : }
    1497             : 
    1498             : 
    1499             : unsigned char slc_reply[128];
    1500             : unsigned char *slc_replyp;
    1501             : 
    1502             : void
    1503           0 : slc_start_reply (void)
    1504             : {
    1505           0 :   slc_replyp = slc_reply;
    1506           0 :   *slc_replyp++ = IAC;
    1507           0 :   *slc_replyp++ = SB;
    1508           0 :   *slc_replyp++ = TELOPT_LINEMODE;
    1509           0 :   *slc_replyp++ = LM_SLC;
    1510           0 : }
    1511             : 
    1512             : void
    1513           0 : slc_add_reply (unsigned char func, unsigned char flags, cc_t value)
    1514             : {
    1515           0 :   if ((*slc_replyp++ = func) == IAC)
    1516           0 :     *slc_replyp++ = IAC;
    1517           0 :   if ((*slc_replyp++ = flags) == IAC)
    1518           0 :     *slc_replyp++ = IAC;
    1519           0 :   if ((*slc_replyp++ = (unsigned char) value) == IAC)
    1520           0 :     *slc_replyp++ = IAC;
    1521           0 : }
    1522             : 
    1523             : void
    1524           0 : slc_end_reply (void)
    1525             : {
    1526             :   register int len;
    1527             : 
    1528           0 :   *slc_replyp++ = IAC;
    1529           0 :   *slc_replyp++ = SE;
    1530           0 :   len = slc_replyp - slc_reply;
    1531           0 :   if (len <= 6)
    1532           0 :     return;
    1533           0 :   if (NETROOM () > len)
    1534             :     {
    1535           0 :       ring_supply_data (&netoring, slc_reply, slc_replyp - slc_reply);
    1536           0 :       printsub ('>', &slc_reply[2], slc_replyp - slc_reply - 2);
    1537             :     }
    1538             : /*@*/
    1539             :   else
    1540           0 :     printf ("slc_end_reply: not enough room\n");
    1541             : }
    1542             : 
    1543             : int
    1544           0 : slc_update (void)
    1545             : {
    1546             :   register struct spc *spcp;
    1547           0 :   int need_update = 0;
    1548             : 
    1549           0 :   for (spcp = &spc_data[1]; spcp < &spc_data[NSLC + 1]; spcp++)
    1550             :     {
    1551           0 :       if (!(spcp->flags & SLC_ACK))
    1552           0 :         continue;
    1553           0 :       spcp->flags &= ~SLC_ACK;
    1554           0 :       if (spcp->valp && (*spcp->valp != spcp->val))
    1555             :         {
    1556           0 :           *spcp->valp = spcp->val;
    1557           0 :           need_update = 1;
    1558             :         }
    1559             :     }
    1560           0 :   return (need_update);
    1561             : }
    1562             : 
    1563             : #ifdef  OLD_ENVIRON
    1564             : # ifdef ENV_HACK
    1565             : /*
    1566             :  * Earlier version of telnet/telnetd from the BSD code had
    1567             :  * the definitions of VALUE and VAR reversed.  To ensure
    1568             :  * maximum interoperability, we assume that the server is
    1569             :  * an older BSD server, until proven otherwise.  The newer
    1570             :  * BSD servers should be able to handle either definition,
    1571             :  * so it is better to use the wrong values if we don't
    1572             :  * know what type of server it is.
    1573             :  */
    1574             : int env_auto = 1;
    1575             : int old_env_var = OLD_ENV_VAR;
    1576             : int old_env_value = OLD_ENV_VALUE;
    1577             : # else
    1578             : #  define old_env_var OLD_ENV_VAR
    1579             : #  define old_env_value OLD_ENV_VALUE
    1580             : # endif
    1581             : #endif
    1582             : 
    1583             : void
    1584           0 : env_opt (register unsigned char *buf, register int len)
    1585             : {
    1586           0 :   register unsigned char *ep = 0, *epc = 0;
    1587             :   register int i;
    1588             : 
    1589           0 :   switch (buf[0] & 0xff)
    1590             :     {
    1591             :     case TELQUAL_SEND:
    1592           0 :       env_opt_start ();
    1593           0 :       if (len == 1)
    1594             :         {
    1595           0 :           env_opt_add (NULL);
    1596             :         }
    1597             :       else
    1598           0 :         for (i = 1; i < len; i++)
    1599             :           {
    1600           0 :             switch (buf[i] & 0xff)
    1601             :               {
    1602             : #ifdef  OLD_ENVIRON
    1603             :               case OLD_ENV_VAR:
    1604             : # ifdef ENV_HACK
    1605             :                 if (telopt_environ == TELOPT_OLD_ENVIRON && env_auto)
    1606             :                   {
    1607             :                     /* Server has the same definitions */
    1608             :                     old_env_var = OLD_ENV_VAR;
    1609             :                     old_env_value = OLD_ENV_VALUE;
    1610             :                   }
    1611             :                 /* FALL THROUGH */
    1612             : # endif
    1613             :               case OLD_ENV_VALUE:
    1614             :                 /*
    1615             :                  * Although OLD_ENV_VALUE is not legal, we will
    1616             :                  * still recognize it, just in case it is an
    1617             :                  * old server that has VAR & VALUE mixed up...
    1618             :                  */
    1619             :                 /* FALL THROUGH */
    1620             : #else
    1621             :               case NEW_ENV_VAR:
    1622             : #endif
    1623             :               case ENV_USERVAR:
    1624           0 :                 if (ep)
    1625             :                   {
    1626           0 :                     *epc = 0;
    1627           0 :                     env_opt_add (ep);
    1628             :                   }
    1629           0 :                 ep = epc = &buf[i + 1];
    1630           0 :                 break;
    1631             :               case ENV_ESC:
    1632           0 :                 i++;
    1633             :                 /*FALL THROUGH */
    1634             :               default:
    1635           0 :                 if (epc)
    1636           0 :                   *epc++ = buf[i];
    1637           0 :                 break;
    1638             :               }
    1639             :           }
    1640           0 :       if (ep)
    1641             :         {
    1642           0 :           *epc = 0;
    1643           0 :           env_opt_add (ep);
    1644             :         }
    1645           0 :       env_opt_end (1);
    1646           0 :       break;
    1647             : 
    1648             :     case TELQUAL_IS:
    1649             :     case TELQUAL_INFO:
    1650             :       /* Ignore for now.  We shouldn't get it anyway. */
    1651           0 :       break;
    1652             : 
    1653             :     default:
    1654           0 :       break;
    1655             :     }
    1656           0 : }
    1657             : 
    1658             : #define OPT_REPLY_SIZE  256
    1659             : unsigned char *opt_reply;
    1660             : unsigned char *opt_replyp;
    1661             : unsigned char *opt_replyend;
    1662             : 
    1663             : void
    1664           0 : env_opt_start (void)
    1665             : {
    1666           0 :   if (opt_reply)
    1667           0 :     opt_reply = (unsigned char *) realloc (opt_reply, OPT_REPLY_SIZE);
    1668             :   else
    1669           0 :     opt_reply = (unsigned char *) malloc (OPT_REPLY_SIZE);
    1670           0 :   if (opt_reply == NULL)
    1671             :     {
    1672           0 : /*@*/ printf ("env_opt_start: malloc()/realloc() failed!!!\n");
    1673           0 :       opt_reply = opt_replyp = opt_replyend = NULL;
    1674           0 :       return;
    1675             :     }
    1676           0 :   opt_replyp = opt_reply;
    1677           0 :   opt_replyend = opt_reply + OPT_REPLY_SIZE;
    1678           0 :   *opt_replyp++ = IAC;
    1679           0 :   *opt_replyp++ = SB;
    1680           0 :   *opt_replyp++ = telopt_environ;
    1681           0 :   *opt_replyp++ = TELQUAL_IS;
    1682             : }
    1683             : 
    1684             : void
    1685           0 : env_opt_start_info (void)
    1686             : {
    1687           0 :   env_opt_start ();
    1688           0 :   if (opt_replyp)
    1689           0 :     opt_replyp[-1] = TELQUAL_INFO;
    1690           0 : }
    1691             : 
    1692             : void
    1693           0 : env_opt_add (register unsigned char *ep)
    1694             : {
    1695             :   register unsigned char *vp, c;
    1696             : 
    1697           0 :   if (opt_reply == NULL)
    1698           0 :      /*XXX*/ return;
    1699           0 :    /*XXX*/ if (ep == NULL || *ep == '\0')
    1700             :     {
    1701             :       /* Send user defined variables first. */
    1702           0 :       env_default (1, 0);
    1703           0 :       while ((ep = env_default (0, 0)))
    1704           0 :         env_opt_add (ep);
    1705             : 
    1706             :       /* Now add the list of well know variables.  */
    1707           0 :       env_default (1, 1);
    1708           0 :       while ((ep = env_default (0, 1)))
    1709           0 :         env_opt_add (ep);
    1710           0 :       return;
    1711             :     }
    1712           0 :   vp = env_getvalue ((char *)ep);
    1713           0 :   if (opt_replyp + (vp ? strlen ((char *) vp) : 0) +
    1714           0 :       strlen ((char *) ep) + 6 > opt_replyend)
    1715             :     {
    1716             :       register int len;
    1717           0 :       opt_replyend += OPT_REPLY_SIZE;
    1718           0 :       len = opt_replyend - opt_reply;
    1719           0 :       opt_reply = (unsigned char *) realloc (opt_reply, len);
    1720           0 :       if (opt_reply == NULL)
    1721             :         {
    1722           0 : /*@*/ printf ("env_opt_add: realloc() failed!!!\n");
    1723           0 :           opt_reply = opt_replyp = opt_replyend = NULL;
    1724           0 :           return;
    1725             :         }
    1726           0 :       opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
    1727           0 :       opt_replyend = opt_reply + len;
    1728             :     }
    1729           0 :   if (opt_welldefined ((char *) ep))
    1730             : #ifdef  OLD_ENVIRON
    1731             :     if (telopt_environ == TELOPT_OLD_ENVIRON)
    1732             :       *opt_replyp++ = old_env_var;
    1733             :     else
    1734             : #endif
    1735           0 :       *opt_replyp++ = NEW_ENV_VAR;
    1736             :   else
    1737           0 :     *opt_replyp++ = ENV_USERVAR;
    1738             :   for (;;)
    1739             :     {
    1740           0 :       while ((c = *ep++))
    1741             :         {
    1742           0 :           switch (c & 0xff)
    1743             :             {
    1744             :             case IAC:
    1745           0 :               *opt_replyp++ = IAC;
    1746           0 :               break;
    1747             :             case NEW_ENV_VAR:
    1748             :             case NEW_ENV_VALUE:
    1749             :             case ENV_ESC:
    1750             :             case ENV_USERVAR:
    1751           0 :               *opt_replyp++ = ENV_ESC;
    1752           0 :               break;
    1753             :             }
    1754           0 :           *opt_replyp++ = c;
    1755             :         }
    1756           0 :       if ((ep = vp))
    1757             :         {
    1758             : #ifdef  OLD_ENVIRON
    1759             :           if (telopt_environ == TELOPT_OLD_ENVIRON)
    1760             :             *opt_replyp++ = old_env_value;
    1761             :           else
    1762             : #endif
    1763           0 :             *opt_replyp++ = NEW_ENV_VALUE;
    1764           0 :           vp = NULL;
    1765             :         }
    1766             :       else
    1767           0 :         break;
    1768           0 :     }
    1769             : }
    1770             : 
    1771             : int
    1772         186 : opt_welldefined (char *ep)
    1773             : {
    1774         369 :   if ((strcmp (ep, "USER") == 0) ||
    1775         363 :       (strcmp (ep, "DISPLAY") == 0) ||
    1776         360 :       (strcmp (ep, "PRINTER") == 0) ||
    1777         360 :       (strcmp (ep, "SYSTEMTYPE") == 0) ||
    1778         360 :       (strcmp (ep, "JOB") == 0) || (strcmp (ep, "ACCT") == 0))
    1779           6 :     return (1);
    1780         180 :   return (0);
    1781             : }
    1782             : 
    1783             : void
    1784           0 : env_opt_end (register int emptyok)
    1785             : {
    1786             :   register int len;
    1787             : 
    1788           0 :   len = opt_replyp - opt_reply + 2;
    1789           0 :   if (emptyok || len > 6)
    1790             :     {
    1791           0 :       *opt_replyp++ = IAC;
    1792           0 :       *opt_replyp++ = SE;
    1793           0 :       if (NETROOM () > len)
    1794             :         {
    1795           0 :           ring_supply_data (&netoring, opt_reply, len);
    1796           0 :           printsub ('>', &opt_reply[2], len - 2);
    1797             :         }
    1798             : /*@*/
    1799             :       else
    1800           0 :         printf ("slc_end_reply: not enough room\n");
    1801             :     }
    1802           0 :   if (opt_reply)
    1803             :     {
    1804           0 :       free (opt_reply);
    1805           0 :       opt_reply = opt_replyp = opt_replyend = NULL;
    1806             :     }
    1807           0 : }
    1808             : 
    1809             : 
    1810             : 
    1811             : int
    1812           6 : telrcv (void)
    1813             : {
    1814             :   register int c;
    1815             :   register int scc;
    1816             :   register unsigned char *sbp;
    1817             :   int count;
    1818           6 :   int returnValue = 0;
    1819             : 
    1820           6 :   scc = 0;
    1821           6 :   count = 0;
    1822          87 :   while (TTYROOM () > 2)
    1823             :     {
    1824          81 :       if (scc == 0)
    1825             :         {
    1826           9 :           if (count)
    1827             :             {
    1828           3 :               ring_consumed (&netiring, count);
    1829           3 :               returnValue = 1;
    1830           3 :               count = 0;
    1831             :             }
    1832           9 :           sbp = netiring.consume;
    1833           9 :           scc = ring_full_consecutive (&netiring);
    1834           9 :           if (scc == 0)
    1835             :             {
    1836             :               /* No more data coming in */
    1837           6 :               break;
    1838             :             }
    1839             :         }
    1840             : 
    1841          75 :       c = *sbp++ & 0xff, scc--;
    1842          75 :       count++;
    1843             : #ifdef  ENCRYPTION
    1844             :       if (decrypt_input)
    1845             :         c = (*decrypt_input) (c);
    1846             : #endif /* ENCRYPTION */
    1847             : 
    1848          75 :       switch (telrcv_state)
    1849             :         {
    1850             : 
    1851             :         case TS_CR:
    1852           0 :           telrcv_state = TS_DATA;
    1853           0 :           if (c == '\0')
    1854             :             {
    1855           0 :               break;            /* Ignore \0 after CR */
    1856             :             }
    1857           0 :           else if ((c == '\n') && my_want_state_is_dont (TELOPT_ECHO)
    1858           0 :                    && !crmod)
    1859             :             {
    1860           0 :               TTYADD (c);
    1861           0 :               break;
    1862             :             }
    1863             :           /* Else, fall through */
    1864             : 
    1865             :         case TS_DATA:
    1866          75 :           if (c == IAC)
    1867             :             {
    1868           0 :               telrcv_state = TS_IAC;
    1869           0 :               break;
    1870             :             }
    1871             : #if defined TN3270
    1872             :           if (In3270)
    1873             :             {
    1874             :               *Ifrontp++ = c;
    1875             :               while (scc > 0)
    1876             :                 {
    1877             :                   c = *sbp++ & 0377, scc--;
    1878             :                   count++;
    1879             : # ifdef ENCRYPTION
    1880             :                   if (decrypt_input)
    1881             :                     c = (*decrypt_input) (c);
    1882             : # endif /* ENCRYPTION */
    1883             :                   if (c == IAC)
    1884             :                     {
    1885             :                       telrcv_state = TS_IAC;
    1886             :                       break;
    1887             :                     }
    1888             :                   *Ifrontp++ = c;
    1889             :                 }
    1890             :             }
    1891             :           else
    1892             : #endif /* defined(TN3270) */
    1893             :             /*
    1894             :              * The 'crmod' hack (see following) is needed
    1895             :              * since we can't * set CRMOD on output only.
    1896             :              * Machines like MULTICS like to send \r without
    1897             :              * \n; since we must turn off CRMOD to get proper
    1898             :              * input, the mapping is done here (sigh).
    1899             :              */
    1900          75 :           if ((c == '\r') && my_want_state_is_dont (TELOPT_BINARY))
    1901             :             {
    1902           0 :               if (scc > 0)
    1903             :                 {
    1904           0 :                   c = *sbp & 0xff;
    1905             : #ifdef  ENCRYPTION
    1906             :                   if (decrypt_input)
    1907             :                     c = (*decrypt_input) (c);
    1908             : #endif /* ENCRYPTION */
    1909           0 :                   if (c == 0)
    1910             :                     {
    1911           0 :                       sbp++, scc--;
    1912           0 :                       count++;
    1913             :                       /* a "true" CR */
    1914           0 :                       TTYADD ('\r');
    1915             :                     }
    1916           0 :                   else if (my_want_state_is_dont (TELOPT_ECHO) && (c == '\n'))
    1917             :                     {
    1918           0 :                       sbp++, scc--;
    1919           0 :                       count++;
    1920           0 :                       TTYADD ('\n');
    1921             :                     }
    1922             :                   else
    1923             :                     {
    1924             : #ifdef  ENCRYPTION
    1925             :                       if (decrypt_input)
    1926             :                         (*decrypt_input) (-1);
    1927             : #endif /* ENCRYPTION */
    1928             : 
    1929           0 :                       TTYADD ('\r');
    1930           0 :                       if (crmod)
    1931             :                         {
    1932           0 :                           TTYADD ('\n');
    1933             :                         }
    1934             :                     }
    1935             :                 }
    1936             :               else
    1937             :                 {
    1938           0 :                   telrcv_state = TS_CR;
    1939           0 :                   TTYADD ('\r');
    1940           0 :                   if (crmod)
    1941             :                     {
    1942           0 :                       TTYADD ('\n');
    1943             :                     }
    1944             :                 }
    1945             :             }
    1946             :           else
    1947             :             {
    1948          75 :               TTYADD (c);
    1949             :             }
    1950          75 :           continue;
    1951             : 
    1952             :         case TS_IAC:
    1953             :         process_iac:
    1954           0 :           switch (c)
    1955             :             {
    1956             : 
    1957             :             case WILL:
    1958           0 :               telrcv_state = TS_WILL;
    1959           0 :               continue;
    1960             : 
    1961             :             case WONT:
    1962           0 :               telrcv_state = TS_WONT;
    1963           0 :               continue;
    1964             : 
    1965             :             case DO:
    1966           0 :               telrcv_state = TS_DO;
    1967           0 :               continue;
    1968             : 
    1969             :             case DONT:
    1970           0 :               telrcv_state = TS_DONT;
    1971           0 :               continue;
    1972             : 
    1973             :             case DM:
    1974             :               /*
    1975             :                * We may have missed an urgent notification,
    1976             :                * so make sure we flush whatever is in the
    1977             :                * buffer currently.
    1978             :                */
    1979           0 :               printoption ("RCVD", IAC, DM);
    1980           0 :               SYNCHing = 1;
    1981           0 :               ttyflush (1);
    1982           0 :               SYNCHing = stilloob ();
    1983           0 :               settimer (gotDM);
    1984           0 :               break;
    1985             : 
    1986             :             case SB:
    1987           0 :               SB_CLEAR ();
    1988           0 :               telrcv_state = TS_SB;
    1989           0 :               continue;
    1990             : 
    1991             : #if defined TN3270
    1992             :             case EOR:
    1993             :               if (In3270)
    1994             :                 {
    1995             :                   if (Ibackp == Ifrontp)
    1996             :                     {
    1997             :                       Ibackp = Ifrontp = Ibuf;
    1998             :                       ISend = 0;        /* should have been! */
    1999             :                     }
    2000             :                   else
    2001             :                     {
    2002             :                       Ibackp += DataFromNetwork (Ibackp, Ifrontp - Ibackp, 1);
    2003             :                       ISend = 1;
    2004             :                     }
    2005             :                 }
    2006             :               printoption ("RCVD", IAC, EOR);
    2007             :               break;
    2008             : #endif /* defined(TN3270) */
    2009             : 
    2010             :             case IAC:
    2011             : #if !defined TN3270
    2012           0 :               TTYADD (IAC);
    2013             : #else /* !defined(TN3270) */
    2014             :               if (In3270)
    2015             :                 {
    2016             :                   *Ifrontp++ = IAC;
    2017             :                 }
    2018             :               else
    2019             :                 {
    2020             :                   TTYADD (IAC);
    2021             :                 }
    2022             : #endif /* !defined(TN3270) */
    2023           0 :               break;
    2024             : 
    2025             :             case NOP:
    2026             :             case GA:
    2027             :             default:
    2028           0 :               printoption ("RCVD", IAC, c);
    2029           0 :               break;
    2030             :             }
    2031           0 :           telrcv_state = TS_DATA;
    2032           0 :           continue;
    2033             : 
    2034             :         case TS_WILL:
    2035           0 :           printoption ("RCVD", WILL, c);
    2036           0 :           willoption (c);
    2037             :           SetIn3270 ();
    2038           0 :           telrcv_state = TS_DATA;
    2039           0 :           continue;
    2040             : 
    2041             :         case TS_WONT:
    2042           0 :           printoption ("RCVD", WONT, c);
    2043           0 :           wontoption (c);
    2044             :           SetIn3270 ();
    2045           0 :           telrcv_state = TS_DATA;
    2046           0 :           continue;
    2047             : 
    2048             :         case TS_DO:
    2049           0 :           printoption ("RCVD", DO, c);
    2050           0 :           dooption (c);
    2051             :           SetIn3270 ();
    2052           0 :           if (c == TELOPT_NAWS)
    2053             :             {
    2054           0 :               sendnaws ();
    2055             :             }
    2056           0 :           else if (c == TELOPT_LFLOW)
    2057             :             {
    2058           0 :               localflow = 1;
    2059           0 :               setcommandmode ();
    2060           0 :               setconnmode (0);
    2061             :             }
    2062           0 :           telrcv_state = TS_DATA;
    2063           0 :           continue;
    2064             : 
    2065             :         case TS_DONT:
    2066           0 :           printoption ("RCVD", DONT, c);
    2067           0 :           dontoption (c);
    2068           0 :           flushline = 1;
    2069           0 :           setconnmode (0);      /* set new tty mode (maybe) */
    2070             :           SetIn3270 ();
    2071           0 :           telrcv_state = TS_DATA;
    2072           0 :           continue;
    2073             : 
    2074             :         case TS_SB:
    2075           0 :           if (c == IAC)
    2076             :             {
    2077           0 :               telrcv_state = TS_SE;
    2078             :             }
    2079             :           else
    2080             :             {
    2081           0 :               SB_ACCUM (c);
    2082             :             }
    2083           0 :           continue;
    2084             : 
    2085             :         case TS_SE:
    2086           0 :           if (c != SE)
    2087             :             {
    2088           0 :               if (c != IAC)
    2089             :                 {
    2090             :                   /*
    2091             :                    * This is an error.  We only expect to get
    2092             :                    * "IAC IAC" or "IAC SE".  Several things may
    2093             :                    * have happend.  An IAC was not doubled, the
    2094             :                    * IAC SE was left off, or another option got
    2095             :                    * inserted into the suboption are all possibilities.
    2096             :                    * If we assume that the IAC was not doubled,
    2097             :                    * and really the IAC SE was left off, we could
    2098             :                    * get into an infinate loop here.  So, instead,
    2099             :                    * we terminate the suboption, and process the
    2100             :                    * partial suboption if we can.
    2101             :                    */
    2102           0 :                   SB_ACCUM (IAC);
    2103           0 :                   SB_ACCUM (c);
    2104           0 :                   subpointer -= 2;
    2105           0 :                   SB_TERM ();
    2106             : 
    2107           0 :                   printoption ("In SUBOPTION processing, RCVD", IAC, c);
    2108           0 :                   suboption (); /* handle sub-option */
    2109             :                   SetIn3270 ();
    2110           0 :                   telrcv_state = TS_IAC;
    2111           0 :                   goto process_iac;
    2112             :                 }
    2113           0 :               SB_ACCUM (c);
    2114           0 :               telrcv_state = TS_SB;
    2115             :             }
    2116             :           else
    2117             :             {
    2118           0 :               SB_ACCUM (IAC);
    2119           0 :               SB_ACCUM (SE);
    2120           0 :               subpointer -= 2;
    2121           0 :               SB_TERM ();
    2122           0 :               suboption ();     /* handle sub-option */
    2123             :               SetIn3270 ();
    2124           0 :               telrcv_state = TS_DATA;
    2125             :             }
    2126             :         }
    2127             :     }
    2128           6 :   if (count)
    2129           0 :     ring_consumed (&netiring, count);
    2130           6 :   return returnValue || count;
    2131             : }
    2132             : 
    2133             : static int bol = 1, local = 0;
    2134             : 
    2135             : int
    2136           0 : rlogin_susp (void)
    2137             : {
    2138           0 :   if (local)
    2139             :     {
    2140           0 :       local = 0;
    2141           0 :       bol = 1;
    2142           0 :       command (0, "z\n", 2);
    2143           0 :       return (1);
    2144             :     }
    2145           0 :   return (0);
    2146             : }
    2147             : 
    2148             : static int
    2149           0 : telsnd (void)
    2150             : {
    2151             :   int tcc;
    2152             :   int count;
    2153           0 :   int returnValue = 0;
    2154             :   unsigned char *tbp;
    2155             : 
    2156           0 :   tcc = 0;
    2157           0 :   count = 0;
    2158           0 :   while (NETROOM () > 2)
    2159             :     {
    2160             :       register int sc;
    2161             :       register int c;
    2162             : 
    2163           0 :       if (tcc == 0)
    2164             :         {
    2165           0 :           if (count)
    2166             :             {
    2167           0 :               ring_consumed (&ttyiring, count);
    2168           0 :               returnValue = 1;
    2169           0 :               count = 0;
    2170             :             }
    2171           0 :           tbp = ttyiring.consume;
    2172           0 :           tcc = ring_full_consecutive (&ttyiring);
    2173           0 :           if (tcc == 0)
    2174             :             {
    2175           0 :               break;
    2176             :             }
    2177             :         }
    2178           0 :       c = *tbp++ & 0xff, sc = strip (c), tcc--;
    2179           0 :       count++;
    2180           0 :       if (rlogin != _POSIX_VDISABLE)
    2181             :         {
    2182           0 :           if (bol)
    2183             :             {
    2184           0 :               bol = 0;
    2185           0 :               if (sc == rlogin)
    2186             :                 {
    2187           0 :                   local = 1;
    2188           0 :                   continue;
    2189             :                 }
    2190             :             }
    2191           0 :           else if (local)
    2192             :             {
    2193           0 :               local = 0;
    2194           0 :               if (sc == '.' || c == termEofChar)
    2195             :                 {
    2196           0 :                   bol = 1;
    2197           0 :                   command (0, "close\n", 6);
    2198           0 :                   continue;
    2199             :                 }
    2200           0 :               if (sc == termSuspChar)
    2201             :                 {
    2202           0 :                   bol = 1;
    2203           0 :                   command (0, "z\n", 2);
    2204           0 :                   continue;
    2205             :                 }
    2206           0 :               if (sc == escape)
    2207             :                 {
    2208           0 :                   command (0, (char *) tbp, tcc);
    2209           0 :                   bol = 1;
    2210           0 :                   count += tcc;
    2211           0 :                   tcc = 0;
    2212           0 :                   flushline = 1;
    2213           0 :                   break;
    2214             :                 }
    2215           0 :               if (sc != rlogin)
    2216             :                 {
    2217           0 :                   ++tcc;
    2218           0 :                   --tbp;
    2219           0 :                   --count;
    2220           0 :                   c = sc = rlogin;
    2221             :                 }
    2222             :             }
    2223           0 :           if ((sc == '\n') || (sc == '\r'))
    2224           0 :             bol = 1;
    2225             :         }
    2226           0 :       else if (sc == escape)
    2227             :         {
    2228             :           /*
    2229             :            * Double escape is a pass through of a single escape character.
    2230             :            */
    2231           0 :           if (tcc && strip (*tbp) == escape)
    2232             :             {
    2233           0 :               tbp++;
    2234           0 :               tcc--;
    2235           0 :               count++;
    2236           0 :               bol = 0;
    2237             :             }
    2238             :           else
    2239             :             {
    2240           0 :               command (0, (char *) tbp, tcc);
    2241           0 :               bol = 1;
    2242           0 :               count += tcc;
    2243           0 :               tcc = 0;
    2244           0 :               flushline = 1;
    2245           0 :               break;
    2246             :             }
    2247             :         }
    2248             :       else
    2249           0 :         bol = 0;
    2250             : #ifdef  KLUDGELINEMODE
    2251           0 :       if (kludgelinemode && (globalmode & MODE_EDIT) && (sc == echoc))
    2252             :         {
    2253           0 :           if (tcc > 0 && strip (*tbp) == echoc)
    2254             :             {
    2255           0 :               tcc--;
    2256           0 :               tbp++;
    2257           0 :               count++;
    2258             :             }
    2259             :           else
    2260             :             {
    2261           0 :               dontlecho = !dontlecho;
    2262           0 :               settimer (echotoggle);
    2263           0 :               setconnmode (0);
    2264           0 :               flushline = 1;
    2265           0 :               break;
    2266             :             }
    2267             :         }
    2268             : #endif
    2269           0 :       if (MODE_LOCAL_CHARS (globalmode))
    2270             :         {
    2271           0 :           if (TerminalSpecialChars (sc) == 0)
    2272             :             {
    2273           0 :               bol = 1;
    2274           0 :               break;
    2275             :             }
    2276             :         }
    2277           0 :       if (my_want_state_is_wont (TELOPT_BINARY))
    2278             :         {
    2279           0 :           switch (c)
    2280             :             {
    2281             :             case '\n':
    2282             :               /*
    2283             :                * If we are in CRMOD mode (\r ==> \n)
    2284             :                * on our local machine, then probably
    2285             :                * a newline (unix) is CRLF (TELNET).
    2286             :                */
    2287           0 :               if (MODE_LOCAL_CHARS (globalmode))
    2288             :                 {
    2289           0 :                   NETADD ('\r');
    2290             :                 }
    2291           0 :               NETADD ('\n');
    2292           0 :               bol = flushline = 1;
    2293           0 :               break;
    2294             :             case '\r':
    2295           0 :               if (!crlf)
    2296             :                 {
    2297           0 :                   NET2ADD ('\r', '\0');
    2298             :                 }
    2299             :               else
    2300             :                 {
    2301           0 :                   NET2ADD ('\r', '\n');
    2302             :                 }
    2303           0 :               bol = flushline = 1;
    2304           0 :               break;
    2305             :             case IAC:
    2306           0 :               NET2ADD (IAC, IAC);
    2307           0 :               break;
    2308             :             default:
    2309           0 :               NETADD (c);
    2310           0 :               break;
    2311             :             }
    2312             :         }
    2313           0 :       else if (c == IAC)
    2314             :         {
    2315           0 :           NET2ADD (IAC, IAC);
    2316             :         }
    2317             :       else
    2318             :         {
    2319           0 :           NETADD (c);
    2320             :         }
    2321             :     }
    2322           0 :   if (count)
    2323           0 :     ring_consumed (&ttyiring, count);
    2324           0 :   return returnValue || count;  /* Non-zero if we did anything */
    2325             : }
    2326             : 
    2327             : /*
    2328             :  * Scheduler()
    2329             :  *
    2330             :  * Try to do something.
    2331             :  *
    2332             :  * If we do something useful, return 1; else return 0.
    2333             :  *
    2334             :  */
    2335             : 
    2336             : 
    2337             : /* block; should we block in the select ? */
    2338             : int
    2339           9 : Scheduler (int block)
    2340             : {
    2341             :   /* One wants to be a bit careful about setting returnValue
    2342             :    * to one, since a one implies we did some useful work,
    2343             :    * and therefore probably won't be called to block next
    2344             :    * time (TN3270 mode only).
    2345             :    */
    2346             :   int returnValue;
    2347             :   int netin, netout, netex, ttyin, ttyout;
    2348             : 
    2349             :   /* Decide which rings should be processed */
    2350             : 
    2351           9 :   netout = ring_full_count (&netoring) &&
    2352           0 :     (flushline || (my_want_state_is_wont (TELOPT_LINEMODE)
    2353             : #ifdef  KLUDGELINEMODE
    2354           0 :                    && (!kludgelinemode || my_want_state_is_do (TELOPT_SGA))
    2355             : #endif
    2356           0 :      ) || my_want_state_is_will (TELOPT_BINARY));
    2357           9 :   ttyout = ring_full_count (&ttyoring);
    2358             : 
    2359             : #if defined TN3270
    2360             :   ttyin = ring_empty_count (&ttyiring) && (shell_active == 0);
    2361             : #else /* defined(TN3270) */
    2362           9 :   ttyin = ring_empty_count (&ttyiring);
    2363             : #endif /* defined(TN3270) */
    2364             : 
    2365             : #if defined TN3270
    2366             :   netin = ring_empty_count (&netiring);
    2367             : #else /* !defined(TN3270) */
    2368           9 :   netin = !ISend && ring_empty_count (&netiring);
    2369             : #endif /* !defined(TN3270) */
    2370             : 
    2371           9 :   netex = !SYNCHing;
    2372             : 
    2373             :   /* If we have seen a signal recently, reset things */
    2374             : #if defined TN3270 && (defined unix || defined __unix || defined __unix__)
    2375             :   if (HaveInput)
    2376             :     {
    2377             :       HaveInput = 0;
    2378             :       signal (SIGIO, inputAvailable);
    2379             :     }
    2380             : #endif /* TN3270 && (unix || __unix || __unix__) */
    2381             : 
    2382             :   /* Call to system code to process rings */
    2383             : 
    2384           9 :   returnValue = process_rings (netin, netout, netex, ttyin, ttyout, !block);
    2385             : 
    2386             :   /* Now, look at the input rings, looking for work to do. */
    2387             : 
    2388           9 :   if (ring_full_count (&ttyiring))
    2389             :     {
    2390             : #if defined TN3270
    2391             :       if (In3270)
    2392             :         {
    2393             :           int c;
    2394             : 
    2395             :           c = DataFromTerminal (ttyiring.consume,
    2396             :                                 ring_full_consecutive (&ttyiring));
    2397             :           if (c)
    2398             :             {
    2399             :               returnValue = 1;
    2400             :               ring_consumed (&ttyiring, c);
    2401             :             }
    2402             :         }
    2403             :       else
    2404             :         {
    2405             : #endif /* defined(TN3270) */
    2406           0 :           returnValue |= telsnd ();
    2407             : #if defined TN3270
    2408             :         }
    2409             : #endif /* defined(TN3270) */
    2410             :     }
    2411             : 
    2412           9 :   if (ring_full_count (&netiring))
    2413             :     {
    2414             : #if !defined TN3270
    2415           3 :       returnValue |= telrcv ();
    2416             : #else /* !defined(TN3270) */
    2417             :       returnValue = Push3270 ();
    2418             : #endif /* !defined(TN3270) */
    2419             :     }
    2420           9 :   return returnValue;
    2421             : }
    2422             : 
    2423             : /*
    2424             :  * Select from tty and network...
    2425             :  */
    2426             : void
    2427           3 : telnet (char *user)
    2428             : {
    2429           3 :   sys_telnet_init ();
    2430             : 
    2431             : #if defined AUTHENTICATION || defined ENCRYPTION
    2432             :   {
    2433             :     static char *local_host = 0;
    2434             : 
    2435             :     if (!local_host)
    2436             :       local_host = localhost ();
    2437             : 
    2438             :     auth_encrypt_init (local_host, hostname, NULL, "TELNET", 0);
    2439             :     auth_encrypt_user (user);
    2440             :   }
    2441             : #else /* !defined(AUTHENTICATION) && !defined(ENCRYPTION)  */
    2442             :   (void) user;
    2443             : #endif
    2444             : #if !defined TN3270
    2445           3 :   if (telnetport)
    2446             :     {
    2447             : # if defined AUTHENTICATION
    2448             :       if (autologin)
    2449             :         send_will (TELOPT_AUTHENTICATION, 1);
    2450             : # endif
    2451             : # ifdef ENCRYPTION
    2452             :       send_do (TELOPT_ENCRYPT, 1);
    2453             :       send_will (TELOPT_ENCRYPT, 1);
    2454             : # endif /* ENCRYPTION */
    2455           0 :       send_do (TELOPT_SGA, 1);
    2456           0 :       send_will (TELOPT_TTYPE, 1);
    2457           0 :       send_will (TELOPT_NAWS, 1);
    2458           0 :       send_will (TELOPT_TSPEED, 1);
    2459           0 :       send_will (TELOPT_LFLOW, 1);
    2460           0 :       send_will (TELOPT_LINEMODE, 1);
    2461           0 :       send_will (TELOPT_NEW_ENVIRON, 1);
    2462           0 :       send_do (TELOPT_STATUS, 1);
    2463           0 :       if (env_getvalue ("DISPLAY"))
    2464           0 :         send_will (TELOPT_XDISPLOC, 1);
    2465           0 :       if (eight)
    2466           0 :         tel_enter_binary (eight);
    2467             :     }
    2468             : #endif /* !defined(TN3270) */
    2469             : 
    2470             : #if !defined TN3270
    2471             :   for (;;)
    2472             :     {
    2473             :       int schedValue;
    2474             : 
    2475          12 :       while ((schedValue = Scheduler (0)) != 0)
    2476             :         {
    2477           3 :           if (schedValue == -1)
    2478             :             {
    2479           3 :               setcommandmode ();
    2480           3 :               return;
    2481             :             }
    2482             :         }
    2483             : 
    2484           3 :       if (Scheduler (1) == -1)
    2485             :         {
    2486           0 :           setcommandmode ();
    2487           0 :           return;
    2488             :         }
    2489           3 :     }
    2490             : #else /* !defined(TN3270) */
    2491             :   for (;;)
    2492             :     {
    2493             :       int schedValue;
    2494             : 
    2495             :       while (!In3270 && !shell_active)
    2496             :         {
    2497             :           if (Scheduler (1) == -1)
    2498             :             {
    2499             :               setcommandmode ();
    2500             :               return;
    2501             :             }
    2502             :         }
    2503             : 
    2504             :       while ((schedValue = Scheduler (0)) != 0)
    2505             :         {
    2506             :           if (schedValue == -1)
    2507             :             {
    2508             :               setcommandmode ();
    2509             :               return;
    2510             :             }
    2511             :         }
    2512             :       /* If there is data waiting to go out to terminal, don't
    2513             :        * schedule any more data for the terminal.
    2514             :        */
    2515             :       if (ring_full_count (&ttyoring))
    2516             :         {
    2517             :           schedValue = 1;
    2518             :         }
    2519             :       else
    2520             :         {
    2521             :           if (shell_active)
    2522             :             {
    2523             :               if (shell_continue () == 0)
    2524             :                 {
    2525             :                   ConnectScreen ();
    2526             :                 }
    2527             :             }
    2528             :           else if (In3270)
    2529             :             {
    2530             :               schedValue = DoTerminalOutput ();
    2531             :             }
    2532             :         }
    2533             :       if (schedValue && (shell_active == 0))
    2534             :         {
    2535             :           if (Scheduler (1) == -1)
    2536             :             {
    2537             :               setcommandmode ();
    2538             :               return;
    2539             :             }
    2540             :         }
    2541             :     }
    2542             : #endif /* !defined(TN3270) */
    2543             : }
    2544             : 
    2545             : #if 0                           /* XXX - this not being in is a bug */
    2546             : /*
    2547             :  * nextitem()
    2548             :  *
    2549             :  *      Return the address of the next "item" in the TELNET data
    2550             :  * stream.  This will be the address of the next character if
    2551             :  * the current address is a user data character, or it will
    2552             :  * be the address of the character following the TELNET command
    2553             :  * if the current address is a TELNET IAC ("I Am a Command")
    2554             :  * character.
    2555             :  */
    2556             : 
    2557             : static char *
    2558             : nextitem (char *current)
    2559             : {
    2560             :   if ((*current & 0xff) != IAC)
    2561             :     {
    2562             :       return current + 1;
    2563             :     }
    2564             :   switch (*(current + 1) & 0xff)
    2565             :     {
    2566             :     case DO:
    2567             :     case DONT:
    2568             :     case WILL:
    2569             :     case WONT:
    2570             :       return current + 3;
    2571             :     case SB:                    /* loop forever looking for the SE */
    2572             :       {
    2573             :         register char *look = current + 2;
    2574             : 
    2575             :         for (;;)
    2576             :           {
    2577             :             if ((*look++ & 0xff) == IAC)
    2578             :               {
    2579             :                 if ((*look++ & 0xff) == SE)
    2580             :                   {
    2581             :                     return look;
    2582             :                   }
    2583             :               }
    2584             :           }
    2585             :       }
    2586             :     default:
    2587             :       return current + 2;
    2588             :     }
    2589             : }
    2590             : #endif /* 0 */
    2591             : 
    2592             : /*
    2593             :  * netclear()
    2594             :  *
    2595             :  *      We are about to do a TELNET SYNCH operation.  Clear
    2596             :  * the path to the network.
    2597             :  *
    2598             :  *      Things are a bit tricky since we may have sent the first
    2599             :  * byte or so of a previous TELNET command into the network.
    2600             :  * So, we have to scan the network buffer from the beginning
    2601             :  * until we are up to where we want to be.
    2602             :  *
    2603             :  *      A side effect of what we do, just to keep things
    2604             :  * simple, is to clear the urgent data pointer.  The principal
    2605             :  * caller should be setting the urgent data pointer AFTER calling
    2606             :  * us in any case.
    2607             :  */
    2608             : 
    2609             : static void
    2610           0 : netclear (void)
    2611             : {
    2612             : #if 0                           /* XXX */
    2613             :   register char *thisitem, *next;
    2614             :   char *good;
    2615             : # define wewant(p)      ((nfrontp > p) && ((*p&0xff) == IAC) && \
    2616             :                                 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
    2617             : 
    2618             :   thisitem = netobuf;
    2619             : 
    2620             :   while ((next = nextitem (thisitem)) <= netobuf.send)
    2621             :     {
    2622             :       thisitem = next;
    2623             :     }
    2624             : 
    2625             :   /* Now, thisitem is first before/at boundary. */
    2626             : 
    2627             :   good = netobuf;               /* where the good bytes go */
    2628             : 
    2629             :   while (netoring.add > thisitem)
    2630             :     {
    2631             :       if (wewant (thisitem))
    2632             :         {
    2633             :           int length;
    2634             : 
    2635             :           next = thisitem;
    2636             :           do
    2637             :             {
    2638             :               next = nextitem (next);
    2639             :             }
    2640             :           while (wewant (next) && (nfrontp > next));
    2641             :           length = next - thisitem;
    2642             :           memmove (good, thisitem, length);
    2643             :           good += length;
    2644             :           thisitem = next;
    2645             :         }
    2646             :       else
    2647             :         {
    2648             :           thisitem = nextitem (thisitem);
    2649             :         }
    2650             :     }
    2651             : 
    2652             : #endif /* 0 */
    2653           0 : }
    2654             : 
    2655             : /*
    2656             :  * These routines add various telnet commands to the data stream.
    2657             :  */
    2658             : 
    2659             : static void
    2660           0 : doflush (void)
    2661             : {
    2662           0 :   NET2ADD (IAC, DO);
    2663           0 :   NETADD (TELOPT_TM);
    2664           0 :   flushline = 1;
    2665           0 :   flushout = 1;
    2666           0 :   ttyflush (1);                 /* Flush/drop output */
    2667             :   /* do printoption AFTER flush, otherwise the output gets tossed... */
    2668           0 :   printoption ("SENT", DO, TELOPT_TM);
    2669           0 : }
    2670             : 
    2671             : void
    2672           0 : xmitAO (void)
    2673             : {
    2674           0 :   NET2ADD (IAC, AO);
    2675           0 :   printoption ("SENT", IAC, AO);
    2676           0 :   if (autoflush)
    2677             :     {
    2678           0 :       doflush ();
    2679             :     }
    2680           0 : }
    2681             : 
    2682             : 
    2683             : void
    2684           0 : xmitEL (void)
    2685             : {
    2686           0 :   NET2ADD (IAC, EL);
    2687           0 :   printoption ("SENT", IAC, EL);
    2688           0 : }
    2689             : 
    2690             : void
    2691           0 : xmitEC (void)
    2692             : {
    2693           0 :   NET2ADD (IAC, EC);
    2694           0 :   printoption ("SENT", IAC, EC);
    2695           0 : }
    2696             : 
    2697             : 
    2698             : int
    2699           0 : dosynch (void)
    2700             : {
    2701           0 :   netclear ();                  /* clear the path to the network */
    2702           0 :   NETADD (IAC);
    2703           0 :   setneturg ();
    2704           0 :   NETADD (DM);
    2705           0 :   printoption ("SENT", IAC, DM);
    2706           0 :   return 1;
    2707             : }
    2708             : 
    2709             : int want_status_response = 0;
    2710             : 
    2711             : int
    2712           0 : get_status (void)
    2713             : {
    2714             :   unsigned char tmp[16];
    2715             :   register unsigned char *cp;
    2716             : 
    2717           0 :   if (my_want_state_is_dont (TELOPT_STATUS))
    2718             :     {
    2719           0 :       printf ("Remote side does not support STATUS option\n");
    2720           0 :       return 0;
    2721             :     }
    2722           0 :   cp = tmp;
    2723             : 
    2724           0 :   *cp++ = IAC;
    2725           0 :   *cp++ = SB;
    2726           0 :   *cp++ = TELOPT_STATUS;
    2727           0 :   *cp++ = TELQUAL_SEND;
    2728           0 :   *cp++ = IAC;
    2729           0 :   *cp++ = SE;
    2730           0 :   if (NETROOM () >= cp - tmp)
    2731             :     {
    2732           0 :       ring_supply_data (&netoring, tmp, cp - tmp);
    2733           0 :       printsub ('>', tmp + 2, cp - tmp - 2);
    2734             :     }
    2735           0 :   ++want_status_response;
    2736           0 :   return 1;
    2737             : }
    2738             : 
    2739             : void
    2740           0 : intp (void)
    2741             : {
    2742           0 :   NET2ADD (IAC, IP);
    2743           0 :   printoption ("SENT", IAC, IP);
    2744           0 :   flushline = 1;
    2745           0 :   if (autoflush)
    2746             :     {
    2747           0 :       doflush ();
    2748             :     }
    2749           0 :   if (autosynch)
    2750             :     {
    2751           0 :       dosynch ();
    2752             :     }
    2753           0 : }
    2754             : 
    2755             : void
    2756           0 : sendbrk (void)
    2757             : {
    2758           0 :   NET2ADD (IAC, BREAK);
    2759           0 :   printoption ("SENT", IAC, BREAK);
    2760           0 :   flushline = 1;
    2761           0 :   if (autoflush)
    2762             :     {
    2763           0 :       doflush ();
    2764             :     }
    2765           0 :   if (autosynch)
    2766             :     {
    2767           0 :       dosynch ();
    2768             :     }
    2769           0 : }
    2770             : 
    2771             : void
    2772           0 : sendabort (void)
    2773             : {
    2774           0 :   NET2ADD (IAC, ABORT);
    2775           0 :   printoption ("SENT", IAC, ABORT);
    2776           0 :   flushline = 1;
    2777           0 :   if (autoflush)
    2778             :     {
    2779           0 :       doflush ();
    2780             :     }
    2781           0 :   if (autosynch)
    2782             :     {
    2783           0 :       dosynch ();
    2784             :     }
    2785           0 : }
    2786             : 
    2787             : void
    2788           0 : sendsusp (void)
    2789             : {
    2790           0 :   NET2ADD (IAC, SUSP);
    2791           0 :   printoption ("SENT", IAC, SUSP);
    2792           0 :   flushline = 1;
    2793           0 :   if (autoflush)
    2794             :     {
    2795           0 :       doflush ();
    2796             :     }
    2797           0 :   if (autosynch)
    2798             :     {
    2799           0 :       dosynch ();
    2800             :     }
    2801           0 : }
    2802             : 
    2803             : void
    2804           0 : sendeof (void)
    2805             : {
    2806           0 :   NET2ADD (IAC, xEOF);
    2807           0 :   printoption ("SENT", IAC, xEOF);
    2808           0 : }
    2809             : 
    2810             : void
    2811           0 : sendayt (void)
    2812             : {
    2813           0 :   NET2ADD (IAC, AYT);
    2814           0 :   printoption ("SENT", IAC, AYT);
    2815           0 : }
    2816             : 
    2817             : /*
    2818             :  * Send a window size update to the remote system.
    2819             :  */
    2820             : 
    2821             : void
    2822           0 : sendnaws (void)
    2823             : {
    2824             :   long rows, cols;
    2825             :   unsigned char tmp[16];
    2826             :   register unsigned char *cp;
    2827             : 
    2828           0 :   if (my_state_is_wont (TELOPT_NAWS))
    2829           0 :     return;
    2830             : 
    2831             : #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
    2832             :                             if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
    2833             : 
    2834           0 :   if (TerminalWindowSize (&rows, &cols) == 0)
    2835             :     {                           /* Failed */
    2836           0 :       return;
    2837             :     }
    2838             : 
    2839           0 :   cp = tmp;
    2840             : 
    2841           0 :   *cp++ = IAC;
    2842           0 :   *cp++ = SB;
    2843           0 :   *cp++ = TELOPT_NAWS;
    2844           0 :   PUTSHORT (cp, cols);
    2845           0 :   PUTSHORT (cp, rows);
    2846           0 :   *cp++ = IAC;
    2847           0 :   *cp++ = SE;
    2848           0 :   if (NETROOM () >= cp - tmp)
    2849             :     {
    2850           0 :       ring_supply_data (&netoring, tmp, cp - tmp);
    2851           0 :       printsub ('>', tmp + 2, cp - tmp - 2);
    2852             :     }
    2853             : }
    2854             : 
    2855             : void
    2856           0 : tel_enter_binary (int rw)
    2857             : {
    2858           0 :   if (rw & 1)
    2859           0 :     send_do (TELOPT_BINARY, 1);
    2860           0 :   if (rw & 2)
    2861           0 :     send_will (TELOPT_BINARY, 1);
    2862           0 : }
    2863             : 
    2864             : void
    2865           0 : tel_leave_binary (int rw)
    2866             : {
    2867           0 :   if (rw & 1)
    2868           0 :     send_dont (TELOPT_BINARY, 1);
    2869           0 :   if (rw & 2)
    2870           0 :     send_wont (TELOPT_BINARY, 1);
    2871           0 : }

Generated by: LCOV version 1.11