By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,107 Members | 1,156 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,107 IT Pros & Developers. It's quick & easy.

parameters or stdin

P: n/a
Greetings!

I need to write some C code that will decide between either reading from
stdin or take a file name from argv and process it.

The program needs to work like all of the typical unix utilities where
the file to process is either provided from a pipe/stream or argv.

Utilities like lp, tr, grep, etc.

So, when the command:

cat filename | grep -i > filename2

or

grep -i filename > filename2

executes, this acts like the programmtic interface i need.

I have tried everything I can think of from getc, getchar, read, gets,
etc. which all did not work. I test for EOF or NULL on the return values
and the program just hangs on a terminal read. So, the command:

cat filename | testprogram -dvalue

hangs on the reading from stdin and I never get to test for EOF.

What am i missing?

Do I need to set some type of fcntl flag and control the stdin flow
similar to a wait/nowait process?

BTW, i am compiling this on HP-UX B.11.00 Unix.

I need an answer ASAP!

Thanks in advance!
Nov 15 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
David Warner wrote:
Greetings!

I need to write some C code that will decide between either reading from
stdin or take a file name from argv and process it.

The program needs to work like all of the typical unix utilities where
the file to process is either provided from a pipe/stream or argv.

Utilities like lp, tr, grep, etc.

So, when the command:

cat filename | grep -i > filename2

or

grep -i filename > filename2

executes, this acts like the programmtic interface i need.

I have tried everything I can think of from getc, getchar, read, gets,
etc. which all did not work. I test for EOF or NULL on the return values
and the program just hangs on a terminal read. So, the command:

cat filename | testprogram -dvalue

hangs on the reading from stdin and I never get to test for EOF.

What am i missing?


Probably you can show your code to see what's missing. This one works.

$ cat simplecat.c
#include <stdio.h>
#include <stdlib.h>

#define BUF_SIZE 100

int main(int argc, char ** argv)
{ char buf[BUF_SIZE + 1];
FILE * inp;

if(argc == 2)
{ inp = fopen(argv[1], "r");
if(!inp)
{ return EXIT_FAILURE;
}
}
else
{ inp = stdin;
}
while(fgets(buf, sizeof buf, inp))
{ printf("%s", buf);
}
fclose(inp);
return EXIT_SUCCESS;
}
ishs

Nov 15 '05 #2

P: n/a
In article <da****************************@corp.supernews.com >,
David Warner <da******@westbase.com> wrote:
I need to write some C code that will decide between either reading from
stdin or take a file name from argv and process it. I have tried everything I can think of from getc, getchar, read, gets,
etc. which all did not work. I test for EOF or NULL on the return values
and the program just hangs on a terminal read.


The usual thing to do it to see whether there's a filename argument
and read from stdin if there isn't. Trying to read is useless, since
there will always be either a file or a terminal on stdin (for typical
operating systems).

-- Richard
Nov 15 '05 #3

P: n/a
I did the exact same thing on HP-UX... this is how my code starts...

