Check if process has a stdin handle

  • Thread starter Nikos Chantziaras
  • Start date
N

Nikos Chantziaras

Hello.

Is there a way to check if the current process has an stdin handle? In
the win32 API, one can do:

_eof(_fileno(stdin))

Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?
 
E

Eric Sosman

Nikos Chantziaras wrote On 08/01/07 09:50,:
Hello.

Is there a way to check if the current process has an stdin handle? In
the win32 API, one can do:

_eof(_fileno(stdin))

Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?

What is a "stdin handle," and what does it mean
for a process to "have" one?

In a hosted environment, at the moment main() is
first called the three streams stdin, stdout, stderr
are open and ready for action. They will remain so
until the program ends, or you close them, or an I/O
error occurs. I/O errors can be detected by using the
ferror() function. If you close any of these streams
you ought to know you've done it. Writing code to
determine the streams' state after the program containing
the code exits is left as an exercise for the reader ;-)
 
R

Richard Tobin

Eric Sosman said:
In a hosted environment, at the moment main() is
first called the three streams stdin, stdout, stderr
are open and ready for action.

Theoretically perhaps, but are there any operating systems where that
is in fact guaranteed?

I don't think so. On unix, a natural thing would be call fstat() and
see if you get EBADF. But it would be more portable just to not do
it: use some other criterion to decide whether to use stdin. That's
the typical unix approach: "cat" reads stdin only if it doesn't have
any filename arguments; it doesn't try to determine whether reading
stdin would block.

-- Richard
 
S

santosh

Nikos said:
Hello.

Is there a way to check if the current process has an stdin handle? In
the win32 API, one can do:

_eof(_fileno(stdin))

Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?

A three standard streams, stdin, stdout, and stderr are always opened and
initialised when a Standard C program begins execution. It might then close
or reopen them. It's not possible in an arbitrary position within the
program to find out whether stdin is open or is connected to the input
device. If you close or reopen stdin, you'll have to manually keep track of
this detail yourself.

Any system specific methods to do this are topical in groups for those
systems, not here.
 
S

santosh

Richard said:
Theoretically perhaps, but are there any operating systems where that
is in fact guaranteed?

Doesn't the C Standard require it to be so?
 
N

Nikos Chantziaras

Eric said:
Nikos Chantziaras wrote On 08/01/07 09:50,:

What is a "stdin handle," and what does it mean
for a process to "have" one?

In a hosted environment, at the moment main() is
first called the three streams stdin, stdout, stderr
are open and ready for action. They will remain so
until the program ends, or you close them, or an I/O
error occurs. I/O errors can be detected by using the
ferror() function. If you close any of these streams
you ought to know you've done it. Writing code to
determine the streams' state after the program containing
the code exits is left as an exercise for the reader ;-)

I formulated it a bit "weird". It's porting work, btw, (from win32 to
"as portable as possible") so not everything is 100% clear to even me,
since I'm not the implementor of the original; I just do the porting ;)

In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.
 
A

Army1987

I formulated it a bit "weird". It's porting work, btw, (from win32 to
"as portable as possible") so not everything is 100% clear to even me,
since I'm not the implementor of the original; I just do the porting ;)

In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.
Have you tried feof(stdin) or ferror(stdin)?
 
S

santosh

Nikos said:
I formulated it a bit "weird". It's porting work, btw, (from win32 to
"as portable as possible") so not everything is 100% clear to even me,
since I'm not the implementor of the original; I just do the porting ;)

In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.

The closest you can come within Standard C is the feof function. It returns
a non-zero value if the end-of-file indicator has been set for it's
argument, which must be a FILE*. The end-of-file indicator would have been
set by the previous I/O operation on that stream, example, a getc call or
an fgets call.

The other possibility for C's I/O functions to return EOF, (which is a macro
defined in stdio.h), is for a read or write error. In this case the
function ferror will return a non-zero value on the concerned stream.
 
A

Army1987

