Bi-directional popen()
functionality was added in FreeBSD 2.2.6 and is available in MacOS. I have a C program that writes a stream of newline-separated strings, and I'd like for it to pipe this to a Perl tool I wrote called cols that reads such a stream from STDIN, buffers it, and then writes it to STDOUT in a multicolumn, vertically-sorted format.
In the C program, I use:
FILE *cols_pipe = popen("cols", "r+");
to open the pipe and start cols;
fprintf( cols_pipe, "%s\n", word );
to send each newline-terminated word to cols; and
while ((getline(&line_buf, &line_buf_len, cols_pipe)) != -1) {
printf("%s", line_buf);
}
to read back and print the reformatted lines from cols. When the program hung at getline()
I realized it was because cols hadn't received EOF on STDIN, but closing cols_pipe (the only way I can think of to send EOF) would prevent me from reading back.
Obviously, cols can't begin to write its output until it's read all the input.
Any suggestions on how to achieve this? The C program is interactive so I don't want to simply invoke it from the command line with STDOUT piped to cols.
setvbuf()
on cols_pipe to disable buffering or make it line-based or call fflush() after your fprintf()perl
for the reverse direction (seeperldoc -v '$|'
)@all_lines=<STDIN>
and theprint "something"
then yes, it waits for EOF and you can't use popen(r+). If it doeswhile(<STDIN>){print "something";}
reading one line at a time, then you should be able to interact with it with your cols_pipe, but you'll likely still have a problem in the end if you need to signify EOF to cols and still read more output from it after that. You'd probably be better of using two pipes or a socketpair where you can shutdown directions independently. I've never used FreeBSD's popen(r+) or bidirectional pipes, they don't seem very useful