kvancamp@ardc.arpa (LCWSL) (12/18/85)
I'm sending one more message to the net regarding the use of buffering when teeing to a file and stdout. This is in response to one person who asked me to summarize my findings, a couple of others who wrote me and shared my misconceptions of the problem, and a few other people who sent me programs that I couldn't respond directly to (my mailer didn't understand their address on the net). I apologize to this last group for not sending replies directly; it wasn't for lack of trying. My problem was with a program whose output I wished to echo to a file at the same time I viewed it on the screen. Because of the interactive nature of the program, it was imperative that buffering be inhibited so I could see the questions before having to respond to them. My findings are as follows: 1.) Three people sent me their versions of tee that inhibited buffering. The main idea was to make a call to setbuf(stdout, (char *) 0); The problem here is that tee wasn't the culprit in the buffering. It was the pipe from my original program, which wrote to stdout. Whenever Unix sees a pipe, it automatically buffers output. I tried all 3 versions of tee, and none could inhibit this. To quote one of the respondees: >This whole saga is so sad when you think about one of the fundamental >UNIX philosophies: files are all just streams of characters and you >can replace files with pipes with devices and it all works the same. >As long as programs don't try to find out where they are going or coming >from (unlike stdio & BSD ls, vi) this works great. When it is violated, >it causes major problems! 2.) The script command is what I really wanted, but didn't have on my Masscomp. One person was nice enough to send me a program he wrote that was similar to script; it compiled on my Masscomp with no alterations (praise be for portable programming!). It's really quite a nifty program. Just start it up and it creates a new shell, piping ALL output thereafter to both a file and stdout, until it is killed. Unfortunately (as the author pointed out), the program uses pipes to do what it does, instead of script's method of using pseudo ttys (pty's); hence the same old problem. Output is buffered because the system sees a pipe. Nonetheless, this is a very useful program when buffering is not a problem -- I'll definitely keep this one around. Some day when I have the time I'd like to modify this program to use pty's (which my Masscomp has) -- to make it a true script command. 3.) The only solution for now is to modify my original program to add the setbuf call. This is okay because all of my interactive programs were written here and I have the sources. As someone pointed out, if the program generates a lot of output, fflush is better to use than setbuf so that things aren't slowed down too much by the inhibited buffering. I've done this already and it works fine. Thanks again to all those who responded! (Any additional comments should be sent directly to me, as I am not on the net. -- <kvancamp@pica-lca.arpa>)
gwyn@BRL.ARPA (VLD/VMB) (12/18/85)
I think it would be a nice idea if the STDIO package would treat pipes much like terminals by default; i.e., not try to fill the whole BUFSIZ buffer but just use whatever data the read() returns. (I don't think anything useful can be done about output to a pipe, since allowing single-character write() would be too inefficient for general use.) Would this cause problems for anyone? If not, let's do it..