Example #1
0
static DWORD WINAPI select_ws_wait_thread(LPVOID lpParameter)
{
  struct select_ws_wait_data *data;
  HANDLE handle, handles[2];
  INPUT_RECORD inputrecord;
  LARGE_INTEGER size, pos;
  DWORD type, length;

  /* retrieve handles from internal structure */
  data = (struct select_ws_wait_data *) lpParameter;
  if(data) {
    handle = data->handle;
    handles[0] = data->event;
    handles[1] = handle;
    free(data);
  }
  else
    return (DWORD)-1;

  /* retrieve the type of file to wait on */
  type = GetFileType(handle);
  switch(type) {
    case FILE_TYPE_DISK:
       /* The handle represents a file on disk, this means:
        * - WaitForMultipleObjectsEx will always be signalled for it.
        * - comparison of current position in file and total size of
        *   the file can be used to check if we reached the end yet.
        *
        * Approach: Loop till either the internal event is signalled
        *           or if the end of the file has already been reached.
        */
      while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE)
            == WAIT_TIMEOUT) {
        /* get total size of file */
        length = 0;
        size.QuadPart = 0;
        size.LowPart = GetFileSize(handle, &length);
        if((size.LowPart != INVALID_FILE_SIZE) ||
           (GetLastError() == NO_ERROR)) {
          size.HighPart = length;
          /* get the current position within the file */
          pos.QuadPart = 0;
          pos.LowPart = SetFilePointer(handle, 0, &pos.HighPart,
                                       FILE_CURRENT);
          if((pos.LowPart != INVALID_SET_FILE_POINTER) ||
             (GetLastError() == NO_ERROR)) {
            /* compare position with size, abort if not equal */
            if(size.QuadPart == pos.QuadPart) {
              /* sleep and continue waiting */
              SleepEx(0, FALSE);
              continue;
            }
          }
        }
        /* there is some data available, stop waiting */
        break;
      }
      break;

    case FILE_TYPE_CHAR:
       /* The handle represents a character input, this means:
        * - WaitForMultipleObjectsEx will be signalled on any kind of input,
        *   including mouse and window size events we do not care about.
        *
        * Approach: Loop till either the internal event is signalled
        *           or we get signalled for an actual key-event.
        */
      while(WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE)
            == WAIT_OBJECT_0 + 1) {
        /* check if this is an actual console handle */
        length = 0;
        if(GetConsoleMode(handle, &length)) {
          /* retrieve an event from the console buffer */
          length = 0;
          if(PeekConsoleInput(handle, &inputrecord, 1, &length)) {
            /* check if the event is not an actual key-event */
            if(length == 1 && inputrecord.EventType != KEY_EVENT) {
              /* purge the non-key-event and continue waiting */
              ReadConsoleInput(handle, &inputrecord, 1, &length);
              continue;
            }
          }
        }
        /* there is some data available, stop waiting */
        break;
      }
      break;

    case FILE_TYPE_PIPE:
       /* The handle represents an anonymous or named pipe, this means:
        * - WaitForMultipleObjectsEx will always be signalled for it.
        * - peek into the pipe and retrieve the amount of data available.
        *
        * Approach: Loop till either the internal event is signalled
        *           or there is data in the pipe available for reading.
        */
      while(WaitForMultipleObjectsEx(1, handles, FALSE, 0, FALSE)
            == WAIT_TIMEOUT) {
        /* peek into the pipe and retrieve the amount of data available */
        length = 0;
        if(PeekNamedPipe(handle, NULL, 0, NULL, &length, NULL)) {
          /* if there is no data available, sleep and continue waiting */
          if(length == 0) {
            SleepEx(0, FALSE);
            continue;
          }
        }
        else {
          /* if the pipe has been closed, sleep and continue waiting */
          if(GetLastError() == ERROR_BROKEN_PIPE) {
            SleepEx(0, FALSE);
            continue;
          }
        }
        /* there is some data available, stop waiting */
        break;
      }
      break;

    default:
      /* The handle has an unknown type, try to wait on it */
      WaitForMultipleObjectsEx(2, handles, FALSE, INFINITE, FALSE);
      break;
  }

  return 0;
}
Example #2
0
static int
WaitForRead(
    ConsoleInfo *infoPtr,	/* Console state. */
    int blocking)		/* Indicates whether call should be blocking
				 * or not. */
{
    DWORD timeout, count;
    HANDLE *handle = infoPtr->handle;
    INPUT_RECORD input;

    while (1) {
	/*
	 * Synchronize with the reader thread.
	 */

	timeout = blocking ? INFINITE : 0;
	if (WaitForSingleObject(infoPtr->readable, timeout) == WAIT_TIMEOUT) {
	    /*
	     * The reader thread is blocked waiting for data and the channel
	     * is in non-blocking mode.
	     */

	    errno = EAGAIN;
	    return -1;
	}

	/*
	 * At this point, the two threads are synchronized, so it is safe to
	 * access shared state.
	 */

	/*
	 * If the console has hit EOF, it is always readable.
	 */

	if (infoPtr->readFlags & CONSOLE_EOF) {
	    return 1;
	}

	if (PeekConsoleInput(handle, &input, 1, &count) == FALSE) {
	    /*
	     * Check to see if the peek failed because of EOF.
	     */

	    TclWinConvertError(GetLastError());

	    if (errno == EOF) {
		infoPtr->readFlags |= CONSOLE_EOF;
		return 1;
	    }

	    /*
	     * Ignore errors if there is data in the buffer.
	     */

	    if (infoPtr->readFlags & CONSOLE_BUFFERED) {
		return 0;
	    } else {
		return -1;
	    }
	}

	/*
	 * If there is data in the buffer, the console must be readable (since
	 * it is a line-oriented device).
	 */

	if (infoPtr->readFlags & CONSOLE_BUFFERED) {
	    return 1;
	}

	/*
	 * There wasn't any data available, so reset the thread and try again.
	 */

	ResetEvent(infoPtr->readable);
	SetEvent(infoPtr->startReader);
    }
}
static int
win32_compute_revents (HANDLE h, int *p_sought)
{
  int i, ret, happened;
  INPUT_RECORD *irbuffer;
  DWORD avail, nbuffer;
  BOOL bRet;
  IO_STATUS_BLOCK iosb;
  FILE_PIPE_LOCAL_INFORMATION fpli;
  static PNtQueryInformationFile NtQueryInformationFile;
  static BOOL once_only;

  switch (GetFileType (h))
    {
    case FILE_TYPE_PIPE:
      if (!once_only)
	{
	  NtQueryInformationFile = (PNtQueryInformationFile)
	    GetProcAddress (GetModuleHandle ("ntdll.dll"),
			    "NtQueryInformationFile");
	  once_only = TRUE;
	}

      happened = 0;
      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
	{
	  if (avail)
	    happened |= *p_sought & (POLLIN | POLLRDNORM);
	}
      else if (GetLastError () == ERROR_BROKEN_PIPE)
	happened |= POLLHUP;

      else
	{
	  /* It was the write-end of the pipe.  Check if it is writable.
	     If NtQueryInformationFile fails, optimistically assume the pipe is
	     writable.  This could happen on Win9x, where NtQueryInformationFile
	     is not available, or if we inherit a pipe that doesn't permit
	     FILE_READ_ATTRIBUTES access on the write end (I think this should
	     not happen since WinXP SP2; WINE seems fine too).  Otherwise,
	     ensure that enough space is available for atomic writes.  */
	  memset (&iosb, 0, sizeof (iosb));
	  memset (&fpli, 0, sizeof (fpli));

	  if (!NtQueryInformationFile
	      || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
					 FilePipeLocalInformation)
	      || fpli.WriteQuotaAvailable >= PIPE_BUF
	      || (fpli.OutboundQuota < PIPE_BUF &&
		  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
	    happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
	}
      return happened;

    case FILE_TYPE_CHAR:
      ret = WaitForSingleObject (h, 0);
      if (!IsConsoleHandle (h))
	return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;

      nbuffer = avail = 0;
      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
      if (bRet)
	{
	  /* Input buffer.  */
	  *p_sought &= POLLIN | POLLRDNORM;
	  if (nbuffer == 0)
	    return POLLHUP;
	  if (!*p_sought)
	    return 0;

	  irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
	  bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
	  if (!bRet || avail == 0)
	    return POLLHUP;

	  for (i = 0; i < avail; i++)
	    if (irbuffer[i].EventType == KEY_EVENT)
	      return *p_sought;
	  return 0;
	}
      else
	{
	  /* Screen buffer.  */
	  *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
	  return *p_sought;
	}

    default:
      ret = WaitForSingleObject (h, 0);
      if (ret == WAIT_OBJECT_0)
	return *p_sought & ~(POLLPRI | POLLRDBAND);

      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
    }
}
Example #4
0
File: select.c Project: sqs/gnutls
static int
win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
                   struct bitset *xbits)
{
  BOOL read, write, except;
  int i, ret;
  INPUT_RECORD *irbuffer;
  DWORD avail, nbuffer;
  BOOL bRet;
  IO_STATUS_BLOCK iosb;
  FILE_PIPE_LOCAL_INFORMATION fpli;
  static PNtQueryInformationFile NtQueryInformationFile;
  static BOOL once_only;

