#! /usr/bin/perl # usage: ytee [-r irs] { command | - } [filter ..] use strict; if($ARGV[0] =~ /^-r(.+)?/){ shift; $/ = eval($1 // shift); die $@ if $@ } elsif(! -t STDIN){ $/ = \0x8000 } my $cmd = shift; my @cl; for(@ARGV){ use IPC::Open2; my $pid = open2 my $from, my $to, $_; push @cl, [$from, $to, $pid]; } defined(my $pid = fork) or die "fork: $!"; if($pid){ delete $$_[0] for @cl; $SIG{PIPE} = 'IGNORE'; my ($s, $n); while(<STDIN>){ for my $c (@cl){ next unless exists $$c[1]; syswrite($$c[1], $_) ? $n++ : delete $$c[1] } last unless $n; } delete $$_[1] for @cl; while((my $p = wait) > 0){ $s += !!$? << ($p != $pid) } exit $s; } delete $$_[1] for @cl; if($cmd eq '-'){ my $n; do { $n = 0; for my $c (@cl){ next unless exists $$c[0]; if(my $d = readline $$c[0]){ print $d; $n++ } else{ delete $$c[0] } } } while $n; }else{ exec join ' ', $cmd, map { use Fcntl; fcntl $$_[0], F_SETFD, fcntl($$_[0], F_GETFD, 0) & ~FD_CLOEXEC; '/dev/fd/'.fileno $$_[0] } @cl; die "exec $cmd: $!"; }