/[inetutils]/inetutils/telnetd/telnetd.c
ViewVC logotype

Diff of /inetutils/telnetd/telnetd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.24 by marcus, Mon Oct 30 01:28:38 2000 UTC revision 1.25 by gray, Thu Mar 14 14:26:04 2002 UTC
# Line 352  main(int argc, char **argv) Line 352  main(int argc, char **argv)
352  #endif  #endif
353                          break;                          break;
354    
                 case 'u':  
 #ifdef HAVE_UTMP_UT_HOST  
                         utmp_len = atoi(optarg);  
 #endif  
                         break;  
   
355                  case 'U':                  case 'U':
356                          registerd_host_only = 1;                          registerd_host_only = 1;
357                          break;                          break;
# Line 790  char *hostname; Line 784  char *hostname;
784  char host_name[MAXHOSTNAMELEN];  char host_name[MAXHOSTNAMELEN];
785  char remote_host_name[MAXHOSTNAMELEN];  char remote_host_name[MAXHOSTNAMELEN];
786    
 #ifndef convex  
 extern void telnet P((int, int));  
 #else  
787  extern void telnet P((int, int, char *));  extern void telnet P((int, int, char *));
 #endif  
788    
789  /*  /*
790   * Get a pty, scan input lines.   * Get a pty, scan input lines.
791   */   */
792  int  int
793  doit(struct sockaddr_in *who)  doit (struct sockaddr_in *who)
794  {  {
795          char *host, *inet_ntoa();    char *host, *inet_ntoa();
796          int t;    int t;
797          struct hostent *hp;    struct hostent *hp;
798          int level;    int level;
799          int ptynum;    char user_name[256];
800          char user_name[256];  
801      /* get name of connected client */
802          /*    hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
803           * Find an available pty to use.                       who->sin_family);
804           */  
805  #ifndef convex    if (hp == NULL && registerd_host_only)
806          pty = getpty(&ptynum);      fatal(net, "Couldn't resolve your address into a host name.\r\n\
807          if (pty < 0)  Please contact your net administrator");
808                  fatal(net, "All network ports in use");    else if (hp)
809  #else      host = hp->h_name;
810          for (;;) {    else
811                  char *lp;      host = inet_ntoa (who->sin_addr);
812                  extern char *line, *getpty();  
813      /*
814                  if ((lp = getpty()) == NULL)     * We must make a copy because Kerberos is probably going
815                          fatal(net, "Out of ptys");     * to also do a gethost* and overwrite the static data...
816       */
817                  if ((pty = open(lp, O_RDWR)) >= 0) {    strncpy (remote_host_name, host, sizeof (remote_host_name)-1);
818                          strcpy(line,lp);    remote_host_name[sizeof (remote_host_name)-1] = 0;
819                          line[5] = 't';    host = remote_host_name;
820                          break;  
821                  }    gethostname (host_name, sizeof (host_name));
822          }    hostname = host_name;
823  #endif  
824    #if defined(AUTHENTICATION) || defined(ENCRYPTION)
825  #if     defined(_SC_CRAY_SECURE_SYS)    auth_encrypt_init (hostname, host, "TELNETD", 1);
826          /*  #endif
827           *      set ttyp line security label  
828           */    init_env ();
829          if (secflag) {    
830                  char slave_dev[16];    /* get terminal type. */
831      *user_name = 0;
832                  sprintf(tty_dev, "/dev/pty/%03d", ptynum);    level = getterminaltype (user_name);
833                  if (setdevs(tty_dev, &dv) < 0)    setenv ("TERM", terminaltype ? terminaltype : "network", 1);
                         fatal(net, "cannot set pty security");  
                 sprintf(slave_dev, "/dev/ttyp%03d", ptynum);  
                 if (setdevs(slave_dev, &dv) < 0)  
                         fatal(net, "cannot set tty security");  
         }  
 #endif  /* _SC_CRAY_SECURE_SYS */  
   
         /* get name of connected client */  
         hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),  
                 who->sin_family);  
   
         if (hp == NULL && registerd_host_only) {  
                 fatal(net, "Couldn't resolve your address into a host name.\r\n\  
          Please contact your net administrator");  
         } else if (hp  
 #ifdef HAVE_UTMP_UT_HOST  
                    && (strlen(hp->h_name) <=  
                        (unsigned int)((utmp_len < 0) ? -utmp_len : utmp_len))  
 #endif  
                    ) {  
                 host = hp->h_name;  
         } else {  
                 host = inet_ntoa(who->sin_addr);  
         }  
         /*  
          * We must make a copy because Kerberos is probably going  
          * to also do a gethost* and overwrite the static data...  
          */  
         strncpy(remote_host_name, host, sizeof(remote_host_name)-1);  
         remote_host_name[sizeof(remote_host_name)-1] = 0;  
         host = remote_host_name;  
   
         (void) gethostname(host_name, sizeof (host_name));  
         hostname = host_name;  
   
 #if     defined(AUTHENTICATION) || defined(ENCRYPTION)  
         auth_encrypt_init(hostname, host, "TELNETD", 1);  
 #endif  
   
         init_env();  
         /*  
          * get terminal type.  
          */  
         *user_name = 0;  
         level = getterminaltype(user_name);  
         setenv("TERM", terminaltype ? terminaltype : "network", 1);  
   
         /*  
          * Start up the login process on the slave side of the terminal  
          */  
 #ifndef convex  
         startslave(host, level, user_name);  
834    
835  #if     defined(_SC_CRAY_SECURE_SYS)    pty = startslave (host, level, user_name);
836          if (secflag) {    telnet(net, pty, host);
                 if (setulvl(dv.dv_actlvl) < 0)  
                         fatal(net,"cannot setulvl()");  
                 if (setucmp(dv.dv_actcmp) < 0)  
                         fatal(net, "cannot setucmp()");  
         }  
 #endif  /* _SC_CRAY_SECURE_SYS */  
   
         telnet(net, pty);  /* begin server processing */  
 #else  
         telnet(net, pty, host);  
 #endif  
         /*NOTREACHED*/  
837  }  /* end of doit */  }  /* end of doit */
838    
839  #if     defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)  #if     defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
# Line 928  Xterm_output(char **ibufp, char **obuf, Line 854  Xterm_output(char **ibufp, char **obuf,
854   * hand data to telnet receiver finite state machine.   * hand data to telnet receiver finite state machine.
855   */   */
856  void  void
857  #ifndef convex  telnet (int f, int p, char *host)
 telnet(int f, int p)  
 #else  
 telnet(int f, int p, char *host)  
 #endif  
