Commit 8ce852a2 authored by Marc Hoersken's avatar Marc Hoersken
Browse files

sockfilt.c: properly handle disk files, pipes and character input

parent fe1c0176
Loading
Loading
Loading
Loading
+79 −14
Original line number Diff line number Diff line
@@ -515,24 +515,74 @@ static void lograw(unsigned char *buffer, ssize_t len)
 */
static DWORD WINAPI select_ws_stdin_wait_thread(LPVOID lpParameter)
{
  HANDLE handle, handles[2];
  INPUT_RECORD inputrecord;
  HANDLE handle;
  DWORD length;
  LARGE_INTEGER size, pos;
  DWORD type, length;

  handle = (HANDLE) lpParameter;
  handle = GetStdHandle(STD_INPUT_HANDLE);
  handles[0] = (HANDLE) lpParameter;
  handles[1] = handle;
  type = GetFileType(handle);

  switch(type) {
    case FILE_TYPE_DISK:
      while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
            == WAIT_OBJECT_0 + 1) {
        size.QuadPart = 0;
        if(GetFileSizeEx(handle, &size)) {
          pos.QuadPart = 0;
          if(SetFilePointerEx(handle, pos, &pos, FILE_CURRENT)) {
            if(size.QuadPart == pos.QuadPart)
              SleepEx(100, FALSE);
            else
              break;
          }
          else
            break;
        }
        else
          break;
      }
      break;

    case FILE_TYPE_CHAR:
      while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
            == WAIT_OBJECT_0 + 1) {
        if(GetConsoleMode(handle, &length)) {
    while(WaitForSingleObjectEx(handle, INFINITE, FALSE) == WAIT_OBJECT_0) {
          length = 0;
          if(PeekConsoleInput(handle, &inputrecord, 1, &length)) {
            if(length == 1 && inputrecord.EventType != KEY_EVENT)
              ReadConsoleInput(handle, &inputrecord, 1, &length);
            else
              break;
          }
          else
            break;
        }
        else
          break;
      }
      break;

    case FILE_TYPE_PIPE:
      while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
            == WAIT_OBJECT_0 + 1) {
        if(!PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) {
          if(GetLastError() == ERROR_BROKEN_PIPE)
            SleepEx(100, FALSE);
          else
            break;
        }
        else
    ReadFile(handle, NULL, 0, &length, NULL);
          break;
      }
      break;

    default:
      WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE);
      break;
  }

  return 0;
}
@@ -546,6 +596,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
  curl_socket_t sock, *fdarr, *wsasocks;
  long networkevents;
  int error, fds;
  HANDLE threadevent = NULL, threadhandle = NULL;
  DWORD nfd = 0, wsa = 0;
  int ret = 0;

@@ -613,10 +664,11 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
    if(networkevents) {
      fdarr[nfd] = curlx_sitosk(fds);
      if(fds == fileno(stdin)) {
        handles[nfd] = CreateThread(NULL, 0,
        threadevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        threadhandle = CreateThread(NULL, 0,
                                    &select_ws_stdin_wait_thread,
                                    GetStdHandle(STD_INPUT_HANDLE),
                                    0, NULL);
                                    threadevent, 0, NULL);
        handles[nfd] = threadhandle;
      }
      else if(fds == fileno(stdout)) {
        handles[nfd] = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -655,6 +707,11 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
  /* wait for one of the internal handles to trigger */
  wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, milliseconds, FALSE);

  /* signal the event handle for the waiting thread */
  if(threadevent) {
    SetEvent(threadevent);
  }

  /* loop over the internal handles returned in the descriptors */
  for(idx = 0; idx < nfd; idx++) {
    handle = handles[idx];
@@ -721,6 +778,14 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
    WSACloseEvent(wsaevents[idx]);
  }

  if(threadhandle) {
    WaitForSingleObject(threadhandle, INFINITE);
    CloseHandle(threadhandle);
  }
  if(threadevent) {
    CloseHandle(threadevent);
  }

  free(wsaevents);
  free(wsasocks);
  free(handles);