Less Perl Pipeline Works

I am trying to configure arbitrary pipelines from Perl, in much the same way as the shell.

This has the desired effect, it is 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 blinks and I do not see the output in the pager. In addition to a brief flash, there are no signs of less running.

Now, something that I am not getting is that the following behavior behaves 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 what this call to pipe () does. The first argument must be a "reader", and the second - a "writer". How is STDIN a "writer"?

I am very confused by this and I think that there might be something fundamental regarding the basic Unix API that I am missing or I forgot.

+6
source share
1 answer

This is an interesting question of time:

  • Fork Shell, creates a process group, sets the foreground group of the terminal and execs perl .
  • perl forks and execs less .
  • perl execs echo .
  • echo exits, the shell believes that the task has been completed and is installed again as a group of foreground processes.
  • less trying to get the terminal. It is not in the terminal foreground process group. less does not work.

The simplest solution: change fork to !fork (or, equivalently, replace if and else blocks). Thus, the final stage of the pipeline determines the service life of the job. (If you watch closely, then the shell forks and execs are processed in the same order as it also starts the pipeline.)

+6
source

Source: https://habr.com/ru/post/921252/


All Articles