bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] implement full-blown select(2) for winsock


From: Bruno Haible
Subject: Re: [PATCH v2] implement full-blown select(2) for winsock
Date: Mon, 29 Sep 2008 19:49:00 +0200
User-agent: KMail/1.5.4

> handle console handles (e.g. stdin)

For reference, here is the code that is in use in clisp to detect whether
reading from a handle would hang or return immediately. The deal with
ENABLE_LINE_INPUT is that PeekConsoleInput will say "yes there is something
is available" as soon as the user has started typing a line, but ReadFile
will hang until the user presses Return.


/* Determines whether ReadFile() on a file/pipe/console handle will hang.
   Returns 0 for yes, 1 for no (or 2 for known EOF or 3 for available byte),
   -1 for unknown. */
int fd_read_wont_hang_p (HANDLE fd)
{
  /* This is pretty complex. To test this, create a file "listen.lisp"
   containing the code
     (tagbody 1 (prin1 (listen *terminal-io*)) (sys::%sleep 0 500) (go 1))
   and execute "lisp.exe -q -i listen.lisp" with redirected standard input. */
  switch (GetFileType(fd)) {
    case FILE_TYPE_CHAR:
      {
        DWORD nevents;
        if (GetNumberOfConsoleInputEvents(fd,&nevents)) { /* It's a console. */
          if (nevents==0)
            return 0;
          INPUT_RECORD* events =
            (INPUT_RECORD*)alloca(nevents*sizeof(INPUT_RECORD));
          DWORD nevents_read;
          DWORD mode;
          if (!PeekConsoleInput(fd,events,nevents,&nevents_read)) {
            OS_error();
          }
          if (nevents_read==0)
            return 0;
          if (!GetConsoleMode(fd,&mode)) {
            OS_error();
          }
          if (mode & ENABLE_LINE_INPUT) {
            /* Look out for a Key-Down event corresponding to CR/LF. */
            DWORD i;
            for (i = 0; i < nevents_read; i++) {
              if (events[i].EventType == KEY_EVENT
                  && events[i].Event.KeyEvent.bKeyDown
                  && events[i].Event.KeyEvent.uAsciiChar == CR)
                /* probably a byte available (except if it is Ctrl-Z) */
                return -1;
            }
          } else {              /* Look out for any Key-Down event. */
            DWORD i;
            for (i = 0; i < nevents_read; i++) {
              if (events[i].EventType == KEY_EVENT
                  && events[i].Event.KeyEvent.bKeyDown
                  && events[i].Event.KeyEvent.uAsciiChar != 0)
                /* probably a byte available (except if it is Ctrl-Z) */
                return -1;
            }
          }
          return 0;
        } else if (!(GetLastError()==ERROR_INVALID_HANDLE)) {
          OS_error();
        }
      }
      /* Not a console. */
      switch (WaitForSingleObject(fd,0)) {
        case WAIT_OBJECT_0:     /* a byte is available, or EOF */
          return 1;
        case WAIT_TIMEOUT:
          return 0;
        default:
          OS_error();
      }
    case FILE_TYPE_DISK:
      return 1;
    case FILE_TYPE_PIPE:
      {
        DWORD nbytes;
        if (PeekNamedPipe(fd,NULL,0,NULL,&nbytes,NULL)) { /* input pipe */
          if (nbytes > 0)
            return 3;
          else
            return 0;
        } else if (GetLastError()==ERROR_BROKEN_PIPE) { /* EOF reached */
          return 2;
        } else if (GetLastError()==ERROR_ACCESS_DENIED) { /* output pipe */
          /* => fake EOF. */
          return 2;
        } else {
          OS_error();
        }
      }
    default:                   /* It's a file (or something unknown). */
      return -1;
  }
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]