  read = write = except = FALSE;
  switch (GetFileType (h))
    {
    case FILE_TYPE_DISK:
      read = TRUE;
      write = TRUE;
      break;

    case FILE_TYPE_PIPE:
      if (!once_only)
        {
          NtQueryInformationFile = (PNtQueryInformationFile)
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
                            "NtQueryInformationFile");
          once_only = TRUE;
        }

      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
        {
          if (avail)
            read = TRUE;
        }
      else if (GetLastError () == ERROR_BROKEN_PIPE)
        ;

      else
        {
          /* It was the write-end of the pipe.  Check if it is writable.
             If NtQueryInformationFile fails, optimistically assume the pipe is
             writable.  This could happen on Win9x, where NtQueryInformationFile
             is not available, or if we inherit a pipe that doesn't permit
             FILE_READ_ATTRIBUTES access on the write end (I think this should
             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
             ensure that enough space is available for atomic writes.  */
          memset (&iosb, 0, sizeof (iosb));
          memset (&fpli, 0, sizeof (fpli));

          if (!NtQueryInformationFile
              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
                                         FilePipeLocalInformation)
              || fpli.WriteQuotaAvailable >= PIPE_BUF
              || (fpli.OutboundQuota < PIPE_BUF &&
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
            write = TRUE;
        }
      break;

    case FILE_TYPE_CHAR:
      write = TRUE;
      if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
        break;

      ret = WaitForSingleObject (h, 0);
      if (ret == WAIT_OBJECT_0)
        {
          if (!IsConsoleHandle (h))
            {
              read = TRUE;
              break;
            }

          nbuffer = avail = 0;
          bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);

          /* Screen buffers handles are filtered earlier.  */
          assert (bRet);
          if (nbuffer == 0)
            {
              except = TRUE;
              break;
            }

          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
          if (!bRet || avail == 0)
            {
              except = TRUE;
              break;
            }

          for (i = 0; i < avail; i++)
            if (irbuffer[i].EventType == KEY_EVENT)
              read = TRUE;
        }
      break;

