1

I am writing a program which currently gets continuous input from stdin and does something with it until stdin is closed.

fgets(buffer, BUFFERSIZE, stdin);
while(fcntl(fileno(stdin), F_GETFD) != -1 || errno != EBADF){
    /*
    some code
    */
    fgets(buffer, BUFFERSIZE, stdin);
}

Currently to test out if this is a valid way of checking if stdin is closed the

some code

is set to just print buffer continuously. However when I try to close stdin with Ctrl +D the program keeps printing whatever it had in buffer indefinitely. Why is that?

1 Answers1

1

There is no portable way to detect that a FILE * has been closed, even for predefined streams such as stdin, stdout or stderr. Testing the system handle fileno(stdin) is not portable and accessing the handle of a stream has undefined behavior if the stream has been closed with fclose().

You seem to make a confusion between closing a stream, which is performed by fclose(), and reaching the end of file, which is detected by testing the return value of fgets() and other functions reading from a stream.

Here is a modified version:

while (fgets(buffer, BUFFERSIZE, stdin)) {
    /*
    some code handling the input received in buffer.
    */
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • *You seem to make a confusion between closing a stream, which is performed by fclose(), and reaching the end of file* Indeed. If `stdin` has been redirected from a file, for example, it won't ever be "closed" unless the process itself closes it, so testing if `stdin` has been closed is not in general useful. – Andrew Henle Oct 03 '22 at 22:33
  • @AndrewHenle: good point: ^D does not actually close the file handle, it causes `read` to return immediately with the number of bytes buffered so far, which is `0` at the beginning of line. The stream library interprets that as an end of file. – chqrlie Oct 03 '22 at 22:39