davide
davide

Reputation: 2152

fgets(): Ok by console, Bad by pipe

Executing the following C code

#include <stdio.h>
int main(int argc, char **argv) {
  char stdinput[10];
  while (1) {
    fgets(stdinput, 10, stdin);
    fputs(stdinput, stdout);
  }
}

produces:

By console:

./a.out
input
input

and then it waits for more input. That is, it echoes stdin to stdout, similarly to cat.

By pipe:

echo input | ./a.out
input
input
input
[...]

after being started, it floods the console, all by itself, without interaction.

This example program is exactly what I used for the tests; it's not a cut. I would expect the two tests to behave the same way. What's happening?

Upvotes: 4

Views: 6365

Answers (3)

Simon MILHAU
Simon MILHAU

Reputation: 214

You could just replace your loop condition by your fgets call, giving:

#include <stdio.h>
int main(int argc, char **argv) {
  char stdinput[10];
  while (fgets(stdinput, 10, stdin)) {
    fputs(stdinput, stdout);
  }
}

This will loop until you get an EOF, in which case fgets() returns NULL just as @nneonneo said. But with this condition you will not have to break your while().

Upvotes: 6

Bowman
Bowman

Reputation: 11

[Note: solves the wrong problem.]

See http://sweslo17.blogspot.tw/2012/04/c-standard-input-redirection.html.

After fgets(), you can add below code to restore stdin again that resolve pipe problems.

freopen("/dev/tty","rb",stdin);

Upvotes: 1

nneonneo
nneonneo

Reputation: 179687

Once EOF is reached, fgets returns NULL immediately without waiting for input (or modifying the buffer). Thus, it will loop infinitely. In your pipe case, echo will close the pipe once it has written "input\n", resulting in EOF.

Change your fgets call to

if(fgets(stdinput, 10, stdin) == NULL)
    break;

Upvotes: 7

Related Questions