Theoretically perhaps, but are there any operating systems where that
is in fact guaranteed?
On a hosted implementation, they are required to be opened at
program startup, so I think that if something goes wrong, either
the program cannot be started (i.e. main() cannot be called) at
all, or there will be a valid pointer-to-FILE called stdin, but
ferror(stdin) will be nonzero and every operation on it will fail
(e.g. return EOF).
 
N

Nikos Chantziaras

Army1987 said:
Eric said:
Nikos Chantziaras wrote On 08/01/07 09:50,:
Is there a way to check if the current process has an stdin handle? In
the win32 API, one can do:

_eof(_fileno(stdin))

Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?
What is a "stdin handle," and what does it mean
for a process to "have" one?
[...]
[...]
In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.
Have you tried feof(stdin) or ferror(stdin)?

Yes. But AFAIK, feof() checks the EOF indicator of a stream, and that
indicator is only set after actually trying to read from the stream.
feof(stdin) therefore would never return non-zero right at the start of
the program (when nothing has been read from stdin yet).
 
N

Nikos Chantziaras

santosh said:
Nikos said:
[...]
In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.

The closest you can come within Standard C is the feof function. It returns
a non-zero value if the end-of-file indicator has been set for it's
argument, which must be a FILE*. The end-of-file indicator would have been
set by the previous I/O operation on that stream, example, a getc call or
an fgets call.

The other possibility for C's I/O functions to return EOF, (which is a macro
defined in stdio.h), is for a read or write error. In this case the
function ferror will return a non-zero value on the concerned stream.

I already suspected that getting information about EOF on an I/O
operation that has yet to happen is not possible with standard C. I
guess I'll just have to use fstat() (or even select()). (Even though
the primary target for the port is Unix, I always try to find a standard
C solution first, then going down the road of standards - POSIX, BSD,
SYSV, etc, with kernel calls being the last resort).
 
S

santosh

Nikos said:
Army1987 said:
Eric Sosman wrote:
Nikos Chantziaras wrote On 08/01/07 09:50,:
Is there a way to check if the current process has an stdin handle?
In the win32 API, one can do:

_eof(_fileno(stdin))

Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?
What is a "stdin handle," and what does it mean
for a process to "have" one?
[...]
[...]
In any event, the original is "_eof(_fileno(stdin))" which checks for
EOF on stdin without blocking. In other words, it allows for knowing
beforehand if EOF would be returned when attempting to read from stdin
without actually reading.
Have you tried feof(stdin) or ferror(stdin)?

Yes. But AFAIK, feof() checks the EOF indicator of a stream, and that
indicator is only set after actually trying to read from the stream.
feof(stdin) therefore would never return non-zero right at the start of
the program (when nothing has been read from stdin yet).

Quite rightly so. How can a program or the system predict that I'll signal
end-of-file with next key sequence without blocking for the key codes to
arrive?

Some libraries can use special system specific APIs to "peek ahead" into the
system's input buffer and look for the end-of-file sequence without
involving an actual read function, but Standard C doesn't work this way.
You'll have to look at your system's terminal facilities to find out a way
to do this.
 
R

Roberto Waltman

Nikos said:
Is there a way to check if the current process has an stdin handle? In
the win32 API, one can do:
_eof(_fileno(stdin))
Crucial here is that the above doesn't block. Is there a standard way
to do the same without resorting to OS-specific API calls?

The following code does not discriminate between a stream at EOF and
other possible error conditions. (stream invalid, not-open, etc.)

#include <stdio.h>

int stream_has_some_data(FILE *stream)
{
int c = getc(stream);
if (c != EOF)
{
ungetc(c, stream); /* add check for errors */
return 1;
}
return 0;
}




Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 
R

Richard Tobin

Theoretically perhaps, but are there any operating systems where that
is in fact guaranteed?
[/QUOTE]
On a hosted implementation, they are required to be opened at
program startup, so I think that if something goes wrong, either
the program cannot be started (i.e. main() cannot be called) at
all, or there will be a valid pointer-to-FILE called stdin, but
ferror(stdin) will be nonzero and every operation on it will fail
(e.g. return EOF).

