0

So I have a project that that requires me to doing something like:

./test < input.txt

But not all the time. The program can also be run as:

./test

with some different code between the two. I'm having trouble being able to differentiate between the two in code. For example, both have an argc value of 1.

What's the best way to tell whether or not there is an input file in the command line?

7
  • 3
    Programs can't tell the difference. Input redirection is handled transparently by the shell. Commented Oct 3, 2017 at 20:37
  • 3
    Usually if a program needs to operate differently, what it really cares about is whether standard input is a terminal or a file, not whether redirection was done on that command line. On Unix the isatty() function can be used. Commented Oct 3, 2017 at 20:39
  • 2
    What kind of difference are you supposed to make between the two? Commented Oct 3, 2017 at 20:40
  • 1
    Are you sure you're not trying to detect the difference between ./test input.txt and ./test? Commented Oct 3, 2017 at 20:40
  • 1
    Perhaps you should edit the question and paste in more of the assignment text. Either this is much more complicated than your instructor likely intended or you have misinterpreted the instructions. Commented Oct 3, 2017 at 20:42

2 Answers 2

2

There are no general ways, and it is operating system specific. I am focusing on Linux and POSIX systems. Notice that test is a poor name (colliding with test(1)...) and that mytest < input.txt stills gets its input from stdin since the redirection is done by the shell before starting your mytest program with execve(2).

The usual way to read from a file would be to give it as explicit argument: mytest input.txt (then test argc). I strongly recommend having such a convention. See also getopt(3), read about program arguments.

On Linux (or POSIX), you might use fstat(2) and/or isatty(3) on STDIN_FILENO (i.e. 0) and even that is not be bullet proof, e.g. for pipelines or here documents.

You might even want to consider the case of batch invocation (i.e. at or crontab jobs) and background jobs. For that you could also check the environment, see environ(7). Read also credentials(7) on controlling terminals and sessions (setsid(2)) and job control. See also /dev/tty (so termios(3), tty(4), and the tty demystified). BTW, you could also care about stdout or stderr being (or not) redirected.

I recommend being able to overcome such an autodetection with explicit program arguments, because it won't be perfect since there are corner cases (what about mytest < /dev/stdin and mytest < /dev/tty ? Do you consider these as redirections to be detected ?). There are conventions and habits about program arguments.

Few programs are doing such an autodetection, and those that do are providing a way, thru program arguments, to overcome it (for example, ls --color and emacs -nw).

Sign up to request clarification or add additional context in comments.

Comments

0

The < operators is used for input redirection. This just means that the file specified after < replaces stdin for that program.

The other method you have does not replace stdin, so the normal stdin file is read from.

In both cases you are still reading from stdin, so no worries, so you might want to double check what the actual requirements are.

1 Comment

But he says in the question that the program is supposed to do different things depending on which way it's used.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.