#!/usr/bin/perl use strict; use warnings; use Fcntl; use POSIX; use constant READSZ => 1024; if (@ARGV != 2 && @ARGV != 3) { die "Usage: demarcate STDOUT-FIFO STDERR-FIFO [ TPUT COMMAND ]\n"; } my $stdout_path = shift @ARGV; my $stderr_path = shift @ARGV; my $tput_cmd = shift @ARGV; my ($aseq, $bseq); if (defined $tput_cmd) { $aseq = `tput $tput_cmd`; } else { $aseq = `tput bold`; } $bseq = `tput sgr0`; chomp $aseq; chomp $bseq; sysopen my $stdout_fh, $stdout_path, O_RDONLY or die "$0: $stdout_path: $!"; sysopen my $stderr_fh, $stderr_path, O_RDONLY or die "$0: $stderr_path: $!"; fcntl $stdout_fh, F_SETFL, O_NONBLOCK or die "$0: nonblock $stdout_path: $!"; fcntl $stderr_fh, F_SETFL, O_NONBLOCK or die "$0: nonblock $stderr_path: $!"; my ($stdout_dead, $stderr_dead); my $in_stderr; my $read; my $buffer; my $rfh = ''; vec($rfh,fileno($stdout_fh),1) = 1; vec($rfh,fileno($stderr_fh),1) = 1; my ($rout, $wout, $eout); $| = 1; while (! ($stdout_dead && $stderr_dead)) { select $rout=$rfh, $wout='', $eout=$rfh, undef; $read = sysread $stdout_fh, $buffer, READSZ unless $stdout_dead; unless (defined $read) { die "$0: read $stdout_path: $!" unless $!{'EAGAIN'}; } elsif ($read > 0) { if ($in_stderr) { print "$bseq"; undef $in_stderr; } printf $buffer; } else { $stdout_dead = 1; } $read = sysread $stderr_fh, $buffer, READSZ unless $stderr_dead; unless (defined $read) { die "$0: read $stderr_path: $!" unless $!{'EAGAIN'}; } elsif ($read > 0) { unless ($in_stderr) { print "$aseq"; $in_stderr = 1; } printf $buffer; } else { $stderr_dead = 1; } }