Skip to content
telnet.c 28.9 KiB
Newer Older
            printoption(data, "In SUBOPTION processing, RCVD", IAC, c);
            suboption(conn);   /* handle sub-option */
            tn->telrcv_state = TS_IAC;
          SB_ACCUM(tn,c);
          tn->telrcv_state = TS_SB;
          SB_ACCUM(tn, (unsigned char)IAC);
          SB_ACCUM(tn, (unsigned char)SE);
          tn->subpointer -= 2;
          SB_TERM(tn);
          suboption(conn);   /* handle sub-option */
          tn->telrcv_state = TS_DATA;
CURLcode Curl_telnet_done(struct connectdata *conn)
Daniel Stenberg's avatar
Daniel Stenberg committed
{
  struct TELNET *tn = (struct TELNET *)conn->proto.telnet;
  curl_slist_free_all(tn->telnet_vars);
Daniel Stenberg's avatar
Daniel Stenberg committed

  free(conn->proto.telnet);
  conn->proto.telnet = NULL;

CURLcode Curl_telnet(struct connectdata *conn)
  struct SessionHandle *data = conn->data;
  int sockfd = conn->firstsocket;
#ifdef WIN32
  WSAEVENT event_handle;
  WSANETWORKEVENTS events;
  HANDLE stdin_handle;
  HANDLE objs[2];
  DWORD waitret;
#else
  fd_set readfd;
  fd_set keepfd;
  bool keepon = TRUE;
  struct TELNET *tn;

  code = init_telnet(conn);
  if(code)
    return code;

  tn = (struct TELNET *)conn->proto.telnet;
Daniel Stenberg's avatar
Daniel Stenberg committed

  code = check_telnet_options(conn);
  if(code)
    return code;

#ifdef WIN32
  /* We want to wait for both stdin and the socket. Since
  ** the select() function in winsock only works on sockets
  ** we have to use the WaitForMultipleObjects() call.
  */

  /* First, create a sockets event object */
  event_handle = WSACreateEvent();

  /* The get the Windows file handle for stdin */
  stdin_handle = GetStdHandle(STD_INPUT_HANDLE);

  /* Create the list of objects to wait for */
  objs[0] = stdin_handle;
  objs[1] = event_handle;

  /* Tell winsock what events we want to listen to */
  if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) {
    return 0;
  }

  /* Keep on listening and act on events */
  while(keepon) {
    waitret = WaitForMultipleObjects(2, objs, FALSE, INFINITE);
    switch(waitret - WAIT_OBJECT_0)
    {
      case 0:
      {
        unsigned char outbuf[2];
        int out_count = 0;
        ssize_t bytes_written;
        char *buffer = buf;
              
        if(!ReadFile(stdin_handle, buf, 255, &nread, NULL)) {
          keepon = FALSE;
          break;
        }
        
        while(nread--) {
          outbuf[0] = *buffer++;
          out_count = 1;
          if(outbuf[0] == IAC)
            outbuf[out_count++] = IAC;
          
          Curl_write(conn, conn->firstsocket, outbuf,
                     out_count, &bytes_written);
        }
      }
      break;
      
      case 1:
        if(WSAEnumNetworkEvents(sockfd, event_handle, &events)
           != SOCKET_ERROR)
        {
          if(events.lNetworkEvents & FD_READ)
          {
            /* This reallu OUGHT to check its return code. */
            Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
            
            telrcv(conn, (unsigned char *)buf, nread);
            
            fflush(stdout);
            
            /* Negotiate if the peer has started negotiating,
               otherwise don't. We don't want to speak telnet with
               non-telnet servers, like POP or SMTP. */
            if(tn->please_negotiate && !tn->already_negotiated) {
              negotiate(conn);
              tn->already_negotiated = 1;
            }
          }
          
          if(events.lNetworkEvents & FD_CLOSE)
          {
            keepon = FALSE;
          }
        }
        break;
    }
  }
#else
  FD_ZERO (&readfd);		/* clear it */
  FD_SET (sockfd, &readfd);
  FD_SET (0, &readfd);
Daniel Stenberg's avatar
Daniel Stenberg committed

  keepfd = readfd;
Daniel Stenberg's avatar
Daniel Stenberg committed

  while (keepon) {
    readfd = keepfd;		/* set this every lap in the loop */
Daniel Stenberg's avatar
Daniel Stenberg committed

    switch (select (sockfd + 1, &readfd, NULL, NULL, NULL)) {
    case -1:			/* error, stop reading */
      keepon = FALSE;
      continue;
    case 0:			/* timeout */
      break;
    default:			/* read! */
      if(FD_ISSET(0, &readfd)) { /* read from stdin */
        unsigned char outbuf[2];
        int out_count = 0;
        ssize_t bytes_written;
        char *buffer = buf;
        
        nread = read(0, buf, 255);

        while(nread--) {
          outbuf[0] = *buffer++;
          out_count = 1;
          if(outbuf[0] == IAC)
            outbuf[out_count++] = IAC;
      
          Curl_write(conn, conn->firstsocket, outbuf,
                     out_count, &bytes_written);
        }
      }
Daniel Stenberg's avatar
Daniel Stenberg committed

      if(FD_ISSET(sockfd, &readfd)) {
        /* This OUGHT to check the return code... */
        Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
Daniel Stenberg's avatar
Daniel Stenberg committed

        /* if we receive 0 or less here, the server closed the connection and
           we bail out from this! */
        if (nread <= 0) {
          keepon = FALSE;
          break;
        }
        telrcv(conn, (unsigned char *)buf, nread);

        /* Negotiate if the peer has started negotiating,
           otherwise don't. We don't want to speak telnet with
           non-telnet servers, like POP or SMTP. */
        if(tn->please_negotiate && !tn->already_negotiated) {
          tn->already_negotiated = 1;
  /* mark this as "no further transfer wanted" */
  return Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Daniel Stenberg's avatar
Daniel Stenberg committed
}

/*
 * local variables:
 * eval: (load-file "../curl-mode.el")
 * end:
 * vim600: fdm=marker
 * vim: et sw=2 ts=2 sts=2 tw=78