Reading from stdin then launching a program that reads from stdin strange behaviour

Discussion in 'Perl Misc' started by Stefano Sabatini, Jul 27, 2007.

  1. Hi all perlers,

    I'm writing a perl script which reads from stdin, then launch an
    interactive session of gnuplot. I'm on a gnu-linux system, perl 5.8.

    The simplified code looks like this:

    #! /usr/bin/perl

    # reads from stdin, then lauch interactively gnuplot

    open(FH, "/dev/stdin");
    # filter stdin
    while (<FH>) {
    ;
    }
    close(FH);

    print "Launching gnuplot...\n";
    # and now launch a gnuplot interactive session
    system "gnuplot -";

    If I feed the script with a file, like this:
    cat file.txt | perl gnuplot-launcher.pl

    gnuplot exits immediately from the interactive session.

    If I filter a regular file (like "file.txt") or type interactively on
    stdin like this:
    cat - | gnuplot-launcher.pl
    I'm writing
    interactively
    on
    stdin
    ^D

    then the gnuplot interactive mode seems to work.

    All I want to do is to be able to access to an interactive session of
    gnuplot from perl, but I'm evidently missing something.

    Many thanks in advance.
    Cheers.
    --
    Stefano Sabatini
    Linux user number 337176 (see http://counter.li.org)
     
    Stefano Sabatini, Jul 27, 2007
    #1
    1. Advertising

  2. Stefano Sabatini

    Mumia W. Guest

    Re: Reading from stdin then launching a program that reads from stdinstrange behaviour

    On 07/27/2007 05:50 AM, Stefano Sabatini wrote:
    > Hi all perlers,
    >
    > I'm writing a perl script which reads from stdin, then launch an
    > interactive session of gnuplot. I'm on a gnu-linux system, perl 5.8.
    >
    > The simplified code looks like this:
    >
    > #! /usr/bin/perl
    >
    > # reads from stdin, then lauch interactively gnuplot
    >
    > open(FH, "/dev/stdin");
    > # filter stdin
    > while (<FH>) {
    > ;
    > }
    > close(FH);
    >
    > print "Launching gnuplot...\n";
    > # and now launch a gnuplot interactive session
    > system "gnuplot -";
    >
    > If I feed the script with a file, like this:
    > cat file.txt | perl gnuplot-launcher.pl
    >
    > gnuplot exits immediately from the interactive session.
    >
    > If I filter a regular file (like "file.txt") or type interactively on
    > stdin like this:
    > cat - | gnuplot-launcher.pl
    > I'm writing
    > interactively
    > on
    > stdin
    > ^D
    >
    > then the gnuplot interactive mode seems to work.
    >
    > All I want to do is to be able to access to an interactive session of
    > gnuplot from perl, but I'm evidently missing something.
    >
    > Many thanks in advance.
    > Cheers.


    You don't provide enough detail about what you're trying to do, but I
    suspect that you can just use 'open' to launch gnuplot:

    open (GNUPLOT, "|-", "gnuplot") or die("blah blah");
    print GNUPLOT "plot blah blah blah...\n";
    close GNUPLOT or die("blah blah");

    Read up on the open command: perldoc -f open. If you need more
    complicated interactions with gnuplot (not likely), you might consider
    using Expect.pm.
     
    Mumia W., Jul 27, 2007
    #2
    1. Advertising

  3. Stefano Sabatini

    Klaus Guest

    On Jul 27, 12:50 pm, Stefano Sabatini <>
    wrote:
    > I'm writing a perl script which reads from stdin, then launch an
    > interactive session of gnuplot.


    > open(FH, "/dev/stdin");
    > # filter stdin
    > while (<FH>) {
    > ;}
    >
    > close(FH);


    So far so good, but at this point, after closing FH, you should also
    close STDIN:

    close STDIN;

    Now, before launching an interactive application, you want to re-open
    STDIN:

    open STDIN, '<&1' or die "Error open STDIN: $!";

    > print "Launching gnuplot...\n";
    > # and now launch a gnuplot interactive session
    > system "gnuplot -";


    --
    Klaus
     
    Klaus, Jul 28, 2007
    #3
  4. On 2007-07-27, Klaus <> wrote:
    > On Jul 27, 12:50 pm, Stefano Sabatini <>
    > wrote:
    >> I'm writing a perl script which reads from stdin, then launch an
    >> interactive session of gnuplot.

    >
    >> open(FH, "/dev/stdin");
    >> # filter stdin
    >> while (<FH>) {
    >> ;}
    >>
    >> close(FH);

    >
    > So far so good, but at this point, after closing FH, you should also
    > close STDIN:
    >
    > close STDIN;
    >
    > Now, before launching an interactive application, you want to re-open
    > STDIN:
    >
    > open STDIN, '<&1' or die "Error open STDIN: $!";
    >
    >> print "Launching gnuplot...\n";
    >> # and now launch a gnuplot interactive session
    >> system "gnuplot -";


    Thank you guys, you saved my day!

    Here it is the complete solution.

    -----------------------------
    while (<>) {
    ;
    }
    close (STDIN);
    open STDIN, '<&1' or die "Error open STDIN: $!";
    system("gnuplot", "-");
    ------------------------------

    Cheers!
    --
    Stefano Sabatini
    Linux user number 337176 (see http://counter.li.org)
     
    Stefano Sabatini, Jul 28, 2007
    #4
  5. Re: Reading from stdin then launching a program that reads fromstdin strange behaviour

    On 2007-07-27 10:50, Stefano Sabatini <> wrote:
    > I'm writing a perl script which reads from stdin, then launch an
    > interactive session of gnuplot. I'm on a gnu-linux system, perl 5.8.

    [...]
    > If I feed the script with a file, like this:
    > cat file.txt | perl gnuplot-launcher.pl
    >
    > gnuplot exits immediately from the interactive session.
    >
    > If I filter a regular file (like "file.txt") or type interactively on
    > stdin like this:
    > cat - | gnuplot-launcher.pl
    > I'm writing
    > interactively
    > on
    > stdin
    > ^D
    >
    > then the gnuplot interactive mode seems to work.


    I don't see how this can work. It's completely equivalent to the
    previous example, as far as gnuplot-launcher.pl is concerned:

    cat reads from stdin until it a read returns 0 bytes (this happens on
    EOF on a file, or when the user types ^D on a terminal). It copies all
    input to the pipe, then exits.

    gnuplot-launcher.pl reads from the pipe until the write-end of the pipe
    is closed (i.e. cat has exited). Then it launches "gnuplot -", which
    will still try to read from a pipe with no writer, so it gets EOF
    immediately and exits.

    Now invoking gnuplot-launcher.pl with stdin from a terminal is a bit
    different. In this case it will read until the user presses ^D, then
    launch gnuplot, which will again run until the user presses ^D. This is
    because a terminal doesn't really have an "end of file", it can only
    return 0 bytes to a read which is interpreted as end of file by most
    programs - and it can do that as often as necessary, of course.

    > All I want to do is to be able to access to an interactive session of
    > gnuplot from perl, but I'm evidently missing something.


    open(STDIN, '<', '/dev/tty') or die "cannot open /dev/tty: $!";

    should work if the process has a controlling tty (otherwise it gets
    tricky: You could start gnuplot in an xterm if $DISPLAY is set).

    hp


    --
    _ | Peter J. Holzer | I know I'd be respectful of a pirate
    |_|_) | Sysadmin WSR | with an emu on his shoulder.
    | | | |
    __/ | http://www.hjp.at/ | -- Sam in "Freefall"
     
    Peter J. Holzer, Jul 28, 2007
    #5
  6. Re: Reading from stdin then launching a program that reads fromstdin strange behaviour

    On 2007-07-27 23:45, Klaus <> wrote:
    > On Jul 27, 12:50 pm, Stefano Sabatini <>
    > wrote:
    >> I'm writing a perl script which reads from stdin, then launch an
    >> interactive session of gnuplot.

    >
    > Now, before launching an interactive application, you want to re-open
    > STDIN:
    >
    > open STDIN, '<&1' or die "Error open STDIN: $!";


    You are duplicating STDIN from STDOUT here. It is not guaranteed that
    STDOUT is readable. Consider:

    ../gnuplot-launcher < foo > bar

    hp


    --
    _ | Peter J. Holzer | I know I'd be respectful of a pirate
    |_|_) | Sysadmin WSR | with an emu on his shoulder.
    | | | |
    __/ | http://www.hjp.at/ | -- Sam in "Freefall"
     
    Peter J. Holzer, Jul 28, 2007
    #6
  7. On 2007-07-28, Peter J. Holzer <> wrote:
    > On 2007-07-27 10:50, Stefano Sabatini <> wrote:
    >> I'm writing a perl script which reads from stdin, then launch an
    >> interactive session of gnuplot. I'm on a gnu-linux system, perl 5.8.

    > [...]
    >> If I feed the script with a file, like this:
    >> cat file.txt | perl gnuplot-launcher.pl
    >>
    >> gnuplot exits immediately from the interactive session.
    >>
    >> If I filter a regular file (like "file.txt") or type interactively on
    >> stdin like this:
    >> cat - | gnuplot-launcher.pl
    >> I'm writing
    >> interactively
    >> on
    >> stdin
    >> ^D
    >>
    >> then the gnuplot interactive mode seems to work.

    >
    > I don't see how this can work. It's completely equivalent to the
    > previous example, as far as gnuplot-launcher.pl is concerned:


    Yes you're right, indeed I tried it again and it didn't work, sorry
    for my error.

    > cat reads from stdin until it a read returns 0 bytes (this happens on
    > EOF on a file, or when the user types ^D on a terminal). It copies all
    > input to the pipe, then exits.
    >
    > gnuplot-launcher.pl reads from the pipe until the write-end of the pipe
    > is closed (i.e. cat has exited). Then it launches "gnuplot -", which
    > will still try to read from a pipe with no writer, so it gets EOF
    > immediately and exits.
    >
    > Now invoking gnuplot-launcher.pl with stdin from a terminal is a bit
    > different. In this case it will read until the user presses ^D, then
    > launch gnuplot, which will again run until the user presses ^D. This is
    > because a terminal doesn't really have an "end of file", it can only
    > return 0 bytes to a read which is interpreted as end of file by most
    > programs - and it can do that as often as necessary, of course.
    >
    >> All I want to do is to be able to access to an interactive session of
    >> gnuplot from perl, but I'm evidently missing something.

    >
    > open(STDIN, '<', '/dev/tty') or die "cannot open /dev/tty: $!";
    >
    > should work if the process has a controlling tty (otherwise it gets
    > tricky: You could start gnuplot in an xterm if $DISPLAY is set).


    Thank you Peter for the indepth analysis, using /dev/tty seems like a
    good idea.

    I think the key to understand the problem is to understand how a perl
    script interprets its input.

    In the case:
    cat - | filter.pl

    (or more in general in the case prog | filter.pl) the input is the
    pipe output of the program which feeds the input pipe, when it sends
    EOF then the STDIN filehandler is closed, and other reads from it are
    doomed to get an immediate EOF and exit.

    In the case:
    filter.pl

    STDIN is defined as a sort of alias to /dev/tty if the script is
    launched in a terminal, and the script reads from it up to the first
    ^D, but doesn't close it afterwhile, so successive reads will result
    in accepting the input from the terminal (interactively typed by the
    user).

    In the case of the gnuplot-launcher.pl the correct solution seems to
    me:

    # diamond operator: reads from input, which can be both the output end
    # of a pipe, a file specified in @ARGV, or /dev/tty
    while (<>) {
    print $_;
    }
    # at this point it could close STDIN, in the case it is the output end
    # of a pipe, and successive reads will fail.

    # we need to redefine STDIN as the terminal ouput, since
    # gnuplot inherits the STDIN filehandler from his parent,
    # the perl script
    open (STDIN, "</dev/tty") or die "Cannot open /dev/tty";
    system("gnuplot -") == 0 or die "Gnuplot error...: $!"

    This works in both the "prog | gnuplot-launcher.pl" and
    "gnuplot-launcher.pl" or "gnuplot-launcher.pl file" case.

    Hope my analisys is not too far from the truth.
    Thank you all for your help.

    Cheers!
    --
    Stefano Sabatini
    Linux user number 337176 (see http://counter.li.org)
     
    Stefano Sabatini, Jul 29, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    485
    Roedy Green
    Mar 28, 2006
  2. barr
    Replies:
    3
    Views:
    1,128
    Miki Tebeka
    Dec 28, 2004
  3. Antoon Pardon

    pep 3116 behaviour on non-blocking reads

    Antoon Pardon, Aug 9, 2007, in forum: Python
    Replies:
    1
    Views:
    260
  4. Replies:
    0
    Views:
    297
  5. Timo Schmiade

    Reading from stdin first, then use curses

    Timo Schmiade, Aug 11, 2013, in forum: Python
    Replies:
    0
    Views:
    103
    Timo Schmiade
    Aug 11, 2013
Loading...

Share This Page