858  {  {
859          int on = 1;    int on = 1;
860  #define TABBUFSIZ       512  #define TABBUFSIZ       512
861          char    defent[TABBUFSIZ];    char  defent[TABBUFSIZ];
862          char    defstrs[TABBUFSIZ];    char  defstrs[TABBUFSIZ];
863  #undef  TABBUFSIZ  #undef  TABBUFSIZ
864  #undef HE /* Make sure its not defined as a macro. */  #undef HE /* Make sure its not defined as a macro. */
865          char *HE;    char *HE;
866          char *HN;    char *HN;
867          char *IM;    char *IM;
868          void netflush();    void netflush();
869          int nfd;    int nfd;
870    
871          /*    /*
872           * Initialize the slc mapping table.     * Initialize the slc mapping table.
873           */     */
874          get_slc_defaults();    get_slc_defaults ();
875    
876          /*    /*
877           * Do some tests where it is desireable to wait for a response.     * Do some tests where it is desireable to wait for a response.
878           * Rather than doing them slowly, one at a time, do them all     * Rather than doing them slowly, one at a time, do them all
879           * at once.     * at once.
880           */     */
881          if (my_state_is_wont(TELOPT_SGA))    if (my_state_is_wont (TELOPT_SGA))
882                  send_will(TELOPT_SGA, 1);      send_will (TELOPT_SGA, 1);
883          /*    /*
884           * Is the client side a 4.2 (NOT 4.3) system?  We need to know this     * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
885           * because 4.2 clients are unable to deal with TCP urgent data.     * because 4.2 clients are unable to deal with TCP urgent data.
886           *     *
887           * To find out, we send out a "DO ECHO".  If the remote system     * To find out, we send out a "DO ECHO".  If the remote system
888           * answers "WILL ECHO" it is probably a 4.2 client, and we note     * answers "WILL ECHO" it is probably a 4.2 client, and we note
889           * that fact ("WILL ECHO" ==> that the client will echo what     * that fact ("WILL ECHO" ==> that the client will echo what
890           * WE, the server, sends it; it does NOT mean that the client will     * WE, the server, sends it; it does NOT mean that the client will
891           * echo the terminal input).     * echo the terminal input).
892           */     */
893          send_do(TELOPT_ECHO, 1);    send_do (TELOPT_ECHO, 1);
894    
895  #ifdef  LINEMODE  #ifdef  LINEMODE
896          if (his_state_is_wont(TELOPT_LINEMODE)) {    if (his_state_is_wont (TELOPT_LINEMODE))
897                  /* Query the peer for linemode support by trying to negotiate      {
898                   * the linemode option.        /* Query the peer for linemode support by trying to negotiate
899                   */         * the linemode option.
900                  linemode = 0;         */
901                  editmode = 0;        linemode = 0;
902                  send_do(TELOPT_LINEMODE, 1);  /* send do linemode */        editmode = 0;
903          }        send_do (TELOPT_LINEMODE, 1);  /* send do linemode */
904        }
905  #endif  /* LINEMODE */  #endif  /* LINEMODE */
906    
907          /*    /*
908           * Send along a couple of other options that we wish to negotiate.     * Send along a couple of other options that we wish to negotiate.
909           */     */
910          send_do(TELOPT_NAWS, 1);    send_do (TELOPT_NAWS, 1);
911          send_will(TELOPT_STATUS, 1);    send_will (TELOPT_STATUS, 1);
912          flowmode = 1;           /* default flow control state */    flowmode = 1;         /* default flow control state */
913          restartany = -1;        /* uninitialized... */    restartany = -1;      /* uninitialized... */
914          send_do(TELOPT_LFLOW, 1);    send_do (TELOPT_LFLOW, 1);
915    
916          /*    /*
917           * Spin, waiting for a response from the DO ECHO.  However,     * Spin, waiting for a response from the DO ECHO.  However,
918           * some REALLY DUMB telnets out there might not respond     * some REALLY DUMB telnets out there might not respond
919           * to the DO ECHO.  So, we spin looking for NAWS, (most dumb     * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
920           * telnets so far seem to respond with WONT for a DO that     * telnets so far seem to respond with WONT for a DO that
921           * they don't understand...) because by the time we get the     * they don't understand...) because by the time we get the
922           * response, it will already have processed the DO ECHO.     * response, it will already have processed the DO ECHO.
923           * Kludge upon kludge.     * Kludge upon kludge.
924           */     */
925          while (his_will_wont_is_changing(TELOPT_NAWS))    while (his_will_wont_is_changing (TELOPT_NAWS))
926                  ttloop();      ttloop ();
927    
928          /*    /*
929           * But...     * But...
930           * The client might have sent a WILL NAWS as part of its     * The client might have sent a WILL NAWS as part of its
931           * startup code; if so, we'll be here before we get the     * startup code; if so, we'll be here before we get the
932           * response to the DO ECHO.  We'll make the assumption     * response to the DO ECHO.  We'll make the assumption
933           * that any implementation that understands about NAWS     * that any implementation that understands about NAWS
934           * is a modern enough implementation that it will respond     * is a modern enough implementation that it will respond
935           * to our DO ECHO request; hence we'll do another spin     * to our DO ECHO request; hence we'll do another spin
936           * waiting for the ECHO option to settle down, which is     * waiting for the ECHO option to settle down, which is
937           * what we wanted to do in the first place...     * what we wanted to do in the first place...
938           */     */
939          if (his_want_state_is_will(TELOPT_ECHO) &&    if (his_want_state_is_will (TELOPT_ECHO)
940              his_state_is_will(TELOPT_NAWS)) {        && his_state_is_will(TELOPT_NAWS))
941                  while (his_will_wont_is_changing(TELOPT_ECHO))      {
942                          ttloop();        while (his_will_wont_is_changing (TELOPT_ECHO))
943          }          ttloop ();
944          /*      }
          * On the off chance that the telnet client is broken and does not  
          * respond to the DO ECHO we sent, (after all, we did send the  
          * DO NAWS negotiation after the DO ECHO, and we won't get here  
          * until a response to the DO NAWS comes back) simulate the  
          * receipt of a will echo.  This will also send a WONT ECHO  
          * to the client, since we assume that the client failed to  
          * respond because it believes that it is already in DO ECHO  
          * mode, which we do not want.  
          */  
         if (his_want_state_is_will(TELOPT_ECHO)) {  
                 DIAG(TD_OPTIONS,  
                         {sprintf(nfrontp, "td: simulating recv\r\n");  
                          nfrontp += strlen(nfrontp);});  
                 willoption(TELOPT_ECHO);  
         }  
945    
946          /*    /*
947           * Finally, to clean things up, we turn on our echo.  This     * On the off chance that the telnet client is broken and does not
948           * will break stupid 4.2 telnets out of local terminal echo.     * respond to the DO ECHO we sent, (after all, we did send the
949           */     * DO NAWS negotiation after the DO ECHO, and we won't get here
950       * until a response to the DO NAWS comes back) simulate the
951       * receipt of a will echo.  This will also send a WONT ECHO
952       * to the client, since we assume that the client failed to
953       * respond because it believes that it is already in DO ECHO
954       * mode, which we do not want.
955       */
956      if (his_want_state_is_will (TELOPT_ECHO))
957        {
958          DIAG (TD_OPTIONS,
959                {sprintf (nfrontp, "td: simulating recv\r\n");
960                nfrontp += strlen (nfrontp);});
961          willoption (TELOPT_ECHO);
962        }
963    
964          if (my_state_is_wont(TELOPT_ECHO))    /*
965                  send_will(TELOPT_ECHO, 1);     * Finally, to clean things up, we turn on our echo.  This
966       * will break stupid 4.2 telnets out of local terminal echo.
967       */
968      
969      if (my_state_is_wont (TELOPT_ECHO))
970        send_will (TELOPT_ECHO, 1);
971    
972  #ifndef HAVE_STREAMSPTY  #ifndef HAVE_STREAMSPTY
973          /*    /*
974           * Turn on packet mode     * Turn on packet mode
975           */     */
976          (void) ioctl(p, TIOCPKT, (char *)&on);    ioctl(p, TIOCPKT, (char *)&on);
977  #endif  #endif
978    
979  #if     defined(LINEMODE) && defined(KLUDGELINEMODE)  #if     defined(LINEMODE) && defined(KLUDGELINEMODE)
980          /*    /*
981           * Continuing line mode support.  If client does not support     * Continuing line mode support.  If client does not support
982           * real linemode, attempt to negotiate kludge linemode by sending     * real linemode, attempt to negotiate kludge linemode by sending
983           * the do timing mark sequence.     * the do timing mark sequence.
984           */     */
985          if (lmodetype < REAL_LINEMODE)    if (lmodetype < REAL_LINEMODE)
986                  send_do(TELOPT_TM, 1);      send_do (TELOPT_TM, 1);
987  #endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */  #endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
988    
989          /*    /*
990           * Call telrcv() once to pick up anything received during     * Call telrcv() once to pick up anything received during
991           * terminal type negotiation, 4.2/4.3 determination, and     * terminal type negotiation, 4.2/4.3 determination, and
992           * linemode negotiation.     * linemode negotiation.
993           */     */
994          telrcv();    telrcv ();
995    
996          (void) ioctl(f, FIONBIO, (char *)&on);    ioctl (f, FIONBIO, (char *)&on);
997          (void) ioctl(p, FIONBIO, (char *)&on);    ioctl (p, FIONBIO, (char *)&on);
998  #if     defined(CRAY2) && defined(UNICOS5)  #if     defined(CRAY2) && defined(UNICOS5)
999          init_termdriver(f, p, interrupts, sendbrk);    init_termdriver (f, p, interrupts, sendbrk);
1000  #endif  #endif
1001    
1002  #if     defined(SO_OOBINLINE)  #if     defined(SO_OOBINLINE)
1003          (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,    setsockopt (net, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof on);
                                 (char *)&on, sizeof on);  
1004  #endif  /* defined(SO_OOBINLINE) */  #endif  /* defined(SO_OOBINLINE) */
1005    
1006  #ifdef  SIGTSTP  #ifdef  SIGTSTP
1007          (void) signal(SIGTSTP, SIG_IGN);    signal (SIGTSTP, SIG_IGN);
1008  #endif  #endif
1009  #ifdef  SIGTTOU  #ifdef  SIGTTOU
1010          /*    /*
1011           * Ignoring SIGTTOU keeps the kernel from blocking us     * Ignoring SIGTTOU keeps the kernel from blocking us
1012           * in ttioct() in /sys/tty.c.     * in ttioct() in /sys/tty.c.
1013           */     */
1014          (void) signal(SIGTTOU, SIG_IGN);    signal (SIGTTOU, SIG_IGN);
1015  #endif  #endif
1016    
1017          (void) signal(SIGCHLD, cleanup);    signal (SIGCHLD, cleanup);
1018    
1019  #if     defined(CRAY2) && defined(UNICOS5)  #if     defined(CRAY2) && defined(UNICOS5)
1020          /*    /*
1021           * Cray-2 will send a signal when pty modes are changed by slave     * Cray-2 will send a signal when pty modes are changed by slave
1022           * side.  Set up signal handler now.     * side.  Set up signal handler now.
1023           */     */
1024          if ((int)signal(SIGUSR1, termstat) < 0)    if ((int)signal (SIGUSR1, termstat) < 0)
1025                  perror("signal");      perror ("signal");
1026          else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)    else if (ioctl (p, TCSIGME, (char *)SIGUSR1) < 0)
1027                  perror("ioctl:TCSIGME");      perror ("ioctl:TCSIGME");
1028          /*    /*
1029           * Make processing loop check terminal characteristics early on.     * Make processing loop check terminal characteristics early on.
1030           */     */
1031          termstat();    termstat ();
1032  #endif  #endif
1033    
1034  #ifdef  TIOCNOTTY  #ifdef  TIOCNOTTY
1035          {    {
1036                  register int t;      register int t;
1037                  t = open(PATH_TTY, O_RDWR);      t = open(PATH_TTY, O_RDWR);
1038                  if (t >= 0) {      if (t >= 0)
1039                          (void) ioctl(t, TIOCNOTTY, (char *)0);        {
1040                          (void) close(t);          ioctl (t, TIOCNOTTY, (char *)0);
1041                  }          close (t);
1042          }        }
1043      }
1044  #endif  #endif
1045    
1046  #if     defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)  #if     defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
1047          (void) setsid();    setsid ();
1048          ioctl(p, TIOCSCTTY, 0);    ioctl (p, TIOCSCTTY, 0);
1049  #endif  #endif
1050    
1051          /*    /*
1052           * Show banner that getty never gave.     * Show banner that getty never gave.
1053           *     *
1054           * We put the banner in the pty input buffer.  This way, it     * We put the banner in the pty input buffer.  This way, it
1055           * gets carriage return null processing, etc., just like all     * gets carriage return null processing, etc., just like all
1056           * other pty --> client data.     * other pty --> client data.
1057           */     */
1058    
1059  #if     !defined(CRAY) || !defined(NEWINIT)  #if     !defined(CRAY) || !defined(NEWINIT)
1060          if (getenv("USER"))    if (getenv ("USER"))
1061                  hostinfo = 0;      hostinfo = 0;
1062  #endif  #endif
1063    
1064          if (getent(defent, "default") == 1) {    if (getent (defent, "default") == 1)
1065                  char *getstr();      {
1066                  char *cp=defstrs;        char *getstr ();
1067          char *cp=defstrs;
1068                  HE = getstr("he", &cp);                  
1069                  HN = getstr("hn", &cp);        HE = getstr ("he", &cp);
1070                  IM = getstr("im", &cp);        HN = getstr ("hn", &cp);
1071                  if (HN && *HN)        IM = getstr ("im", &cp);
1072                          (void) strcpy(host_name, HN);        if (HN && *HN)
1073                  if (IM == 0)          strcpy (host_name, HN);
1074                          IM = "";        if (IM == 0)
1075          } else {          IM = "";
1076        }
1077      else
1078        {
1079  #ifdef HAVE_UNAME  #ifdef HAVE_UNAME
1080                  struct utsname u;        struct utsname u;
1081  #endif  #endif
1082    
1083  #ifdef DEFAULT_IM  #ifdef DEFAULT_IM
1084                  IM = DEFAULT_IM;        IM = DEFAULT_IM;
1085  #else  #else
1086                  IM = 0;        IM = 0;
1087  #ifdef HAVE_UNAME  #ifdef HAVE_UNAME
1088                  if (uname (&u) == 0) {        if (uname (&u) == 0)
1089                          IM = malloc (strlen (UNAME_IM_PREFIX)          {
1090                                       + strlen (u.sysname)            IM = malloc (strlen (UNAME_IM_PREFIX)
1091                                       + 1 + strlen (u.release)                         + strlen (u.sysname)
1092                                       + strlen (UNAME_IM_SUFFIX) + 1);                         + 1 + strlen (u.release)
1093                          if (IM)                         + strlen (UNAME_IM_SUFFIX) + 1);
1094                                  sprintf (IM, "%s%s %s%s",            if (IM)
1095                                           UNAME_IM_PREFIX,              sprintf (IM, "%s%s %s%s",
1096                                           u.sysname, u.release,                       UNAME_IM_PREFIX,
1097                                           UNAME_IM_SUFFIX);                       u.sysname, u.release,
1098                  }                       UNAME_IM_SUFFIX);
1099            }
1100  #endif /* HAVE_UNAME */  #endif /* HAVE_UNAME */
1101                  if (! IM)        if (! IM)
1102                          IM = "\r\n\nUNIX (%h) (%t)\r\n\n";          IM = "\r\n\nUNIX (%h) (%t)\r\n\n";
1103  #endif /* DEFAULT_IM */  #endif /* DEFAULT_IM */
1104    
1105                  HE = 0;        HE = 0;
1106          }      }
1107    
1108          edithost(HE, host_name);    edithost (HE, host_name);
1109          if (hostinfo && *IM)    if (hostinfo && *IM)
1110                  putf(IM, ptyibuf2);      putf (IM, ptyibuf2);
1111    
1112          if (pcc)    if (pcc)
1113                  (void) strncat(ptyibuf2, ptyip, pcc+1);      strncat (ptyibuf2, ptyip, pcc+1);
1114          ptyip = ptyibuf2;    ptyip = ptyibuf2;
1115          pcc = strlen(ptyip);    pcc = strlen (ptyip);
1116  #ifdef  LINEMODE  #ifdef  LINEMODE
1117          /*    /*
1118           * Last check to make sure all our states are correct.     * Last check to make sure all our states are correct.
1119           */     */
1120          init_termbuf();    init_termbuf ();
1121          localstat();    localstat ();
1122  #endif  /* LINEMODE */  #endif  /* LINEMODE */
1123    
1124          DIAG(TD_REPORT,    DIAG (TD_REPORT,
1125                  {sprintf(nfrontp, "td: Entering processing loop\r\n");          {sprintf (nfrontp, "td: Entering processing loop\r\n");
1126                   nfrontp += strlen(nfrontp);});          nfrontp += strlen (nfrontp);});
1127    
1128  #ifdef  convex    nfd = ((f > p) ? f : p) + 1;
1129          startslave(host);    for (;;)
1130  #endif      {
1131          fd_set ibits, obits, xbits;
1132          nfd = ((f > p) ? f : p) + 1;        register int c;
         for (;;) {  
                 fd_set ibits, obits, xbits;  
                 register int c;  
1133    
1134                  if (ncc < 0 && pcc < 0)        if (ncc < 0 && pcc < 0)
1135                          break;          break;
1136    
1137  #if     defined(CRAY2) && defined(UNICOS5)  #if     defined(CRAY2) && defined(UNICOS5)
1138                  if (needtermstat)        if (needtermstat)
1139                          _termstat();          _termstat ();
1140  #endif  /* defined(CRAY2) && defined(UNICOS5) */  #endif  /* defined(CRAY2) && defined(UNICOS5) */
1141                  FD_ZERO(&ibits);        FD_ZERO (&ibits);
1142                  FD_ZERO(&obits);        FD_ZERO (&obits);
1143                  FD_ZERO(&xbits);        FD_ZERO (&xbits);
1144                  /*        /*
1145                   * Never look for input if there's still         * Never look for input if there's still
1146                   * stuff in the corresponding output buffer         * stuff in the corresponding output buffer
1147                   */         */
1148                  if (nfrontp - nbackp || pcc > 0) {        if (nfrontp - nbackp || pcc > 0)
1149                          FD_SET(f, &obits);          FD_SET (f, &obits);
1150                  } else {        else
1151                          FD_SET(p, &ibits);          FD_SET(p, &ibits);
1152                  }      
1153                  if (pfrontp - pbackp || ncc > 0) {        if (pfrontp - pbackp || ncc > 0)
1154                          FD_SET(p, &obits);          FD_SET (p, &obits);
1155                  } else {        else
1156                          FD_SET(f, &ibits);          FD_SET (f, &ibits);
1157                  }                  
1158                  if (!SYNCHing) {        if (!SYNCHing)
1159                          FD_SET(f, &xbits);          FD_SET (f, &xbits);
                 }  
                 if ((c = select(nfd, &ibits, &obits, &xbits,  
                                                 (struct timeval *)0)) < 1) {  
                         if (c == -1) {  
                                 if (errno == EINTR) {  
                                         continue;  
                                 }  
                         }  
                         sleep(5);  
                         continue;  
                 }  
1160    
1161                  /*        c = select (nfd, &ibits, &obits, &xbits, NULL);
1162                   * Any urgent data?        if (c == -1)
1163                   */          {
1164                  if (FD_ISSET(net, &xbits)) {            if (errno != EINTR)
1165                      SYNCHing = 1;              sleep(5);
1166                  }            continue;
1167            }
1168    
1169                  /*        /*
1170                   * Something to read from the network...         * Any urgent data?
1171                   */         */
1172                  if (FD_ISSET(net, &ibits)) {        if (FD_ISSET (net, &xbits))
1173  #if     !defined(SO_OOBINLINE)          SYNCHing = 1;
                         /*  
                          * In 4.2 (and 4.3 beta) systems, the  
                          * OOB indication and data handling in the kernel  
                          * is such that if two separate TCP Urgent requests  
                          * come in, one byte of TCP data will be overlaid.  
                          * This is fatal for Telnet, but we try to live  
                          * with it.  
                          *  
                          * In addition, in 4.2 (and...), a special protocol  
                          * is needed to pick up the TCP Urgent data in  
                          * the correct sequence.  
                          *  
                          * What we do is:  if we think we are in urgent  
                          * mode, we look to see if we are "at the mark".  
                          * If we are, we do an OOB receive.  If we run  
                          * this twice, we will do the OOB receive twice,  
                          * but the second will fail, since the second  
                          * time we were "at the mark", but there wasn't  
                          * any data there (the kernel doesn't reset  
                          * "at the mark" until we do a normal read).  
                          * Once we've read the OOB data, we go ahead  
                          * and do normal reads.  
                          *  
                          * There is also another problem, which is that  
                          * since the OOB byte we read doesn't put us  
                          * out of OOB state, and since that byte is most  
                          * likely the TELNET DM (data mark), we would  
                          * stay in the TELNET SYNCH (SYNCHing) state.  
                          * So, clocks to the rescue.  If we've "just"  
                          * received a DM, then we test for the  
                          * presence of OOB data when the receive OOB  
                          * fails (and AFTER we did the normal mode read  
                          * to clear "at the mark").  
                          */  
                     if (SYNCHing) {  
                         int atmark;  
1174    
1175                          (void) ioctl(net, SIOCATMARK, (char *)&atmark);  
1176                          if (atmark) {        /*
1177                              ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);         * Something to read from the network...
1178                              if ((ncc == -1) && (errno == EINVAL)) {         */
1179                                  ncc = read(net, netibuf, sizeof (netibuf));        if (FD_ISSET (net, &ibits))
1180                                  if (sequenceIs(didnetreceive, gotDM)) {          {
1181                                      SYNCHing = stilloob(net);  #if     !defined(SO_OOBINLINE)
1182                                  }            /*
1183                              }             * In 4.2 (and 4.3 beta) systems, the
1184                          } else {             * OOB indication and data handling in the kernel
1185                              ncc = read(net, netibuf, sizeof (netibuf));             * is such that if two separate TCP Urgent requests
1186                          }             * come in, one byte of TCP data will be overlaid.
1187                      } else {             * This is fatal for Telnet, but we try to live
1188                          ncc = read(net, netibuf, sizeof (netibuf));             * with it.
1189               *
1190               * In addition, in 4.2 (and...), a special protocol
1191               * is needed to pick up the TCP Urgent data in
1192               * the correct sequence.
1193               *
1194               * What we do is:  if we think we are in urgent
1195               * mode, we look to see if we are "at the mark".
1196               * If we are, we do an OOB receive.  If we run
1197               * this twice, we will do the OOB receive twice,
1198               * but the second will fail, since the second
1199               * time we were "at the mark", but there wasn't
1200               * any data there (the kernel doesn't reset
1201               * "at the mark" until we do a normal read).
1202               * Once we've read the OOB data, we go ahead
1203               * and do normal reads.
1204               *
1205               * There is also another problem, which is that
1206               * since the OOB byte we read doesn't put us
1207               * out of OOB state, and since that byte is most
1208               * likely the TELNET DM (data mark), we would
1209               * stay in the TELNET SYNCH (SYNCHing) state.
1210               * So, clocks to the rescue.  If we've "just"
1211               * received a DM, then we test for the
1212               * presence of OOB data when the receive OOB
1213               * fails (and AFTER we did the normal mode read
1214               * to clear "at the mark").
1215               */
1216              if (SYNCHing)
1217                {
1218                  int atmark;
1219    
1220                  ioctl (net, SIOCATMARK, (char *)&atmark);
1221                  if (atmark)
1222                    {
1223                      ncc = recv (net, netibuf, sizeof (netibuf), MSG_OOB);
1224                      if (ncc == -1 && errno == EINVAL)
1225                        {
1226                          ncc = read (net, netibuf, sizeof (netibuf));
1227                          if (sequenceIs (didnetreceive, gotDM))
1228                            SYNCHing = stilloob (net);
1229                      }                      }
1230                      settimer(didnetreceive);                  }
1231                  else
1232                    {
1233                      ncc = read (net, netibuf, sizeof (netibuf));
1234                    }
1235                }
1236              else
1237                {
1238                  ncc = read (net, netibuf, sizeof (netibuf));
1239                }
1240              settimer (didnetreceive);
1241  #else   /* !defined(SO_OOBINLINE)) */  #else   /* !defined(SO_OOBINLINE)) */
1242                      ncc = read(net, netibuf, sizeof (netibuf));            ncc = read (net, netibuf, sizeof (netibuf));
1243  #endif  /* !defined(SO_OOBINLINE)) */  #endif  /* !defined(SO_OOBINLINE)) */
1244                      if (ncc < 0 && errno == EWOULDBLOCK)            if (ncc < 0 && errno == EWOULDBLOCK)
1245                          ncc = 0;              ncc = 0;
1246                      else {            else
1247                          if (ncc <= 0)              {
1248                              break;                if (ncc <= 0)
1249                          netip = netibuf;                  break;
1250                      }                netip = netibuf;
1251                      DIAG((TD_REPORT | TD_NETDATA),              }
1252                              {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);            DIAG ((TD_REPORT | TD_NETDATA),
1253                               nfrontp += strlen(nfrontp);});                  {sprintf (nfrontp, "td: netread %d chars\r\n", ncc);
1254                      DIAG(TD_NETDATA, printdata("nd", netip, ncc));                  nfrontp += strlen (nfrontp);});
1255                  }            DIAG (TD_NETDATA, printdata ("nd", netip, ncc));
1256            }
1257    
1258                  /*        /*
1259                   * Something to read from the pty...         * Something to read from the pty...
1260                   */         */
1261                  if (FD_ISSET(p, &ibits)) {        if (FD_ISSET (p, &ibits))
1262  #ifndef HAVE_STREAMSPTY          {
1263                          pcc = read(p, ptyibuf, BUFSIZ);            pcc = readstream (p, ptyibuf, BUFSIZ);
1264  #else            /*
1265                          pcc = readstream(p, ptyibuf, BUFSIZ);             * On some systems, if we try to read something
1266  #endif             * off the master side before the slave side is
1267                          /*             * opened, we get EIO.
1268                           * On some systems, if we try to read something             */
1269                           * off the master side before the slave side is            if (pcc < 0 &&
1270                           * opened, we get EIO.                (errno == EWOULDBLOCK
                          */  
                         if (pcc < 0 && (errno == EWOULDBLOCK ||  
1271  #ifdef  EAGAIN  #ifdef  EAGAIN
1272                                          errno == EAGAIN ||                 || errno == EAGAIN
1273  #endif  #endif
1274                                          errno == EIO)) {                 || errno == EIO))
1275                                  pcc = 0;              pcc = 0;
1276                          } else {            else  if (pcc <= 0)
1277                                  if (pcc <= 0)              break;
1278                                          break;  
1279  #if     !defined(CRAY2) || !defined(UNICOS5)  #if     !defined(CRAY2) || !defined(UNICOS5)
1280  #if defined (LINEMODE) && defined (TIOCPKT_IOCTL)  #if defined (LINEMODE) && defined (TIOCPKT_IOCTL)
1281                                  /*            /*
1282                                   * If ioctl from pty, pass it through net             * If ioctl from pty, pass it through net
1283                                   */             */
1284                                  if (ptyibuf[0] & TIOCPKT_IOCTL) {            if (ptyibuf[0] & TIOCPKT_IOCTL)
1285                                          copy_termbuf(ptyibuf+1, pcc-1);              {
1286                                          localstat();                copy_termbuf(ptyibuf+1, pcc-1);
1287                                          pcc = 1;                localstat();
1288                                  }                pcc = 1;
1289                }
1290  #endif  /* LINEMODE && TIOCPKT_IOCTL */  #endif  /* LINEMODE && TIOCPKT_IOCTL */
1291                                  if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {            if (ptyibuf[0] & TIOCPKT_FLUSHWRITE)
1292                                          netclear();     /* clear buffer back */              {
1293                  netclear ();      /* clear buffer back */
1294  #ifndef NO_URGENT  #ifndef NO_URGENT
1295                                          /*                /*
1296                                           * There are client telnets on some                 * There are client telnets on some
1297                                           * operating systems get screwed up                 * operating systems get screwed up
1298                                           * royally if we send them urgent                 * royally if we send them urgent
1299                                           * mode data.                 * mode data.
1300                                           */                 */
1301                                          *nfrontp++ = IAC;                *nfrontp++ = IAC;
1302                                          *nfrontp++ = DM;                *nfrontp++ = DM;
1303                                          neturg = nfrontp-1; /* off by one XXX */                neturg = nfrontp-1; /* off by one XXX */
1304                                          DIAG(TD_OPTIONS,                DIAG(TD_OPTIONS,
1305                                              printoption("td: send IAC", DM));                     printoption ("td: send IAC", DM));
1306    
1307  #endif  #endif
1308                                  }              }
1309                                  if (his_state_is_will(TELOPT_LFLOW) &&  
1310                                      (ptyibuf[0] &            if (his_state_is_will (TELOPT_LFLOW)
1311                                       (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {                && (ptyibuf[0] &(TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)))
1312                                          int newflow =              {
1313                                              ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;                int newflow = ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0;
1314                                          if (newflow != flowmode) {                if (newflow != flowmode)
1315                                                  flowmode = newflow;                  {
1316                                                  (void) sprintf(nfrontp,                    flowmode = newflow;
1317                                                          "%c%c%c%c%c%c",                    sprintf(nfrontp,
1318                                                          IAC, SB, TELOPT_LFLOW,                            "%c%c%c%c%c%c",
1319                                                          flowmode ? LFLOW_ON                            IAC, SB, TELOPT_LFLOW,
1320                                                                   : LFLOW_OFF,                            flowmode ? LFLOW_ON
1321                                                          IAC, SE);                            : LFLOW_OFF,
1322                                                  nfrontp += 6;                            IAC, SE);
1323                                                  DIAG(TD_OPTIONS, printsub('>',                    nfrontp += 6;
1324                                                      (unsigned char *)nfrontp-4,                    DIAG (TD_OPTIONS,
1325                                                      4););                          printsub ('>', (unsigned char *)nfrontp-4, 4););
1326                                          }                  }
1327                                  }              }
1328                                  pcc--;            pcc--;
1329                                  ptyip = ptyibuf+1;            ptyip = ptyibuf+1;
1330              
1331  #else   /* defined(CRAY2) && defined(UNICOS5) */  #else   /* defined(CRAY2) && defined(UNICOS5) */
1332                                  if (!uselinemode) {            if (!uselinemode)
1333                                          unpcc = pcc;              {
1334                                          unptyip = ptyibuf;                unpcc = pcc;
1335                                          pcc = term_output(&unptyip, ptyibuf2,                unptyip = ptyibuf;
1336                                                                  &unpcc, BUFSIZ);                pcc = term_output (&unptyip, ptyibuf2, &unpcc, BUFSIZ);
1337                                          ptyip = ptyibuf2;                ptyip = ptyibuf2;
1338                                  } else              }
1339                                          ptyip = ptyibuf;            else
1340                ptyip = ptyibuf;
1341  #endif  /* defined(CRAY2) && defined(UNICOS5) */  #endif  /* defined(CRAY2) && defined(UNICOS5) */
1342                          }          }
                 }  
1343    
1344                  while (pcc > 0) {        while (pcc > 0)
1345                          if ((&netobuf[BUFSIZ] - nfrontp) < 2)          {
1346                                  break;            if ((&netobuf[BUFSIZ] - nfrontp) < 2)
1347                          c = *ptyip++ & 0377, pcc--;              break;
1348                          if (c == IAC)            c = *ptyip++ & 0377;
1349                                  *nfrontp++ = c;            pcc--;
1350              if (c == IAC)
1351                *nfrontp++ = c;
1352  #if     defined(CRAY2) && defined(UNICOS5)  #if     defined(CRAY2) && defined(UNICOS5)
1353                          else if (c == '\n' &&            else if (c == '\n' && my_state_is_wont(TELOPT_BINARY) && newmap)
1354                                       my_state_is_wont(TELOPT_BINARY) && newmap)              *nfrontp++ = '\r';
                                 *nfrontp++ = '\r';  
1355  #endif  /* defined(CRAY2) && defined(UNICOS5) */  #endif  /* defined(CRAY2) && defined(UNICOS5) */
1356                          *nfrontp++ = c;            *nfrontp++ = c;
1357                          if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {            if (c == '\r' && (my_state_is_wont(TELOPT_BINARY)))
1358                                  if (pcc > 0 && ((*ptyip & 0377) == '\n')) {              {
1359                                          *nfrontp++ = *ptyip++ & 0377;                if (pcc > 0 && (*ptyip & 0377) == '\n')
1360                                          pcc--;                  {
1361                                  } else                    *nfrontp++ = *ptyip++ & 0377;
1362                                          *nfrontp++ = '\0';                    pcc--;
                         }  
1363                  }                  }
1364                  else
1365                    *nfrontp++ = '\0';
1366                }
1367            }
1368  #if     defined(CRAY2) && defined(UNICOS5)  #if     defined(CRAY2) && defined(UNICOS5)
1369                  /*        /*
1370                   * If chars were left over from the terminal driver,         * If chars were left over from the terminal driver,
1371                   * note their existence.         * note their existence.
1372                   */         */
1373                  if (!uselinemode && unpcc) {        if (!uselinemode && unpcc)
1374                          pcc = unpcc;          {
1375                          unpcc = 0;            pcc = unpcc;
1376                          ptyip = unptyip;            unpcc = 0;
1377                  }            ptyip = unptyip;
1378            }
1379  #endif  /* defined(CRAY2) && defined(UNICOS5) */  #endif  /* defined(CRAY2) && defined(UNICOS5) */
1380    
1381                  if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)        if (FD_ISSET (f, &obits) && (nfrontp - nbackp) > 0)
1382                          netflush();          netflush ();
1383                  if (ncc > 0)        if (ncc > 0)
1384                          telrcv();          telrcv ();
1385                  if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)        if (FD_ISSET (p, &obits) && (pfrontp - pbackp) > 0)
1386                          ptyflush();          ptyflush ();
1387          }      }
1388          cleanup(0);    cleanup(0);
1389  }  /* end of telnet */  }  /* end of telnet */
1390    
1391  #ifndef TCSIG  #ifndef TCSIG
# Line 1456  telnet(int f, int p, char *host) Line 1394  telnet(int f, int p, char *host)
1394  # endif  # endif
1395  #endif  #endif
1396    
 #ifdef  HAVE_STREAMSPTY  
   
