I am trying to set up arbitrary pipelines from Perl, in much the same way as a shell might.
This has the desired effect, it's like "echo foo | sed s/oo/ar/":
#!/usr/bin/perl
use strict;
use IO::Handle;
$| = 1;
my ($first_prog, $second_prog) = ([qw(echo foo)], [qw(sed s/oo/ar/)]);
#$second_prog = ["less"];
pipe(my $second_prog_input, my $first_prog_output)
or die "problem setting up pipe: $!\n";
if (fork) {
STDOUT->fdopen(fileno($first_prog_output), 'w') or die;
exec(@$first_prog) or die;
}
else {
STDIN->fdopen(fileno($second_prog_input), 'r') or die;
exec(@$second_prog) or
die "couldn't exec: $!: command was @$first_prog\n";
}
However, when I make the second argument "less", my terminal flashes, and I don't see the output in the pager. Other than the brief flash, there is no sign of less running at all.
Now something I don't get at all is that the following does behave like "echo foo | less":
pipe(my $first_prog_output, STDIN) or die "problem setting up pipe: $!\n";
my ($first_prog, $second_prog) = ([qw(echo foo)], ["less"]);
open($first_prog_output, "-|", @$first_prog) or
die "$!: command was @$first_prog\n";
exec(@$second_prog) or
die "couldn't exec: $!: command was @$first_prog\n";
But I don't understand at all what that call to pipe() is doing. The first argument is supposed to be a "reader", and the second one a "writer". How is STDIN a "writer"?
I'm very confused by all this, and think there may be something fundamental about the underlying Unix API that I'm missing or I've forgotten.