static CURLcode telnet_do(struct connectdata *conn, bool *done)
{
  CURLcode code;
  struct SessionHandle *data = conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
  HMODULE wsock2;
  WSOCK2_FUNC close_event_func;
  WSOCK2_FUNC create_event_func;
  WSOCK2_FUNC event_select_func;
  WSOCK2_FUNC enum_netevents_func;
  WSAEVENT event_handle;
  WSANETWORKEVENTS events;
  HANDLE stdin_handle;
  HANDLE objs[2];
  DWORD  obj_count;
  DWORD  wait_timeout;
  DWORD waitret;
  DWORD readfile_read;
  int err;
#else
  int interval_ms;
  struct pollfd pfd[2];
  int poll_cnt;
  curl_off_t total_dl = 0;
  curl_off_t total_ul = 0;
#endif
  ssize_t nread;
  struct timeval now;
  bool keepon = TRUE;
  char *buf = data->state.buffer;
  struct TELNET *tn;

  *done = TRUE; /* unconditionally */

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

  tn = (struct TELNET *)data->state.proto.telnet;

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

#ifdef USE_WINSOCK
  /*
  ** This functionality only works with WinSock >= 2.0.  So,
  ** make sure have it.
  */
  code = check_wsock2(data);
  if(code)
    return code;

  /* OK, so we have WinSock 2.0.  We need to dynamically */
  /* load ws2_32.dll and get the function pointers we need. */
  wsock2 = LoadLibrary("WS2_32.DLL");
  if(wsock2 == NULL) {
    failf(data,"failed to load WS2_32.DLL (%d)", ERRNO);
    return CURLE_FAILED_INIT;
  }

  /* Grab a pointer to WSACreateEvent */
  create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
  if(create_event_func == NULL) {
    failf(data,"failed to find WSACreateEvent function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSACloseEvent */
  close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
  if(close_event_func == NULL) {
    failf(data,"failed to find WSACloseEvent function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSAEventSelect */
  event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
  if(event_select_func == NULL) {
    failf(data,"failed to find WSAEventSelect function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSAEnumNetworkEvents */
  enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
  if(enum_netevents_func == NULL) {
    failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* 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 = (WSAEVENT)create_event_func();
  if(event_handle == WSA_INVALID_EVENT) {
    failf(data,"WSACreateEvent failed (%d)", SOCKERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* Tell winsock what events we want to listen to */
  if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) ==
     SOCKET_ERROR) {
    close_event_func(event_handle);
    FreeLibrary(wsock2);
    return CURLE_OK;
  }

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

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

  /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
     else use the old WaitForMultipleObjects() way */
  if(GetFileType(stdin_handle) == FILE_TYPE_PIPE ||
     data->set.is_fread_set) {
    /* Don't wait for stdin_handle, just wait for event_handle */
    obj_count = 1;
    /* Check stdin_handle per 100 milliseconds */
    wait_timeout = 100;
  }
  else {
    obj_count = 2;
    wait_timeout = 1000;
  }

  /* Keep on listening and act on events */
  while(keepon) {
    waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
    switch(waitret) {
    case WAIT_TIMEOUT:
    {
      for(;;) {
        if(obj_count == 1) {
          /* read from user-supplied method */
          code = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
          if(code == CURL_READFUNC_ABORT) {
            keepon = FALSE;
            code = CURLE_READ_ERROR;
            break;
          }

          if(code == CURL_READFUNC_PAUSE)
            break;

          if(code == 0)                        /* no bytes */
            break;

          readfile_read = code; /* fall thru with number of bytes read */
        }
        else {
          /* read from stdin */
          if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL,
                            &readfile_read, NULL)) {
            keepon = FALSE;
            code = CURLE_READ_ERROR;
            break;
          }

          if(!readfile_read)
            break;

          if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
                       &readfile_read, NULL)) {
            keepon = FALSE;
            code = CURLE_READ_ERROR;
            break;
          }
        }

        code = send_telnet_data(conn, buf, readfile_read);
        if(code) {
          keepon = FALSE;
          break;
        }
      }
    }
    break;

    case WAIT_OBJECT_0 + 1:
    {
      if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
                   &readfile_read, NULL)) {
        keepon = FALSE;
        code = CURLE_READ_ERROR;
        break;
      }

      code = send_telnet_data(conn, buf, readfile_read);
      if(code) {
        keepon = FALSE;
        break;
      }
    }
    break;

    case WAIT_OBJECT_0:

      if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
        if((err = SOCKERRNO) != EINPROGRESS) {
          infof(data,"WSAEnumNetworkEvents failed (%d)", err);
          keepon = FALSE;
          code = CURLE_READ_ERROR;
        }
        break;
      }
      if(events.lNetworkEvents & FD_READ) {
        /* read data from network */
        code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
        /* read would've blocked. Loop again */
        if(code == CURLE_AGAIN)
          break;
        /* returned not-zero, this an error */
        else if(code) {
          keepon = FALSE;
          break;
        }
        /* returned zero but actually received 0 or less here,
           the server closed the connection and we bail out */
        else if(nread <= 0) {
          keepon = FALSE;
          break;
        }

        code = telrcv(conn, (unsigned char *)buf, nread);
        if(code) {
          keepon = FALSE;
          break;
        }

        /* 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;

    }

    if(data->set.timeout) {
      now = Curl_tvnow();
      if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
        failf(data, "Time-out");
        code = CURLE_OPERATION_TIMEDOUT;
        keepon = FALSE;
      }
    }
  }

  /* We called WSACreateEvent, so call WSACloseEvent */
  if(!close_event_func(event_handle)) {
    infof(data,"WSACloseEvent failed (%d)", SOCKERRNO);
  }

  /* "Forget" pointers into the library we're about to free */
  create_event_func = NULL;
  close_event_func = NULL;
  event_select_func = NULL;
  enum_netevents_func = NULL;

  /* We called LoadLibrary, so call FreeLibrary */
  if(!FreeLibrary(wsock2))
    infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO);
#else
  pfd[0].fd = sockfd;
  pfd[0].events = POLLIN;

  if(conn->fread_func != (curl_read_callback)fread) {
    poll_cnt = 1;
    interval_ms = 100; /* poll user-supplied read function */
  }
  else {
    /* really using fread, so infile is a FILE* */
    pfd[1].fd = fileno((FILE *)conn->fread_in);
    pfd[1].events = POLLIN;
    poll_cnt = 2;
    interval_ms = 1 * 1000;
  }

  while(keepon) {
    switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
    case -1:                    /* error, stop reading */
      keepon = FALSE;
      continue;
    case 0:                     /* timeout */
      pfd[0].revents = 0;
      pfd[1].revents = 0;
      /* fall through */
    default:                    /* read! */
      if(pfd[0].revents & POLLIN) {
        /* read data from network */
        code = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
        /* read would've blocked. Loop again */
        if(code == CURLE_AGAIN)
          break;
        /* returned not-zero, this an error */
        else if(code) {
          keepon = FALSE;
          break;
        }
        /* returned zero but actually received 0 or less here,
           the server closed the connection and we bail out */
        else if(nread <= 0) {
          keepon = FALSE;
          break;
        }

        total_dl += nread;
        Curl_pgrsSetDownloadCounter(data, total_dl);
        code = telrcv(conn, (unsigned char *)buf, nread);
        if(code) {
          keepon = FALSE;
          break;
        }

        /* 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;
        }
      }

      nread = 0;
      if(poll_cnt == 2) {
        if(pfd[1].revents & POLLIN) { /* read from in file */
          nread = read(pfd[1].fd, buf, BUFSIZE - 1);
        }
      }
      else {
        /* read from user-supplied method */
        nread = (int)conn->fread_func(buf, 1, BUFSIZE - 1, conn->fread_in);
        if(nread == CURL_READFUNC_ABORT) {
          keepon = FALSE;
          break;
        }
        if(nread == CURL_READFUNC_PAUSE)
          break;
      }

      if(nread > 0) {
        code = send_telnet_data(conn, buf, nread);
        if(code) {
          keepon = FALSE;
          break;
        }
        total_ul += nread;
        Curl_pgrsSetUploadCounter(data, total_ul);
      }
      else if(nread < 0)
        keepon = FALSE;

      break;
    } /* poll switch statement */

    if(data->set.timeout) {
      now = Curl_tvnow();
      if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
        failf(data, "Time-out");
        code = CURLE_OPERATION_TIMEDOUT;
        keepon = FALSE;
      }
    }

    if(Curl_pgrsUpdate(conn)) {
      code = CURLE_ABORTED_BY_CALLBACK;
      break;
    }
  }