main(int argc, char *argv[])
{
if (argc > 1) {
if the arguments are greater than 1 (1 being the command) then process
them, else use a default. I wrote this to check the similarties
between 2 files. They are allways the same, but this way I can use it
to check whatever 2 files I wish. I can option to add file names or
use defaults.

Hope this helps,
-#2pencil-
http://www.akroncdnr.com

Nov 15 '05 #4

P: n/a

In article <d9***********@pc-news.cogsci.ed.ac.uk>, ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:

The usual thing to do it to see whether there's a filename argument
and read from stdin if there isn't. Trying to read is useless, since
there will always be either a file or a terminal on stdin (for typical
operating systems).


Unix is atypical? A great many Unix processes are executed with
neither a file nor a terminal associated with stdin. Some have
nothing associated with stdin (for Unix implementations, this
means descriptor 0 does not refer to an open entry in the file
table); many more have other types of system objects associated
with stdin.

The language requires that (for a hosted implementation) at program
startup stdin be "predefined" and "need not be opened explicitly".
That doesn't mean that it must refer to something that can success-
fully be read. It's entirely possible that the first attempt to
read from stdin will result in EOF or an error.

None of that helps with the OP's question, of course.

--
Michael Wojcik mi************@microfocus.com

This book uses the modern technology to explain the phenomemon in the world
of Japanese animation. If you love anime so much, you'd better read this.
After you read it, you may agree that is destroying the dream of the child.
Needs Chinese viewing system. -- The Goodboy Scientific
Nov 15 '05 #5

P: n/a
In article <da*********@news4.newsguy.com>,
Michael Wojcik <mw*****@newsguy.com> wrote:
Trying to read is useless, since
there will always be either a file or a terminal on stdin (for typical
operating systems).
Unix is atypical? A great many Unix processes are executed with
neither a file nor a terminal associated with stdin.


I was referring to programs run from the command line, which was what
the OP seemed interested in.

-- Richard
Nov 15 '05 #6

P: n/a

In article <da**********@pc-news.cogsci.ed.ac.uk>, ri*****@cogsci.ed.ac.uk (Richard Tobin) writes:
In article <da*********@news4.newsguy.com>,
Michael Wojcik <mw*****@newsguy.com> wrote:
Trying to read is useless, since
there will always be either a file or a terminal on stdin (for typical
operating systems).

Unix is atypical? A great many Unix processes are executed with
neither a file nor a terminal associated with stdin.


I was referring to programs run from the command line, which was what
the OP seemed interested in.


Perhaps. We all write code that makes some assumptions. I merely
wanted to point out that this one - that stdin could be read
successfully - was not always justified.

It's not true of programs started from the Unix command line, either.
In ksh:

$ cat <&-
cat: cannot stat

Does anyone do that? Yes. (After all, the operator is there for a
reason.) I recently had to use this myself, to run a program (that
I couldn't modify) in the background with no controlling terminal
association.

Many Unix programs can assume that stdin is associated with a
readable entity at program startup, because their failure mode if
it is not is acceptable. Some cannot. I've dealt with programs
that had security holes if they opened a file and it received
descriptor 0, 1, or 2, because they assumed that stdin, stdout,
and stderr were valid at program startup.

--
Michael Wojcik mi************@microfocus.com

Thanks for your prompt reply and thanks for your invitatin to your
paradise. Based on Buddihism transmigration, I realize you, European,
might be a philanthropist in previous life! -- supplied by Stacy Vickers
Nov 15 '05 #7

P: n/a
In article <da********@news4.newsguy.com>,
Michael Wojcik <mw*****@newsguy.com> wrote:
Perhaps. We all write code that makes some assumptions. I merely
wanted to point out that this one - that stdin could be read
successfully - was not always justified.


The assumption relevant to this discussion is not that stdin can be
read. On the contrary, it's that the fact that stdin *can* be read
implies nothing about whether it's the intended input for the program.
I see no harm in ignoring the corner cases of unix when explaining how
to decide where to read input from.

To reiterate the possibly lost point: decide where to read from based
on the arguments, not on the state of stdin.

-- Richard
Nov 15 '05 #8

P: n/a
Richard Tobin wrote:
Michael Wojcik <mw*****@newsguy.com> wrote:
Perhaps. We all write code that makes some assumptions. I
merely wanted to point out that this one - that stdin could be
read successfully - was not always justified.


The assumption relevant to this discussion is not that stdin can
be read. On the contrary, it's that the fact that stdin *can* be
read implies nothing about whether it's the intended input for the
program. I see no harm in ignoring the corner cases of unix when
explaining how to decide where to read input from.

To reiterate the possibly lost point: decide where to read from
based on the arguments, not on the state of stdin.


On most systems it is possible to decide whether or not stdin is
connected to an interactive keyboard with slightly non-portable
code (which in turn can be replaced by something that reports
not-a-keyboard portably). This allows some easy up-front
decisions, such as whether to emit a help screen and exit. Very
useful for filters.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 15 '05 #9

P: n/a
CBFalconer wrote:
Richard Tobin wrote:
Michael Wojcik <mw*****@newsguy.com> wrote:

Perhaps. We all write code that makes some assumptions. I
merely wanted to point out that this one - that stdin could be
read successfully - was not always justified.


The assumption relevant to this discussion is not that stdin can
be read. On the contrary, it's that the fact that stdin *can* be
read implies nothing about whether it's the intended input for the
program. I see no harm in ignoring the corner cases of unix when
explaining how to decide where to read input from.

To reiterate the possibly lost point: decide where to read from
based on the arguments, not on the state of stdin.

On most systems it is possible to decide whether or not stdin is
connected to an interactive keyboard with slightly non-portable
code (which in turn can be replaced by something that reports
not-a-keyboard portably). This allows some easy up-front
decisions, such as whether to emit a help screen and exit. Very
useful for filters.


Pray tell. Given foo, a program which takes no arguments and expects
input from stdin, I might invoke it two ways..

foo

in which case I am expected to enter data from the keyboard or..

foo < infile

in which case data comes to stdin from a file. How can I know from
within foo, which way foo was invoked?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #10

P: n/a
On Sat, 02 Jul 2005 10:02:57 -0400, Joe Wright
<jo********@comcast.net> wrote:
CBFalconer wrote:

On most systems it is possible to decide whether or not stdin is
connected to an interactive keyboard with slightly non-portable
code (which in turn can be replaced by something that reports
not-a-keyboard portably). This allows some easy up-front
decisions, such as whether to emit a help screen and exit. Very
useful for filters.


Pray tell. Given foo, a program which takes no arguments and expects
input from stdin, I might invoke it two ways..

foo

in which case I am expected to enter data from the keyboard or..

foo < infile

in which case data comes to stdin from a file. How can I know from
within foo, which way foo was invoked?


You can't do it portably. The C standard has no concept of what (if
anything) might be attached to stdin (or stdout or stderr for that
matter) or any other file stream.

OFF TOPIC:

On some systems there is an operating system call like isatty(int fd)
which returns a true value if the file descriptor (not FILE pointer)
refers to an interactive device. For instance, on a POSIX system (like
most modern Unix-derived ones) see

http://www.opengroup.org/onlinepubs/...ns/isatty.html

You will need to pass it the value 0 (zero) for the file descriptor of
stdin, or you can get the file descriptor of any FILE pointer using
fileno()

http://www.opengroup.org/onlinepubs/...ns/fileno.html

Windows with the POSIX layer installed may also support those functions
in console mode, as may some other non-Unix systems, but you need to
read the manuals for your system. Hopefully the above will give a clue
where to look. So on a POSIX compliant system you could write:

if (!isatty(fileno(stdin)))
{
fprintf(stderr, "Input not interactive!\n");
exit(EXIT_FAILURE);
}

However, there is no guarantee that a human is on the other end, it
could be a serial port connected to another computer for instance.

As CBFalconer said, you can then wrap those in a function of your own in
a module which is known to be implementation specific, so that the rest
of your code will be portable (and on a system without any way of
determining what is connected to stdin can just always return false or
whatever).

Chris C
Nov 15 '05 #11

P: n/a
Joe Wright wrote:
CBFalconer wrote:

.... snip ...

On most systems it is possible to decide whether or not stdin is
connected to an interactive keyboard with slightly non-portable
code (which in turn can be replaced by something that reports
not-a-keyboard portably). This allows some easy up-front
decisions, such as whether to emit a help screen and exit. Very
useful for filters.


Pray tell. Given foo, a program which takes no arguments and
expects input from stdin, I might invoke it two ways..

foo

in which case I am expected to enter data from the keyboard or..

foo < infile

in which case data comes to stdin from a file. How can I know
from within foo, which way foo was invoked?


It is not properly portable, but I use the following, which is
arranged so that I do not have to inhibit proper checking in the
rest of the C file. If it doesn't work simply replace it by
something that does "return 0" and you are back where you are now.
The usage is simply:

if (akeyboard(stdin)) helpandexit();
else {
/* use the redirected stdin */
}

and it is all independent of whether or not foo takes arguments.

/* ------------------- */

/* This is very likely to be non-portable */
/* DOES NOT check fp open for reading */
/* NULL fp is considered a keyboard here! */
static int akeyboard(FILE *fp)
{
#ifndef __TURBOC__ /* Turbo C is peculiar */
# ifdef __STDC__
/* This dirty operation allows gcc -ansi -pedantic */
extern int fileno(FILE *fp);
extern int isatty(int fn);
# endif
#endif
return ((fp != NULL) && isatty(fileno(fp)));
} /* akeyboard */

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 15 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.