Is it possible to read intermittently-sent data through a named pipe using redirection to stdin?
What I’d like to do is this:
$ mkfifo pipe
$ ./test < pipe
In another terminal:
$ cat datafile > pipe
$ cat datafile > pipe
repeating dumping information into the pipe. This only works the first time.
Here’s a demonstration program for test that shows the behavior:
int main(int argc, char *argv[]) {
char input_string[30];
while(1) {
while( cin.read(input_string, 30) || cin.gcount()!=0 ) {
cout << "!" << endl;
}
}
return 1;
}
So, what’s going on? Does redirection only provide the contents of a single send to the pipe? I’ve already written a version of the actual production code that takes in the name of the pipe as a parameter and keeps it open for writing this way, and maybe that’s the answer. But I’m wondering if there’s a way to do this with redirection.
When you redirect the input from the pipe like this:
The shell opens the pipe for reading and then starts your program. But opening the pipe does not complete until a writer exists — that is,
open(2)blocks. When another process opens the pipe for writing, the originalopencall completes, and the two can communicate. When the writer closes its end of the pipe, the read end also closes — the reader gets an EOF.Once that cycle completes, you can reopen the pipe for reading and start another cycle, but you have to do it yourself. So if you’re reading for stdin, you’ll have to restart your program. Alternatively, you can just reopen the pipe on a different file descriptor, e.g.:
If you want to wrap the raw I/O in a stdio
FILE*, you can usefdopen(3); I’m not aware of a way to wrap a file descriptor in a C++ stream object, though it might be possible.