#endif
  /* mark this as "no further transfer wanted" */
  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);

  return code;
}
Beispiel #2
0
static CURLcode telnet_do(struct connectdata *conn, bool *done)
{
  CURLcode code;
  struct SessionHandle *data = conn->data;
  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef USE_WINSOCK
  HMODULE wsock2;
  WSOCK2_FUNC close_event_func;
  WSOCK2_FUNC create_event_func;
  WSOCK2_FUNC event_select_func;
  WSOCK2_FUNC enum_netevents_func;
  WSAEVENT event_handle;
  WSANETWORKEVENTS events;
  HANDLE stdin_handle;
  HANDLE objs[2];
  DWORD  obj_count;
  DWORD  wait_timeout;
  DWORD waitret;
  DWORD readfile_read;
#else
  int interval_ms;
  struct pollfd pfd[2];
#endif
  ssize_t nread;
  bool keepon = TRUE;
  char *buf = data->state.buffer;
  struct TELNET *tn;

  *done = TRUE; /* unconditionally */

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

  tn = (struct TELNET *)data->state.proto.telnet;

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

#ifdef USE_WINSOCK
  /*
  ** This functionality only works with WinSock >= 2.0.  So,
  ** make sure have it.
  */
  code = check_wsock2(data);
  if(code)
    return code;

  /* OK, so we have WinSock 2.0.  We need to dynamically */
  /* load ws2_32.dll and get the function pointers we need. */
  wsock2 = LoadLibrary("WS2_32.DLL");
  if(wsock2 == NULL) {
    failf(data,"failed to load WS2_32.DLL (%d)", ERRNO);
    return CURLE_FAILED_INIT;
  }

  /* Grab a pointer to WSACreateEvent */
  create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
  if(create_event_func == NULL) {
    failf(data,"failed to find WSACreateEvent function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSACloseEvent */
  close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
  if(close_event_func == NULL) {
    failf(data,"failed to find WSACloseEvent function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSAEventSelect */
  event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
  if(event_select_func == NULL) {
    failf(data,"failed to find WSAEventSelect function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* And WSAEnumNetworkEvents */
  enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
  if(enum_netevents_func == NULL) {
    failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
          ERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

  /* 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 = (WSAEVENT)create_event_func();
  if(event_handle == WSA_INVALID_EVENT) {
    failf(data,"WSACreateEvent failed (%d)", SOCKERRNO);
    FreeLibrary(wsock2);
    return CURLE_FAILED_INIT;
  }

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

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

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

  /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it,
     else use the old WaitForMultipleObjects() way */
  if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) {
    /* Don't wait for stdin_handle, just wait for event_handle */
    obj_count = 1;
    /* Check stdin_handle per 100 milliseconds */
    wait_timeout = 100;
  } else {
    obj_count = 2;
    wait_timeout = INFINITE;
  }

  /* Keep on listening and act on events */
  while(keepon) {
    waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
    switch(waitret) {
    case WAIT_TIMEOUT:
    {
      unsigned char outbuf[2];
      int out_count = 0;
      ssize_t bytes_written;
      char *buffer = buf;

      while(1) {
        if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) {
          keepon = FALSE;
          break;
        }
        nread = readfile_read;

        if(!nread)
          break;

        if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
                     &readfile_read, NULL)) {
          keepon = FALSE;
          break;
        }
        nread = readfile_read;

        while(nread--) {
          outbuf[0] = *buffer++;
          out_count = 1;
          if(outbuf[0] == CURL_IAC)
            outbuf[out_count++] = CURL_IAC;

          Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
                     out_count, &bytes_written);
        }
      }
    }
    break;

    case WAIT_OBJECT_0 + 1:
    {
      unsigned char outbuf[2];
      int out_count = 0;
      ssize_t bytes_written;
      char *buffer = buf;

      if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer),
                   &readfile_read, NULL)) {
        keepon = FALSE;
        break;
      }
      nread = readfile_read;

      while(nread--) {
        outbuf[0] = *buffer++;
        out_count = 1;
        if(outbuf[0] == CURL_IAC)
          outbuf[out_count++] = CURL_IAC;

        Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
                   out_count, &bytes_written);
      }
    }
    break;

    case WAIT_OBJECT_0:
      if(enum_netevents_func(sockfd, event_handle, &events)
         != SOCKET_ERROR) {
        if(events.lNetworkEvents & FD_READ) {
          /* This reallu OUGHT to check its return code. */
          (void)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;
    }
  }

  /* We called WSACreateEvent, so call WSACloseEvent */
  if(close_event_func(event_handle) == FALSE) {
    infof(data,"WSACloseEvent failed (%d)", SOCKERRNO);
  }

  /* "Forget" pointers into the library we're about to free */
  create_event_func = NULL;
  close_event_func = NULL;
  event_select_func = NULL;
  enum_netevents_func = NULL;

  /* We called LoadLibrary, so call FreeLibrary */
  if(!FreeLibrary(wsock2))
    infof(data,"FreeLibrary(wsock2) failed (%d)", ERRNO);
#else
  pfd[0].fd = sockfd;
  pfd[0].events = POLLIN;
  pfd[1].fd = 0;
  pfd[1].events = POLLIN;
  interval_ms = 1 * 1000;

  while(keepon) {
    switch (Curl_poll(pfd, 2, interval_ms)) {
    case -1:                    /* error, stop reading */
      keepon = FALSE;
      continue;
    case 0:                     /* timeout */
      break;
    default:                    /* read! */
      if(pfd[1].revents & POLLIN) { /* 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] == CURL_IAC)
            outbuf[out_count++] = CURL_IAC;

          Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
                     out_count, &bytes_written);
        }
      }

      if(pfd[0].revents & POLLIN) {
        /* This OUGHT to check the return code... */
        (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);

        /* 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) {
          negotiate(conn);
          tn->already_negotiated = 1;
        }
      }
    }
    if(data->set.timeout) {
      struct timeval now;           /* current time */
      now = Curl_tvnow();
      if(Curl_tvdiff(now, conn->created) >= data->set.timeout) {
        failf(data, "Time-out");
        code = CURLE_OPERATION_TIMEDOUT;
        keepon = FALSE;
      }
    }
  }
#endif
  /* mark this as "no further transfer wanted" */
  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);

  return code;
}
Beispiel #3
0
CURLcode Curl_telnet(struct connectdata *conn)
{
    CURLcode code;
    struct SessionHandle *data = conn->data;
    curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
#ifdef WIN32
    HMODULE wsock2;
    WSOCK2_FUNC close_event_func;
    WSOCK2_FUNC create_event_func;
    WSOCK2_FUNC event_select_func;
    WSOCK2_FUNC enum_netevents_func;
    WSAEVENT event_handle;
    WSANETWORKEVENTS events;
    HANDLE stdin_handle;
    HANDLE objs[2];
    DWORD waitret;
    DWORD readfile_read;
#else
    fd_set readfd;
    fd_set keepfd;
#endif
    ssize_t nread;
    bool keepon = TRUE;
    char *buf = data->state.buffer;
    struct TELNET *tn;

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

    tn = (struct TELNET *)conn->proto.telnet;

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

#ifdef WIN32
    /*
    ** This functionality only works with WinSock >= 2.0.  So,
    ** make sure have it.
    */
    code = check_wsock2(data);
    if (code)
        return code;

    /* OK, so we have WinSock 2.0.  We need to dynamically */
    /* load ws2_32.dll and get the function pointers we need. */
    wsock2 = LoadLibrary("WS2_32.DLL");
    if (wsock2 == NULL)
    {
        failf(data,"failed to load WS2_32.DLL (%d)",GetLastError());
        return CURLE_FAILED_INIT;
    }

    /* Grab a pointer to WSACreateEvent */
    create_event_func = GetProcAddress(wsock2,"WSACreateEvent");
    if (create_event_func == NULL)
    {
        failf(data,"failed to find WSACreateEvent function (%d)",
              GetLastError());
        FreeLibrary(wsock2);
        return CURLE_FAILED_INIT;
    }

    /* And WSACloseEvent */
    close_event_func = GetProcAddress(wsock2,"WSACloseEvent");
    if (create_event_func == NULL)
    {
        failf(data,"failed to find WSACloseEvent function (%d)",
              GetLastError());
        FreeLibrary(wsock2);
        return CURLE_FAILED_INIT;
    }

    /* And WSAEventSelect */
    event_select_func = GetProcAddress(wsock2,"WSAEventSelect");
    if (event_select_func == NULL)
    {
        failf(data,"failed to find WSAEventSelect function (%d)",
              GetLastError());
        FreeLibrary(wsock2);
        return CURLE_FAILED_INIT;
    }

    /* And WSAEnumNetworkEvents */
    enum_netevents_func = GetProcAddress(wsock2,"WSAEnumNetworkEvents");
    if (enum_netevents_func == NULL)
    {
        failf(data,"failed to find WSAEnumNetworkEvents function (%d)",
              GetLastError());
        FreeLibrary(wsock2);
        return CURLE_FAILED_INIT;
    }

    /* 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 = (WSAEVENT)create_event_func();
    if (event_handle == WSA_INVALID_EVENT)
    {
        failf(data,"WSACreateEvent failed (%d)",WSAGetLastError());
        FreeLibrary(wsock2);
        return CURLE_FAILED_INIT;
    }

    /* 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(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR)
    {
        close_event_func(event_handle);
        FreeLibrary(wsock2);
        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, sizeof(data->state.buffer),
                         &readfile_read, NULL))
            {
                keepon = FALSE;
                break;
            }
            nread = readfile_read;

            while(nread--)
            {
                outbuf[0] = *buffer++;
                out_count = 1;
                if(outbuf[0] == CURL_IAC)
                    outbuf[out_count++] = CURL_IAC;

                Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
                           out_count, &bytes_written);
            }
        }
        break;

        case 1:
            if(enum_netevents_func(sockfd, event_handle, &events)
                    != SOCKET_ERROR)
            {
                if(events.lNetworkEvents & FD_READ)
                {
                    /* This reallu OUGHT to check its return code. */
                    (void)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;
        }
    }

    /* We called WSACreateEvent, so call WSACloseEvent */
    if (close_event_func(event_handle) == FALSE)
    {
        infof(data,"WSACloseEvent failed (%d)",WSAGetLastError());
    }

    /* "Forget" pointers into the library we're about to free */
    create_event_func = NULL;
    close_event_func = NULL;
    event_select_func = NULL;
    enum_netevents_func = NULL;

    /* We called LoadLibrary, so call FreeLibrary */
    if (!FreeLibrary(wsock2))
        infof(data,"FreeLibrary(wsock2) failed (%d)",GetLastError());
#else
    FD_ZERO (&readfd);		/* clear it */
    FD_SET (sockfd, &readfd);
    FD_SET (0, &readfd);

    keepfd = readfd;

    while (keepon)
    {
        struct timeval interval;

        readfd = keepfd;		/* set this every lap in the loop */
        interval.tv_sec = 1;
        interval.tv_usec = 0;

        switch (select (sockfd + 1, &readfd, NULL, NULL, &interval))
        {
        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] == CURL_IAC)
                        outbuf[out_count++] = CURL_IAC;

                    Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf,
                               out_count, &bytes_written);
                }
            }

            if(FD_ISSET(sockfd, &readfd))
            {
                /* This OUGHT to check the return code... */
                (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);

                /* 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)
                {
                    negotiate(conn);
                    tn->already_negotiated = 1;
                }
            }
        }
        if(data->set.timeout)
        {
            struct timeval now;           /* current time */
            now = Curl_tvnow();
            if(Curl_tvdiff(now, conn->created)/1000 >= data->set.timeout)
            {
                failf(data, "Time-out");
                code = CURLE_OPERATION_TIMEOUTED;
                keepon = FALSE;
            }
        }
    }
#endif
    /* mark this as "no further transfer wanted" */
    Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);

    return code;
}