The latter is what happens on all the implementations I'm familiar with.
For example, on unix (using bash as a shell) then "cat <&-" will result
in the unix file descriptor 0 being not open, so that reads from stdin
return EOF with errno set to EBADF.

So yes, you're right, they are open in the strict C sense of being a
usable FILE *, but I assume the OP wanted to be sure that stdin was
"really open", in the sense of being connected to something.

-- Richard
 
R

Richard Tobin

Quite rightly so. How can a program or the system predict that I'll signal
end-of-file with next key sequence without blocking for the key codes to
arrive?

In the case in question, the system may know that stdin is not
connected to anything, so that any read would result in EOF. I think
it would be reasonable for a system to consider that if stdin isn't
connected to anything then an error has already occurred, and make
ferror(stdin) return true. But I don't know of any implementations
that do that - they just let you get the error when you do the read.

[On unix, running a program with stdin unconnected will result in
bizarre results if the program fopen()s a file and then attempts to
read from stdin, because the opened file will have file descriptor 0
and therefore be attached to stdin as well as the FILE * returned from
fopen().]

-- Richard
 
R

Roberto Waltman

Eric Sosman said:
In a hosted environment, at the moment main() is
first called the three streams stdin, stdout, stderr
are open and ready for action.

Is this guaranteed? I though a process can be started with any or all
of the standard streams closed.
For example, a Unix application to start an arbitrary program as a
"daemon" by, among other things, closing stdin, stdout and stderr
before calling an exec???() function.
On the other hand, I just read on the OpenGroup man page for exec that
"If file descriptors 0, 1, and 2 would otherwise be closed after a
successful call to one of the exec family of functions, ... <snip> ...
implementations may open an unspecified file for each of these file
descriptors in the new process image."
What does the C standard require? (I couldn't find an answer on N1124)

Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 
R

Richard Tobin

Roberto Waltman said:
On the other hand, I just read on the OpenGroup man page for exec that
"If file descriptors 0, 1, and 2 would otherwise be closed after a
successful call to one of the exec family of functions, ... <snip> ...
implementations may open an unspecified file for each of these file
descriptors in the new process image."

Ah, presumably that is to avoid the strange behaviour I mentioned.
But none of the unixes I have to hand seem to do it.

-- Richard
 
E

Eric Sosman

Richard Tobin wrote On 08/01/07 10:36,:
Theoretically perhaps, but are there any operating systems where that
is in fact guaranteed?

As far as C is concerned, yes (7.19.3p7). They might
not be "really open" from the platform's point of view --
for example, an implementation might defer the "low-level
open" that underlies stderr until the program actually
writes something to it. Still, the implementation must
behave as if stderr has been open all along -- in particular,
if the "low-level open" fails, this will have to show up
as an I/O error in the output function, not as a failure in
the (non-existent) fopen call.
 
R

Richard Tobin

Roberto Waltman said:
Correct. The following code fragment may or not do what you need, it
does not discriminate between a stream at EOF (not an error) and other
possible error conditions: stream invalid, not-open, etc.
#include <stdio.h>

int stream_has_some_data(FILE *stream)
{
int c = getc(stream);
if (c != EOF)
{
ungetc(c, stream); /* add check for errors */
return 1;
}
return 0;
}

This has the problem (for the OP) that it may block for an arbitrarily
long time if the stream is connected to, for example, a terminal.

-- Richard
 
R

Roberto Waltman

Nikos said:
Yes. But AFAIK, feof() checks the EOF indicator of a stream, and that
indicator is only set after actually trying to read from the stream.
feof(stdin) therefore would never return non-zero right at the start of
the program (when nothing has been read from stdin yet).

Correct. The following code fragment may or not do what you need, it
does not discriminate between a stream at EOF (not an error) and other
possible error conditions: stream invalid, not-open, etc.

#include <stdio.h>

int stream_has_some_data(FILE *stream)
{
int c = getc(stream);
if (c != EOF)
{
ungetc(c, stream); /* add check for errors */
return 1;
}
return 0;
}

(Sorry if this is an almost duplicate post. I canceled a previous
one, but ...)

Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top