I have simple program that reads file line by line, and prints each line. The core of the program is:
while ((size = getline(&line, &len, f)) != -1)
printf("%s", line);
Now I have following problem:
this works:
./test zz
this also works:
/bin/cat <(./test zz)
but when I pipe the output to other program, it does not work:
/bin/cat <(./test zz) | /bin/cat
there is no output.
When I compare with strace
the one that works, and the one that doesn't:
/bin/cat <(strace ./test zz)
/bin/cat <(strace ./test zz) | /bin/cat
I see this error: -1 ENOTTY (Inappropriate ioctl for device)
ioctl(0, TCGETS, 0x7ffc302104d0) = -1 ENOTTY (Inappropriate ioctl for device)
brk(NULL) = 0x55b4e1fd3000
brk(0x55b4e1ff4000) = 0x55b4e1ff4000
fstat(0, {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}) = 0
ioctl(0, TCGETS, 0x7ffc30210350) = -1 ENOTTY (Inappropriate ioctl for device)
read(0, "", 4096) = 0
close(0) = 0
exit_group(0) = ?
+++ exited with 0 +++
here is my proof-of-concept code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <unistd.h>
int main(int argc, char **argv) {
FILE *f;
char *line = NULL;
size_t len = 0;
ssize_t size, cut;
if (!isatty(STDIN_FILENO) || argc < 2 || (argv[1] == "-"))
f = stdin;
else
if (!(f = fopen(argv[1], "r"))) {
perror(argv[1]);
return 1;
}
while ((size = getline(&line, &len, f)) != -1)
printf("%s", line);
fflush(stdout);
fclose(f);
if (line)
free(line);
exit(EXIT_SUCCESS);
}
I have removed the part: (!isatty(STDIN_FILENO)
and that fixed the problem. But I don't understand what is happening.
I originally added this, so that my program can take filename as argument ./test zz
or take input from pipe cat zz | ./test
.
If any of the following conditions are true, the program uses stdin for input:
-
.In the scenario you presented, stdin isn't connected to a terminal[1], so the test
reads from stdin. You don't get the desired result since you want to read from the file zz
.
The first condition (!isatty(STDIN_FILENO)
) makes no sense. You were correct to remove it. The remaining two conditions are sufficient to make cat zz | ./test
work.