    default:
      ret = WaitForSingleObject (h, 0);
      write = TRUE;
      if (ret == WAIT_OBJECT_0)
        read = TRUE;

      break;
    }

  ret = 0;
  if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  return ret;
}
Example #5
0
static int hb_gt_std_ReadKey( PHB_GT pGT, int iEventMask )
{
   PHB_GTSTD pGTSTD;
   int ch = 0;

   HB_TRACE( HB_TR_DEBUG, ( "hb_gt_std_ReadKey(%p,%d)", pGT, iEventMask ) );

   HB_SYMBOL_UNUSED( iEventMask );

   pGTSTD = HB_GTSTD_GET( pGT );

#if defined( HB_HAS_TERMIOS )
   {
      struct timeval tv;
      fd_set rfds;
      tv.tv_sec = 0;
      tv.tv_usec = 0;
      FD_ZERO( &rfds );
      FD_SET( pGTSTD->hStdin, &rfds );
      if( select( pGTSTD->hStdin + 1, &rfds, NULL, NULL, &tv ) > 0 )
      {
         HB_BYTE bChar;
         if( hb_fsRead( pGTSTD->hStdin, &bChar, 1 ) == 1 )
            ch = bChar;
      }
   }
#elif defined( _MSC_VER ) && ! defined( HB_OS_WIN_CE )
   if( pGTSTD->fStdinConsole )
   {
      if( _kbhit() )
      {
         ch = _getch();
         if( ( ch == 0 || ch == 224 ) && _kbhit() )
         {
            /* It was a function key lead-in code, so read the actual
               function key and then offset it by 256 */
            ch = _getch() + 256;
         }
         ch = hb_gt_dos_keyCodeTranslate( ch );
      }
   }
   else if( ! _eof( ( int ) pGTSTD->hStdin ) )
   {
      HB_BYTE bChar;
      if( _read( ( int ) pGTSTD->hStdin, &bChar, 1 ) == 1 )
         ch = bChar;
   }
#elif defined( HB_OS_WIN )
   if( ! pGTSTD->fStdinConsole )
   {
      HB_BYTE bChar;
      if( hb_fsRead( pGTSTD->hStdin, &bChar, 1 ) == 1 )
         ch = bChar;
   }
   else if( WaitForSingleObject( ( HANDLE ) hb_fsGetOsHandle( pGTSTD->hStdin ), 0 ) == WAIT_OBJECT_0 )
   {
#if defined( HB_OS_WIN_CE )
      HB_BYTE bChar;
      if( hb_fsRead( pGTSTD->hStdin, &bChar, 1 ) == 1 )
         ch = bChar;
#else
      INPUT_RECORD  ir;
      DWORD         dwEvents;
      while( PeekConsoleInput( ( HANDLE ) hb_fsGetOsHandle( pGTSTD->hStdin ), &ir, 1, &dwEvents ) && dwEvents == 1 )
      {
         if( ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown )
         {
            HB_BYTE bChar;
            if( hb_fsRead( pGTSTD->hStdin, &bChar, 1 ) == 1 )
               ch = bChar;
         }
         else /* Remove from the input queue */
            ReadConsoleInput( ( HANDLE ) hb_fsGetOsHandle( pGTSTD->hStdin ), &ir, 1, &dwEvents );
      }
#endif
   }
#elif defined( __WATCOMC__ )
   if( pGTSTD->fStdinConsole )
   {
      if( kbhit() )
      {
         ch = getch();
         if( ( ch == 0 || ch == 224 ) && kbhit() )
         {
            /* It was a function key lead-in code, so read the actual
               function key and then offset it by 256 */
            ch = getch() + 256;
         }
         ch = hb_gt_dos_keyCodeTranslate( ch );
      }
   }
   else if( ! eof( pGTSTD->hStdin ) )
   {
      HB_BYTE bChar;
      if( read( pGTSTD->hStdin, &bChar, 1 ) == 1 )
         ch = bChar;
   }
#else
   {
      if( ! pGTSTD->fStdinConsole )
      {
         HB_BYTE bChar;
         if( hb_fsRead( pGTSTD->hStdin, &bChar, 1 ) == 1 )
            ch = bChar;
      }
      else
      {
         int iTODO; /* TODO: */
      }
   }
#endif

   if( ch )
   {
      int u = HB_GTSELF_KEYTRANS( pGT, ch );
      if( u )
         ch = HB_INKEY_NEW_UNICODE( u );
   }

   return ch;
}
Example #6
0
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  (void) nc;

  switch (ev) {
    case MG_EV_CONNECT: {
      int status = *((int *) ev_data);
      if (status != 0) {
        printf("-- Connection error: %d\n", status);
      }
      break;
    }
    case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
      struct http_message *hm = (struct http_message *) ev_data;
      if (hm->resp_code == 101) {
        printf("-- Connected\n");
        s_is_connected = 1;
      } else {
        printf("-- Connection failed! HTTP code %d\n", hm->resp_code);
        /* Connection will be closed after this. */
      }
      break;
    }
    case MG_EV_POLL: {
      char msg[500];
      int n = 0;
#ifdef _WIN32 /* Windows console input is special. */
      INPUT_RECORD inp[100];
      HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
      DWORD i, num;
      if (!PeekConsoleInput(h, inp, sizeof(inp) / sizeof(*inp), &num)) break;
      for (i = 0; i < num; i++) {
        if (inp[i].EventType == KEY_EVENT &&
            inp[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN) {
          break;
        }
      }
      if (i == num) break;
      if (!ReadConsole(h, msg, sizeof(msg), &num, NULL)) break;
      /* Un-unicode. This is totally not the right way to do it. */
      for (i = 0; i < num * 2; i += 2) msg[i / 2] = msg[i];
      n = (int) num;
#else /* For everybody else, we just read() stdin. */
      fd_set read_set, write_set, err_set;
      struct timeval timeout = {0, 0};
      FD_ZERO(&read_set);
      FD_ZERO(&write_set);
      FD_ZERO(&err_set);
      FD_SET(0 /* stdin */, &read_set);
      if (select(1, &read_set, &write_set, &err_set, &timeout) == 1) {
        n = read(0, msg, sizeof(msg));
      }
#endif
      if (n <= 0) break;
      while (msg[n - 1] == '\r' || msg[n - 1] == '\n') n--;
      mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg, n);
      break;
    }
    case MG_EV_WEBSOCKET_FRAME: {
      struct websocket_message *wm = (struct websocket_message *) ev_data;
      printf("%.*s\n", (int) wm->size, wm->data);
      break;
    }
    case MG_EV_CLOSE: {
      if (s_is_connected) printf("-- Disconnected\n");
      s_done = 1;
      break;
    }
  }
}
Example #7
0
static int _process_mouse_event(void)
{
    static const DWORD button_mask[] = {1, 4, 2};
    short action, shift_flags = 0;
    int i;

    save_press = 0;
    SP->key_code = TRUE;

    memset(&pdc_mouse_status, 0, sizeof(MOUSE_STATUS));

    /* Handle scroll wheel */

    if (MEV.dwEventFlags == 4)
    {
        pdc_mouse_status.changes = (MEV.dwButtonState & 0xFF000000) ?
            PDC_MOUSE_WHEEL_DOWN : PDC_MOUSE_WHEEL_UP;

        pdc_mouse_status.x = -1;
        pdc_mouse_status.y = -1;

        memset(&old_mouse_status, 0, sizeof(old_mouse_status));

        return KEY_MOUSE;
    }

    action = (MEV.dwEventFlags == 2) ? BUTTON_DOUBLE_CLICKED :
            ((MEV.dwEventFlags == 1) ? BUTTON_MOVED : BUTTON_PRESSED);

    for (i = 0; i < 3; i++)
        pdc_mouse_status.button[i] =
            (MEV.dwButtonState & button_mask[i]) ? action : 0;

    if (action == BUTTON_PRESSED && MEV.dwButtonState & 7 && SP->mouse_wait)
    {
        /* Check for a click -- a PRESS followed immediately by a release */

        if (!event_count)
        {
            napms(SP->mouse_wait);

            GetNumberOfConsoleInputEvents(pdc_con_in, &event_count);
        }

        if (event_count)
        {
            INPUT_RECORD ip;
            DWORD count;
            bool have_click = FALSE;

            PeekConsoleInput(pdc_con_in, &ip, 1, &count);

            for (i = 0; i < 3; i++)
            {
                if (pdc_mouse_status.button[i] == BUTTON_PRESSED &&
                    !(ip.Event.MouseEvent.dwButtonState & button_mask[i]))
                {
                    pdc_mouse_status.button[i] = BUTTON_CLICKED;
                    have_click = TRUE;
                }
            }

            /* If a click was found, throw out the event */

            if (have_click)
                ReadConsoleInput(pdc_con_in, &ip, 1, &count);
        }
    }

    pdc_mouse_status.x = MEV.dwMousePosition.X;
    pdc_mouse_status.y = MEV.dwMousePosition.Y;

    pdc_mouse_status.changes = 0;

    for (i = 0; i < 3; i++)
    {
        if (old_mouse_status.button[i] != pdc_mouse_status.button[i])
            pdc_mouse_status.changes |= (1 << i);

        if (pdc_mouse_status.button[i] == BUTTON_MOVED)
        {
            /* Discard non-moved "moves" */

            if (pdc_mouse_status.x == old_mouse_status.x &&
                pdc_mouse_status.y == old_mouse_status.y)
                return -1;

            /* Motion events always flag the button as changed */

            pdc_mouse_status.changes |= (1 << i);
            pdc_mouse_status.changes |= PDC_MOUSE_MOVED;
            break;
        }
    }

    old_mouse_status = pdc_mouse_status;

    /* Treat click events as release events for comparison purposes */

    for (i = 0; i < 3; i++)
    {
        if (old_mouse_status.button[i] == BUTTON_CLICKED ||
            old_mouse_status.button[i] == BUTTON_DOUBLE_CLICKED)
            old_mouse_status.button[i] = BUTTON_RELEASED;
    }

    /* Check for SHIFT/CONTROL/ALT */

    if (MEV.dwControlKeyState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED))
        shift_flags |= BUTTON_ALT;

    if (MEV.dwControlKeyState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED))
        shift_flags |= BUTTON_CONTROL;

    if (MEV.dwControlKeyState & SHIFT_PRESSED)
        shift_flags |= BUTTON_SHIFT;

    if (shift_flags)
    {
        for (i = 0; i < 3; i++)
        {
            if (pdc_mouse_status.changes & (1 << i))
                pdc_mouse_status.button[i] |= shift_flags;
        }
    }

    return KEY_MOUSE;
}
Example #8
0
// Oh you, Win32 ... <_<
static size_t read_stdin(char *buf, size_t size)
{
   DWORD i;
   HANDLE hnd = GetStdHandle(STD_INPUT_HANDLE);
   if (hnd == INVALID_HANDLE_VALUE)
      return 0;

   // Check first if we're a pipe
   // (not console).
   DWORD avail = 0;
   bool echo = false;

   // If not a pipe, check if we're running in a console.
   if (!PeekNamedPipe(hnd, NULL, 0, NULL, &avail, NULL))
   {
      DWORD mode = 0;
      if (!GetConsoleMode(hnd, &mode))
         return 0;

      if ((mode & (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT))
            && !SetConsoleMode(hnd, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)))
         return 0;

      // Win32, Y U NO SANE NONBLOCK READ!?
      DWORD has_read = 0;
      INPUT_RECORD recs[256];
      if (!PeekConsoleInput(hnd, recs, sizeof(recs) / sizeof(recs[0]), &has_read))
         return 0;

      bool has_key = false;
      for (i = 0; i < has_read; i++)
      {
         // Very crude, but should get the job done ...
         if (recs[i].EventType == KEY_EVENT &&
               recs[i].Event.KeyEvent.bKeyDown &&
               (isgraph(recs[i].Event.KeyEvent.wVirtualKeyCode) || recs[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN))
         {
            has_key = true;
            echo    = true;
            avail   = size;
            break;
         }
      }

      if (!has_key)
      {
         FlushConsoleInputBuffer(hnd);
         return 0;
      }
   }

   if (!avail)
      return 0;

   if (avail > size)
      avail = size;

   DWORD has_read = 0;
   if (!ReadFile(hnd, buf, avail, &has_read, NULL))
      return 0;

   for (i = 0; i < has_read; i++)
      if (buf[i] == '\r')
         buf[i] = '\n';

   // Console won't echo for us while in non-line mode, so do it manually ...
   if (echo)
   {
      HANDLE hnd_out = GetStdHandle(STD_OUTPUT_HANDLE);
      if (hnd_out != INVALID_HANDLE_VALUE)
      {
         DWORD has_written;
         WriteConsole(hnd_out, buf, has_read, &has_written, NULL);
      }
   }

   return has_read;
}
Example #9
0
int __cdecl _kbhit_nolock (

        void
        )
{
        DWORD NumPending;
        DWORD NumPeeked;
        int ret = FALSE;
        PINPUT_RECORD pIRBuf=NULL;

        /*
         * if a character has been pushed back, return TRUE
         */
        if ( chbuf != -1 )
            return TRUE;

        /*
         * _coninpfh, the handle to the console input, is created the first
         * time that either _getch() or _cgets() or _kbhit() is called.
         */

        if ( _coninpfh == -2 )
            __initconin();

        /*
         * Peek all pending console events
         */
        if ( (_coninpfh == -1) ||

             !GetNumberOfConsoleInputEvents((HANDLE)_coninpfh, &NumPending) ||

             (NumPending == 0))
        {
            return FALSE;
        }

        pIRBuf=(PINPUT_RECORD)_calloca(NumPending, sizeof(INPUT_RECORD));
        if ( pIRBuf == NULL )
        {
            return FALSE;
        }

        if ( PeekConsoleInput( (HANDLE)_coninpfh,
                               pIRBuf,
                               NumPending,
                               &NumPeeked ) &&

             (NumPeeked != 0L) &&

             (NumPeeked <= NumPending) )
        {

            /*
             * Scan all of the peeked events to determine if any is a key event
             * which should be recognized.
             */
            PINPUT_RECORD pIR;
            for ( pIR = pIRBuf ; NumPeeked > 0 ; NumPeeked--, pIR++ ) {

                if ( (pIR->EventType == KEY_EVENT) &&

                     (pIR->Event.KeyEvent.bKeyDown) &&

                     ( pIR->Event.KeyEvent.uChar.AsciiChar ||
                       _getextendedkeycode( &(pIR->Event.KeyEvent) ) ) )
                {
                    /*
                     * Key event corresponding to an ASCII character or an
                     * extended code. In either case, success!
                     */
                    ret = TRUE;
                }
            }
        }

        _freea( pIRBuf );

        return ret;
}
Example #10
0
// simple version without readline...
void ServerConsole::MainLoop()
{
    char line[321];
    line[0] = '\0';

    CPrompt (COL_BLUE "%s: " COL_NORMAL, prompt);

    // This important flag allows clean shutdown outside the console
    // since stdin is polled asynchronously
    while (!stop)
    {

        // Make sure that if we don't type anything the loop is continued
        // so that the running flag will be checked.

#ifdef WIN32
        // Windows only allows select to be used on sockets so we have to use this
        // roundabout method. Note: the running flag won't be checked when the
        // user is in the middle of typing something.
        HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
        DWORD records_read = 0;
        INPUT_RECORD irec[1];

        // Wait until the console receives input
        if(WaitForSingleObject(hInput, 1000) == WAIT_TIMEOUT)
            continue;

        // Check if the record is for a keypress
        PeekConsoleInput(hInput, irec, 1, (LPDWORD)(&records_read));

        if(irec[0].EventType != KEY_EVENT)
        {
            // Read and discard this event
            ReadConsoleInput(hInput, irec, 1, (LPDWORD)(&records_read));
            continue;
        }
#else
        struct timeval tv;
        fd_set readfds;

        tv.tv_sec = 1;
        tv.tv_usec = 0;

        FD_ZERO(&readfds);
        FD_SET(STDIN_FILENO, &readfds);

        // This allows the running flag to be checked every second but only works on Unix.
        int retval = select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv);
        if(retval == 0)
        {
            continue;
        }
#endif

        if (fgets(line,319,stdin) == NULL)
        {
            // TODO: Yield timeslice here maybe?
			continue;
        }

        ConsoleOut::atStartOfLine = true;

        char* s;
        s = stripwhite(line);

        // Strip trailing newline
        if (s[strlen(s)-1]=='\n')
            s[strlen(s)-1]='\0';

        if (*s)
        {
#ifdef USE_HISTORY
            add_history(s);
#endif
            if (*s != '/')  // commands starting with slash are remote commands from npcclient to server
            {
                if(!strcmp("quit", s))
                    execute_line(s, NULL);
                else
                    EventManager::GetSingleton().Push(new psServerConsoleCommand(s));
            }
            else if (cmdcatcher)
            {
                // Give something else access to the command
                cmdcatcher->CatchCommand(s);
                CPrompt (COL_BLUE "%s: " COL_NORMAL, prompt);
            }
        }
        else
        {
            CPrompt (COL_BLUE "%s: " COL_NORMAL, prompt);
        }
    }
}