Determining if stdin data exists for your program BEFORE issuing fgetc() or similar command

banders7 0 Tallied Votes 630 Views Share

A program that handles either piped input (command/prog | your_prog) or file redirected (your_prog < file_name) input. Determine whether such input exists before issuing a stdin read so that the program does not go into a "waiting for input" state. Written in/for the XP environment.

// Problem:
// You need to write a program (like 'more') that can accept input in the
// form of a pipe, as in: some_program_or_command | your_program or from
// a redirected file as in: your_program < some_file. You need to be able
// to determine if data exists in stdin BEFORE issuing a command such as
// ch = fgetc(stdin), which will put your program into a wait state (if there
// is no data) until such time as you manually feed it 1 or more characters,
// press enter and/or press ctrl+z followed by enter to
// terminate the input.
//
// Execute 'more' without piped or redirected input and see what happens.
// Remember ctrl+z and enter to end normally, ctrl+c to abort

#include <stdlib.h>
#include <stdio.h>
#include <io.h>    // filelength()
#include <conio.h> // fgetc()
int main(int argc, char *argv[])
{
int stdinHandle,stdinFileLength;
int fseekRC;
char ch=-2,savech=-2;
int bytes;
int i=-1;

argc--;
if (argc > 0) // any command line input (not germane to this exercise)
   printf("Command line input ignored\n");

// Try to determine the length of STDIN file
stdinHandle = fileno(stdin);
stdinFileLength = filelength(stdinHandle);

// filelength function failed. NO piped data, NO redirected data
if (stdinFileLength < 0)
   {
   printf("There are currently no characters waiting in STDIN\n");
   printf("DOS Error Code: %d\n",errno);
   printf("DOS Error Text: %s\n",_sys_errlist[errno]);
   return -1;
   }

// Trial and error has shown me that redirected input from a file returns
// a filelength > 0 (the actual file length),  but piped input, regardless of
// how much data is there, MAY return a file length of 0. Not sure why some
// pipes show actual length and some show 0.
if (stdinFileLength == 0)
   {
   // Try to reposition the file pointer to the beginning of file
   // If, despite a 0 length indicator, it works, there really is data.
   // Actually, BOF or EOF does not really reposition the pointer, but if
   // there is input there, the function does not fail ....
   // Again, piped input can/will show as having 0 bytes ....    0      1
   fseekRC = fseek(stdin,0,0); // fseek(file,offset,relative to BOF or EOF flag)
   if (fseekRC < 0) // Seek failed. Definitely no data
      {
      printf("There are currently no characters waiting in STDIN\n");
      printf("DOS Error Code: %d\n",errno);
      printf("DOS Error Text: %s\n",_sys_errlist[errno]);
      return -1;
      }
   }

// We have now determined that there is stdin data ...
bytes = 0;
// fgetc or fgets or something else ... whatever strikes your fancy
// so long as it's an explict stdin read
// I'm fond of fgetc ... there's no dependency on finding carriage return/
// line feeds in the input stream
ch = fgetc(stdin);
while(ch != -1)
   {
   // Do what you will with data coming in ... store it, spank it, whatever
   bytes++;
   savech = ch; // Idle curiosity ... what is last character read?
   ch = fgetc(stdin);
   }
// Post stdin input checks .... (getstdin is what I compiled this under)
printf("Bytes in: %d\n",bytes);
if (bytes == 0)
   printf("Hmm, command was likely getstdin < (0 length file) !!!\n");
if (bytes == 1 && ch == -1)
   {
   printf("Hmm, command was likely command/prog | getstdin with 0 length pipe data\n");
   printf("such as: cls | getstdin (savech = %d/0x%X/%c)\n",savech,savech,savech);
   }
// Exceptions have been now been identified
// At this point, you should be able to go ahead and process the data
// collected in the loop above
return 0;
}
jivemaster 0 Newbie Poster

Really useful stuff, thank's
I can fill in why filelength() is 0 though..
The piped program will not send EOF until terminated,
and unless fflush(stdin) is called, nor stdout is filled real quick,
filelength() will return 0.. make sens :) /Magnus

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.