Search code examples
cargumentsstdinfgetc

C Lang - How to detect if a file has been used as input argument?


I am having issues with handling the arguments that are passed to my program. The user should have the ability to provide his own arguments or to provide a JSON file containing the arguments at launch.

The individual can enter their own arguments at the launch. For example:

prog --x 1 --y 2

The individual can also send the arguments through a file input (JSON).

prog < arguments.json

The issue I am having is trying to get to recognize if a file has been passed through stdin. More specifically, if the user runs the program without any arguments or file input.

I can easily find out if any arguments have been passed by checking argc, but then my program gets stuck at verifying if anything has been passed in stdin by going through this ;

[...]

char str[150];
char c;

while ((c = fgetc(stdin)) != EOF) {
    strncat(str, &c, sizeof(char));
}

[...]

After launching the program with no arguments, it sits in the terminal waiting for my input (which it should not be doing since there is no file input). The problem is only when the user has put in no arguments at launch, and the program tries to check the stdin. Is there anyway for me to check if stdin is empty before using fgetc?


Solution

  • Not easily. There are two immediate problems.

    1. As mentioned, it's not that easy to detect if the standard input is tied to a file. You could possibly use isatty but there may be perfectly valid reasons why you wish to send a file with real input to your program, not options.

    2. As foreshadowed in the preceding point, if you use standard input for passing in arguments, that rather stops you from also using it for "proper" input. Now it may be that your program expects no input in which case that's fine. But, if you want to provide a file with options and allow input, things start to get difficult.

    The way this is usually handled is to not use standard input for the options, rather you provide another option which will specify a file to be used.

    For example, the file my.options could contain --x 1 --y 2 and you would run your program as one of:

    prog --opts-file=my_options.json
    prog -o my_options.json
    

    That requires an extra level of indirection in that you have to handle both command line options and options read in from the file but it leaves standard input for what ${DEITY} intended :-)