From: Dilbert on
I have the following program:

use strict;
use warnings;

# redirect STDOUT to a file, but keep output to
# screen alive (via the "tee" command)
open STDOUT, "| tee logfile.txt" or die "Error: $!";

print "abc", "z" x 30, "enter a number >";
my $num = <STDIN>;
print "\nYou entered: $num\n";

When I run this program, I see

abczzzzzzzzzzzzzzzzzz

but I can see no prompt "enter a number >"

the cursor waits after the "...zzzz"

I can blindly type in a number (e.g. 123), when I do this, I see the
following on my screen:

abczzzzzzzzzzzzzzzzzz123
zzzzzzzzzzzzenter a number >
You entered: 123

The problem here is that STDIN and STDOUT are not synchronized anymore
(probably due to the previous open STDOUT, "| tee logfile.txt"). --
and by synchronized I mean that the STDOUT buffer is flushed before
every read from STDIN.

How can I teach perl that STDOUT buffer is to be flushed before every
read from STDIN, even after an open STDOUT, "| tee logfile.txt".

I am on Ubuntu Linux:

This is perl, v5.10.1 built for i686-linux-thread-multi
(with 2 registered patches, see perl -V for more detail)
Copyright 1987-2009, Larry Wall
Binary build 1006 [291086] provided by ActiveState http://www.ActiveState.com
Built Aug 24 2009 13:45:03
From: J�rgen Exner on
Dilbert <dilbert1999(a)gmail.com> wrote:

>How can I teach perl that STDOUT buffer is to be flushed before every
>read from STDIN, even after an open STDOUT, "| tee logfile.txt".

What happened when you asked the FAQ?

perldoc -q flush
perldoc -q buffer

Of course this only tells perl to not buffer the output, your OS might
still do its own buffering.

jue
From: Dilbert on
On 12 jan, 17:15, Jürgen Exner <jurge...(a)hotmail.com> wrote:
> Dilbert <dilbert1...(a)gmail.com> wrote:
> >How can I teach perl that STDOUT buffer is to be flushed before every
> >read from STDIN, even after an open STDOUT, "| tee logfile.txt".
>
> What happened when you asked the FAQ?
>
>         perldoc -q flush
>         perldoc -q buffer
>
> Of course this only tells perl to not buffer the output, your OS might
> still do its own buffering.

The FAQ gave me an example with setting autoflush(1), ...
use IO::Handle;
open my( $io_fh ), ">", "output.txt";
$io_fh->autoflush(1);
.... but this disables buffering for the whole program, which is not
what I want, I just want to flush automatically before every read from
STDIN.

The other example from the FAQ is better...
$io_fh->flush;
....but still not satisfactory. In fact I would have to intervene in
the programs and add an STDOUT->flush before each read from STDIN.
It's a good solution, but I want something better.

From what I understand, Perl puts STDIN and STDOUT in a "special
relationship", such that STDOUT buffered under normal circumstances,
but is *automatically* flushed before each read from STDIN, no need to
manually flush using STDOUT->flush. The reason for that is that STDIN
and STDOUT are both connected to the same terminal.

Now, if I re-open STDOUT '| tee logfile.txt', Perl sees that STDOUT is
not connected anymore to the terminal and therefore it cancels the
"special relationship" between STDIN and STDOUT, the re-opened STDOUT
is *not* flushed automatically before each read from STDIN.

The point I make is that, yes, I re-open STDOUT to write to a flat
file, but I use a backdoor and re-connect it via the "tee" command
back to the terminal.

What I want in this case (where STDOUT is re-opened to a flat file and
then re-connected back to the terminal) is to establish the original
relationship between STDIN and STDOUT where STDOUT is *automatically*
flushed before each read from STDIN, no need to manually flush using
STDOUT->flush.
From: Jim Gibson on
In article
<7d8990a2-0f33-4f0c-8a5e-b93e1cfab286(a)m3g2000yqf.googlegroups.com>,
Dilbert <dilbert1999(a)gmail.com> wrote:

> On 12 jan, 17:15, J�rgen Exner <jurge...(a)hotmail.com> wrote:
> > Dilbert <dilbert1...(a)gmail.com> wrote:
> > >How can I teach perl that STDOUT buffer is to be flushed before every
> > >read from STDIN, even after an open STDOUT, "| tee logfile.txt".
> >
> > What happened when you asked the FAQ?
> >
> > � � � � perldoc -q flush
> > � � � � perldoc -q buffer
> >
> > Of course this only tells perl to not buffer the output, your OS might
> > still do its own buffering.
>

[problem with flushing output to screen before reading input snipped]

It is likely that it is the tee program that is doing the buffering and
needs to be flushed before input is read. Since this is not possible,
you should consider some alternative approach that does not use an
external program to duplicate output to the screen and a file.

How about writing a function that takes input and writes it to the
screen and a file?

This has been done before, so search at http://search.cpan.org for
"tee" and find modules such as File::Tee, IO::Tee, and PerlIO::tee. I
have not used any of these, so I don't know if they will work for you.

--
Jim Gibson
From: Peter J. Holzer on
On 2010-01-12 22:48, Jim Gibson <jimsgibson(a)gmail.com> wrote:
> [problem with flushing output to screen before reading input snipped]
>
> It is likely that it is the tee program that is doing the buffering and
> needs to be flushed before input is read.

No. tee doesn't buffer (at least not the implementations I'm familiar
with). Dilbert correctly (except that he erroneously calls a pipe a
"flat file", but that makes no difference in this context) the behaviour
required for stdio by the C standard. Apparently perlio emulates this
behaviour.

hp