Checking the availability of input on stdin
One of the things MinPSP is looking for, is native port of the homebrew SDK for their respective native platforms, so on Windows we have Windows native executables, on Linux we have Linux native executables, on Linux 64bit... you got the idea... One of the annoying things about this is that not all OSes are POSIX, and not all OSes are from Redmond, so there are quite some quirks that need to be fixed with the crancky #ifdef preprocessor statement. In my last revisit to the MinPSP code I tried to work around the lack of select on file descriptors on windows and converted the pspsh.exe binary from a cygwin binary to a 100% windows native. I isolated all socket code, sockets use select to verify the data availability and for the stdin i assumed that using _kbhit() would be enough. And it has been enough for me since for my tests i always used it from the command prompt, however a long time ago i wrote a small booklet explaining how to plug Eclipse IDE with MinPSP to make it easier to fully develop homebrew applications and there i showed how to invoke pspsh.exe from the eclipse tools. So what was the problem with Eclipse and MinPSP pspsh.exe? Well... i totally forgot that eclipse will just start the process and communicate with it via pipes!!! When you have pipes the _kbhit() function will never return a value other than 0. Having this in mind pspsh would never read anything from stdin since all I/O in the application is non blocking. So after long time of googling and testing i found this piece of code:
static int is_pipe = 0;
static HANDLE input_handle = 0;
int input_available()
{
DWORD nchars;
/* When using Standard C input functions, also check if there
is anything in the buffer. After a call to such functions,
the input waiting in the pipe will be copied to the buffer,
and the call to PeekNamedPipe can indicate no input available.
Setting stdin to unbuffered was not enough, IIRC */
if (stdin->_cnt > 0)
return 1;
if (is_pipe)
{
/* When running under a GUI, you will end here. */
if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
/* Something went wrong. Probably the parent program exited.
Could call exit() here. Returning 1 will make the next call
to the input function return EOF, where this should be
catched then. */
return 1;
return (nchars != 0);
}
else
return _kbhit() != 0; /* In "text-mode" without GUI */
}
Amazingly this code works for me, and lets me pool stdin from pipe for data available to be read. The only thing missing here is how is the is_pipe variable initialized. I've found 2 ways one using the function _isatty( _fileno(stdin)) or using Win32 API, I've chosen this way:
DWORD dw; input_handle = GetStdHandle(STD_INPUT_HANDLE); is_pipe = !GetConsoleMode(input_handle, &dw);
And that was it, now you can handle non blocking input from console and from pipes!!! Hurray!!!