Skip to content

Commit fa32a1e

Browse files
authored
tee: add strict (#684)
* Correct left-over reference to variable $unbuffer * Remove custom SIGPIPE code which doesn't exist in the BSD version (the only reference to signals is SIGINT being ignored) * Standards document mentions nothing about SIGPIPE in Asynchronous Events section[1] * Output files table (%fh) is now keyed based on file descriptor and contains filehandle and the saved filename from ARGV * Explicitly check for directory before opening a file * test1: "ifconfig | perl tee out.1" --> out.1 created * test2: "ifconfig | perl tee -a out.1 out.2" --> existing out.1 appended, out.2 created 1. https://pubs.opengroup.org/onlinepubs/009696699/utilities/tee.html
1 parent 21fd9b4 commit fa32a1e

File tree

1 file changed

+29
-16
lines changed

1 file changed

+29
-16
lines changed

bin/tee

+29-16
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,57 @@ License: perl
1717
# Tom Christiansen <tchrist@convex.com>
1818
# 6 June 91
1919

20+
use strict;
21+
2022
use Getopt::Std qw(getopts);
23+
use IO::File;
2124

2225
my %opt;
2326
getopts('aiu', \%opt) or die "usage: tee [-aiu] [file ...]\n";
2427
$SIG{'INT'} = 'IGNORE' if $opt{'i'};
25-
$SIG{'PIPE'} = 'PLUMBER';
2628
$| = 1 if $opt{'u'};
2729

28-
my $mode = $opt{'a'} ? '>>' : '>';
29-
my $fh = 'FH000';
30-
my %fh = ('STDOUT', 'standard output'); # always go to stdout
30+
my $mode = $opt{'a'} ? 'a' : 'w';
3131
my $status = 0;
32+
my $default_fd = fileno(*STDOUT);
33+
my %fh = ($default_fd => {
34+
'name' => 'standard output',
35+
'fh' => *STDOUT,
36+
});
3237

3338
for (@ARGV) {
34-
if (!open($fh, $mode, $_)) {
39+
if (-d $_) {
40+
warn "$0: '$_' is a directory\n";
41+
$status++;
42+
next;
43+
}
44+
my $fh = IO::File->new($_, $mode);
45+
unless (defined $fh) {
3546
warn "$0: cannot open $_: $!\n"; # like sun's; i prefer die
3647
$status++;
3748
next;
3849
}
39-
select((select($fh), $| = 1)[0]) if $unbuffer;
40-
$fh{$fh++} = $_;
50+
select((select($fh), $| = 1)[0]) if $opt{'u'};
51+
my $fd = fileno($fh);
52+
$fh{$fd}->{'name'} = $_;
53+
$fh{$fd}->{'fh'} = $fh;
4154
}
4255
while (<STDIN>) {
43-
for my $fh (keys %fh) {
56+
for my $fh (get_filehandles()) {
4457
print {$fh} $_;
4558
}
4659
}
47-
for my $fh (keys %fh) {
48-
next if close($fh) || !defined $fh{$fh};
49-
warn "$0: couldn't close $fh{$fh}: $!\n";
50-
$status++;
60+
for my $fd (keys %fh) {
61+
unless (close $fh{$fd}->{'fh'}) {
62+
warn sprintf("%s: close '%s': %s\n", $0, $fh{$fd}->{'name'}, $!);
63+
$status++;
64+
}
5165
}
5266
exit $status;
5367

54-
sub PLUMBER {
55-
warn "$0: pipe to \"$fh{$fh}\" broke!\n";
56-
$status++;
57-
delete $fh{$fh};
68+
sub get_filehandles {
69+
my @handles = map { $fh{$_}->{'fh'} } (keys %fh);
70+
return @handles;
5871
}
5972

6073
=encoding utf8

0 commit comments

Comments
 (0)