views:

448

answers:

3

Hi,

I have some problem to figure out how I can maintain the pipe and redirect functionality of a shell once I find out that there are missing command line arguments.

If I for example use a scanf call, that will work with a re-direct or a pipe from a shell, but in absence of this I get a prompt, which I don't want.

I would like to accept command line arguments through argv[], a pipe or re-direct but I can't figure out how to do it with out getting the prompt. If I for example try something like this:

if(argc < 2)
    exit(0);

Then the program will terminate if I try this:

echo arg | myProgram

Or this:

myProgram < fileWithArgument

I have tried to look this up but I always get some bash scripting reference.

+7  A: 

The common way to handle situations like this is to check if the standard input stream is connected to a terminal or not, using isatty or similar functions depending on your OS. If it is, you take parameters from the command line, if not (it's been redirected), you read standard input.

anon
Great, that seems like it should work. I have isatty available here (os x). Thanks
Fred
A: 

In your examples you are using pipe redirection, both echo arg | myProgram and myProgram < filesWithArguments are sending output to the STDIN of your program.

If you want to read these values, use scanf or fread on the STDIN file descriptor.

If you are trying to get the file content as an argument list for your executable, you need to use it like this:

# This will pass `lala` as a variable
myProgram `echo lala`
Am
Ok, I see. But the problem I have had with this is that if I give no arguments at all I get a prompt. What I would like instead is a usage description followed by termination. I haven't used fread but scanf or fgets.
Fred
+2  A: 

Short version: You can't do it.

Pipeline and redirect specifiers are not arguments to your program, rather they are commands to the invoking shell and are processed before the running instance of your program even exists. The shell does no pass them to the program in argv or any other variable, and you can not discover them in any reliable way.

Neil has given you the way to determine if you are connected to a terminal.

dmckee
Sure, and I have now used isatty successfully. The reason for wanting to do this is that it's the way most program works. It would not be possible (or very limiting) to use the program in a bash script if the input could not be redirected, right.
Fred
How would you say that this is done typically then, when writing command-line tools if they are to be posix compliant? They should accept pipes and redirection.
Fred
@Fred: I am still not clear *what* you want to accomplish. What you can't do is detect what (if any) pipelines and redirects have been established. Normally you write you code to expect a particular behavior and provide commandline flags for changing it to other mechanisms that you support. That is: you expect you caller to *tell you* what kind of non-default input they are sending.
dmckee
I see, what I wan't to do in this particular case is to make a program that can add metadata to a file. In this case I want to be able to use it in scripts (to process an entire folder for example) as well as running it manually on one single file with provided arguments. What I do now is check if the input comes from a terminal (thanks Niel), if it does, I use argv. If isatty returns 0 I get the input with fgets, parse it and make sure it's valid for the purpose of what I'm doing. So far this has worked as I expected.
Fred