/usr/share/perl5/IO/Tee.pm is in libio-tee-perl 0.64-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | package IO::Tee;
require 5.004;
use strict;
use Carp;
use Symbol;
use IO::Handle;
use IO::File;
use vars qw($VERSION @ISA);
$VERSION = '0.64';
@ISA = 'IO::Handle';
# Constructor -- bless array reference into our class
sub new
{
my $class = shift;
my $self = gensym;
@{*$self} = map {
! ref($_) ? IO::File->new($_)
: ref($_) eq 'ARRAY' ? IO::File->new(@$_)
: ref($_) eq 'GLOB' ? bless $_, 'IO::Handle'
: $_ or return undef } @_;
bless $self, $class;
tie *$self, $class, $self;
return $self;
}
# Return a list of all associated handles
sub handles
{
@{*{$_[0]}};
}
# Proxy routines for various IO::Handle and IO::File operations
sub _method_return_success
{
my $method = (caller(1))[3];
$method =~ s/.*:://;
my $self = shift;
my $ret = 1;
foreach my $fh (@{*$self}) { undef $ret unless $fh->$method(@_) }
return $ret;
}
sub close { _method_return_success(@_) }
sub truncate { _method_return_success(@_) }
sub write { _method_return_success(@_) }
sub syswrite { _method_return_success(@_) }
sub format_write { _method_return_success(@_) }
sub fcntl { _method_return_success(@_) }
sub ioctl { _method_return_success(@_) }
sub flush { _method_return_success(@_) }
sub clearerr { _method_return_success(@_) }
sub seek { _method_return_success(@_) }
sub formline
{
my $self = shift;
my $picture = shift;
local($^A) = $^A;
local($\) = "";
formline($picture, @_);
my $ret = 1;
foreach my $fh (@{*$self}) { undef $ret unless print $fh $^A }
return $ret;
}
sub _state_modify
{
my $method = (caller(1))[3];
$method =~ s/.*:://;
croak "$method values cannot be retrieved collectively" if @_ <= 1;
my $self = shift;
if (ref $self)
{
foreach my $fh (@{*$self}) { $fh->$method(@_) }
}
else
{
IO::Handle->$method(@_);
}
# Note that we do not return any "previous value" here
}
sub autoflush { _state_modify(@_) }
sub output_field_separator { _state_modify(@_) }
sub output_record_separator { _state_modify(@_) }
sub format_page_number { _state_modify(@_) }
sub format_lines_per_page { _state_modify(@_) }
sub format_lines_left { _state_modify(@_) }
sub format_name { _state_modify(@_) }
sub format_top_name { _state_modify(@_) }
sub format_line_break_characters { _state_modify(@_) }
sub format_formfeed { _state_modify(@_) }
sub input_record_separator
{
my $self = shift;
my $ret = (ref $self ? ${*$self}[0] : 'IO::Handle')
->input_record_separator(@_);
$ret; # This works around an apparent bug in Perl 5.004_04
}
sub input_line_number
{
my $self = shift;
my $ret = ${*$self}[0]->input_line_number(@_);
$ret; # This works around an apparent bug in Perl 5.004_04
}
# File handle tying interface
sub TIEHANDLE
{
my ($class, $self) = @_;
return bless *$self{ARRAY}, $class;
}
sub PRINT
{
my $self = shift;
my $ret = 1;
foreach my $fh (@$self) { undef $ret unless print $fh @_ }
return $ret;
}
sub PRINTF
{
my $self = shift;
my $fmt = shift;
my $ret = 1;
foreach my $fh (@$self) { undef $ret unless printf $fh $fmt, @_ }
return $ret;
}
sub _multiplex_input
{
my ($self, $input) = @_;
my $ret = 1;
if (length $input)
{
for (my $i = 1; $i < @$self; ++$i)
{
undef $ret unless print {$self->[$i]} $input;
}
}
$ret;
}
sub READ
{
my $self = shift;
my $bytes = $self->[0]->read(@_);
$bytes and $self->_multiplex_input(substr($_[0], $_[2], $bytes));
$bytes;
}
sub READLINE
{
my $self = shift;
my $infh = $self->[0];
if (wantarray)
{
my @data;
my $data;
while (defined($data = <$infh>) and length($data))
{
push @data, $data;
$self->_multiplex_input($data);
}
@data;
}
else
{
my $data = <$infh>;
defined $data and $self->_multiplex_input($data);
$data;
}
}
sub GETC
{
my $self = shift;
my $data = getc($self->[0]);
defined $data and $self->_multiplex_input($data);
$data;
}
sub sysread
{
my $self = shift;
my $bytes = ${*$self}[0]->sysread(@_);
$bytes and (\@{*$self})->
_multiplex_input(substr($_[0], $_[2] || 0, $bytes));
$bytes;
}
sub EOF
{
my $self = shift;
return $self->[0]->eof;
}
1;
__END__
=head1 NAME
IO::Tee - Multiplex output to multiple output handles
=head1 SYNOPSIS
use IO::Tee;
$tee = IO::Tee->new($handle1, $handle2);
print $tee "foo", "bar";
my $input = <$tee>;
=head1 DESCRIPTION
C<IO::Tee> objects can be used to multiplex input and output in two
different ways. The first way is to multiplex output to zero or more
output handles. The C<IO::Tee> constructor, given a list of output
handles, returns a tied handle that can be written to. When written
to (using print or printf), the C<IO::Tee> object multiplexes the
output to the list of handles originally passed to the constructor.
As a shortcut, you can also directly pass a string or an array
reference to the constructor, in which case C<IO::File::new> is called
for you with the specified argument or arguments.
The second way is to multiplex input from one input handle to zero or
more output handles as it is being read. The C<IO::Tee> constructor,
given an input handle followed by a list of output handles, returns a
tied handle that can be read from as well as written to. When written
to, the C<IO::Tee> object multiplexes the output to all handles passed
to the constructor, as described in the previous paragraph. When read
from, the C<IO::Tee> object reads from the input handle given as the
first argument to the C<IO::Tee> constructor, then writes any data
read to the output handles given as the remaining arguments to the
constructor.
The C<IO::Tee> class supports certain C<IO::Handle> and C<IO::File>
methods related to input and output. In particular, the following
methods will iterate themselves over all handles associated with the
C<IO::Tee> object, and return TRUE indicating success if and only if
all associated handles returned TRUE indicating success:
=over 4
=item close
=item truncate
=item write
=item syswrite
=item format_write
=item formline
=item fcntl
=item ioctl
=item flush
=item clearerr
=item seek
=back
The following methods perform input multiplexing as described above:
=over 4
=item read
=item sysread
=item readline
=item getc
=item gets
=item eof
=item getline
=item getlines
=back
The following methods can be used to set (but not retrieve) the
current values of output-related state variables on all associated
handles:
=over 4
=item autoflush
=item output_field_separator
=item output_record_separator
=item format_page_number
=item format_lines_per_page
=item format_lines_left
=item format_name
=item format_top_name
=item format_line_break_characters
=item format_formfeed
=back
The following methods are directly passed on to the input handle given
as the first argument to the C<IO::Tee> constructor:
=over 4
=item input_record_separator
=item input_line_number
=back
Note that the return value of input multiplexing methods (such as
C<print>) is always the return value of the input action, not the
return value of subsequent output actions. In particular, no error is
indicated by the return value if the input action itself succeeds but
subsequent output multiplexing fails.
=head1 EXAMPLE
use IO::Tee;
use IO::File;
my $tee = new IO::Tee(\*STDOUT,
new IO::File(">tt1.out"), ">tt2.out");
print join(' ', $tee->handles), "\n";
for (1..10) { print $tee $_, "\n" }
for (1..10) { $tee->print($_, "\n") }
$tee->flush;
$tee = new IO::Tee('</etc/passwd', \*STDOUT);
my @lines = <$tee>;
print scalar(@lines);
=head1 AUTHOR
Chung-chieh Shan, ken@digitas.harvard.edu
=head1 COPYRIGHT
Copyright (c) 1998-2001 Chung-chieh Shan. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=head1 SEE ALSO
L<perlfunc>, L<IO::Handle>, L<IO::File>.
=cut
|