1397  int flowison = -1;  /* current state of flow: -1 is unknown */  int flowison = -1;  /* current state of flow: -1 is unknown */
1398    
1399  int  int
1400  readstream(int p, char *ibuf, int bufsize)  readstream(int p, char *ibuf, int bufsize)
1401  {  {
1402          int flags = 0;  #ifndef HAVE_STREAMSPTY
1403          int ret = 0;    return read (p, ibuf, bufsize);
1404          struct termios *tsp;  #else
1405          struct termio *tp;    int flags = 0;
1406          struct iocblk *ip;    int ret = 0;
1407          char vstop, vstart;    struct termios *tsp;
1408          int ixon;    struct termio *tp;
1409          int newflow;    struct iocblk *ip;
1410      char vstop, vstart;
1411          strbufc.maxlen = BUFSIZ;    int ixon;
1412          strbufc.buf = (char *)ctlbuf;    int newflow;
1413          strbufd.maxlen = bufsize-1;  
1414          strbufd.len = 0;    strbufc.maxlen = BUFSIZ;
1415          strbufd.buf = ibuf+1;    strbufc.buf = (char *)ctlbuf;
1416          ibuf[0] = 0;    strbufd.maxlen = bufsize-1;
1417      strbufd.len = 0;
1418          ret = getmsg(p, &strbufc, &strbufd, &flags);    strbufd.buf = ibuf+1;
1419          if (ret < 0)  /* error of some sort -- probably EAGAIN */    ibuf[0] = 0;
1420                  return(-1);    
1421      ret = getmsg(p, &strbufc, &strbufd, &flags);
1422          if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {    if (ret < 0)  /* error of some sort -- probably EAGAIN */
1423                  /* data message */      return -1;
1424                  if (strbufd.len > 0) {                  /* real data */  
1425                          return(strbufd.len + 1);        /* count header char */    if (strbufc.len <= 0 || ctlbuf[0] == M_DATA)
1426                  } else {      {
1427                          /* nothing there */        /* data message */
1428                          errno = EAGAIN;        if (strbufd.len > 0) /* real data */
1429                          return(-1);          return strbufd.len + 1; /* count header char */
1430                  }        else
1431            {
1432              /* nothing there */
1433              errno = EAGAIN;
1434              return -1;
1435          }          }
1436        }
1437    
1438          /*    /*
1439           * It's a control message.  Return 1, to look at the flag we set     * It's a control message.  Return 1, to look at the flag we set
1440           */     */
1441    
1442      switch (ctlbuf[0])
1443        {
1444        case M_FLUSH:
1445          if (ibuf[1] & FLUSHW)
1446            ibuf[0] = TIOCPKT_FLUSHWRITE;
1447          return 1;
1448    
1449          switch (ctlbuf[0]) {      case M_IOCTL:
1450          case M_FLUSH:        ip = (struct iocblk *) (ibuf+1);
                 if (ibuf[1] & FLUSHW)  
                         ibuf[0] = TIOCPKT_FLUSHWRITE;  
                 return(1);  
   
         case M_IOCTL:  
                 ip = (struct iocblk *) (ibuf+1);  
   
                 switch (ip->ioc_cmd) {  
                 case TCSETS:  
                 case TCSETSW:  
                 case TCSETSF:  
                         tsp = (struct termios *)  
                                         (ibuf+1 + sizeof(struct iocblk));  
                         vstop = tsp->c_cc[VSTOP];  
                         vstart = tsp->c_cc[VSTART];  
                         ixon = tsp->c_iflag & IXON;  
                         break;  
                 case TCSETA:  
                 case TCSETAW:  
                 case TCSETAF:  
                         tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));  
                         vstop = tp->c_cc[VSTOP];  
                         vstart = tp->c_cc[VSTART];  
                         ixon = tp->c_iflag & IXON;  
                         break;  
                 default:  
                         errno = EAGAIN;  
                         return(-1);  
                 }  
1451    
1452                  newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;        switch (ip->ioc_cmd)
1453                  if (newflow != flowison) {  /* it's a change */          {
1454                          flowison = newflow;          case TCSETS:
1455                          ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;          case TCSETSW:
1456                          return(1);          case TCSETSF:
1457                  }            tsp = (struct termios *) (ibuf + 1 + sizeof(struct iocblk));
1458              vstop = tsp->c_cc[VSTOP];
1459              vstart = tsp->c_cc[VSTART];
1460              ixon = tsp->c_iflag & IXON;
1461              break;
1462              
1463            case TCSETA:
1464            case TCSETAW:
1465            case TCSETAF:
1466              tp = (struct termio *) (ibuf + 1 + sizeof(struct iocblk));
1467              vstop = tp->c_cc[VSTOP];
1468              vstart = tp->c_cc[VSTART];
1469              ixon = tp->c_iflag & IXON;
1470              break;
1471    
1472            default:
1473              errno = EAGAIN;
1474              return -1;
1475          }          }
1476    
1477          /* nothing worth doing anything about */        newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
1478          errno = EAGAIN;        if (newflow != flowison)  /* it's a change */
1479          return(-1);          {
1480  }            flowison = newflow;
1481              ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
1482              return 1;
1483            }
1484        }
1485    
1486      /* nothing worth doing anything about */
1487      errno = EAGAIN;
1488      return -1;
1489  #endif /* HAVE_STREAMSPTY */  #endif /* HAVE_STREAMSPTY */
1490    }
1491    
1492  /*  /*
1493   * Send interrupt to process on other side of pty.   * Send interrupt to process on other side of pty.

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.25

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26