File Coverage

blib/lib/IPC/Run/IO.pm
Criterion Covered Total %
statement 183 190 96.3
branch 79 118 66.9
condition 19 40 47.5
subroutine 29 29 100.0
pod 12 12 100.0
total 322 389 82.7


line stmt bran cond sub pod time code
1             package IPC::Run::IO;
2              
3             =head1 NAME
4              
5             IPC::Run::IO -- I/O channels for IPC::Run.
6              
7             =head1 SYNOPSIS
8              
9             B
10             normal file descriptors; IPC::RUN::IO needs to use IPC::Run::Win32Helper
11             to do this.>
12              
13             use IPC::Run qw( io );
14              
15             ## The sense of '>' and '<' is opposite of perl's open(),
16             ## but agrees with IPC::Run.
17             $io = io( "filename", '>', \$recv );
18             $io = io( "filename", 'r', \$recv );
19              
20             ## Append to $recv:
21             $io = io( "filename", '>>', \$recv );
22             $io = io( "filename", 'ra', \$recv );
23              
24             $io = io( "filename", '<', \$send );
25             $io = io( "filename", 'w', \$send );
26              
27             $io = io( "filename", '<<', \$send );
28             $io = io( "filename", 'wa', \$send );
29              
30             ## Handles / IO objects that the caller opens:
31             $io = io( \*HANDLE, '<', \$send );
32              
33             $f = IO::Handle->new( ... ); # Any subclass of IO::Handle
34             $io = io( $f, '<', \$send );
35              
36             require IPC::Run::IO;
37             $io = IPC::Run::IO->new( ... );
38              
39             ## Then run(), harness(), or start():
40             run $io, ...;
41              
42             ## You can, of course, use io() or IPC::Run::IO->new() as an
43             ## argument to run(), harness, or start():
44             run io( ... );
45              
46             =head1 DESCRIPTION
47              
48             This class and module allows filehandles and filenames to be harnessed for
49             I/O when used IPC::Run, independent of anything else IPC::Run is doing
50             (except that errors & exceptions can affect all things that IPC::Run is
51             doing).
52              
53             =head1 SUBCLASSING
54              
55             INCOMPATIBLE CHANGE: due to the awkwardness introduced in ripping pseudohashes
56             out of Perl, this class I uses the fields pragma.
57              
58             =cut
59              
60             ## This class is also used internally by IPC::Run in a very intimate way,
61             ## since this is a partial factoring of code from IPC::Run plus some code
62             ## needed to do standalone channels. This factoring process will continue
63             ## at some point. Don't know how far how fast.
64              
65 117     117   819 use strict;
  117         243  
  117         3956  
66 117     117   593 use Carp;
  117         227  
  117         6495  
67 117     117   744 use Fcntl;
  117         262  
  117         23281  
68 117     117   721 use Symbol;
  117         226  
  117         5554  
69              
70 117     117   622 use IPC::Run::Debug;
  117         231  
  117         7164  
71 117     117   1545 use IPC::Run qw( Win32_MODE );
  117         219  
  117         7353  
72              
73 117     117   765 use vars qw{$VERSION};
  117         188  
  117         11093  
74              
75             BEGIN {
76 117     117   647 $VERSION = '20200505.0';
77 117 50       239608 if (Win32_MODE) {
78 0 0 0     0 eval "use IPC::Run::Win32Helper; require IPC::Run::Win32IO; 1"
      0        
79             or ( $@ && die )
80             or die "$!";
81             }
82             }
83              
84             sub _empty($);
85             *_empty = \&IPC::Run::_empty;
86              
87             =head1 SUBROUTINES
88              
89             =over 4
90              
91             =item new
92              
93             I think it takes >> or << along with some other data.
94              
95             TODO: Needs more thorough documentation. Patches welcome.
96              
97             =cut
98              
99             sub new {
100 7     7 1 15 my $class = shift;
101 7   33     29 $class = ref $class || $class;
102              
103 7         15 my ( $external, $type, $internal ) = ( shift, shift, pop );
104              
105 7 50       42 croak "$class: '$_' is not a valid I/O operator"
106             unless $type =~ /^(?:<>?)$/;
107              
108 7         22 my IPC::Run::IO $self = $class->_new_internal( $type, undef, undef, $internal, undef, @_ );
109              
110 7 50 0     15 if ( !ref $external ) {
    0          
111 7         15 $self->{FILENAME} = $external;
112             }
113             elsif ( ref $external eq 'GLOB' || UNIVERSAL::isa( $external, 'IO::Handle' ) ) {
114 0         0 $self->{HANDLE} = $external;
115 0         0 $self->{DONT_CLOSE} = 1;
116             }
117             else {
118 0         0 croak "$class: cannot accept " . ref($external) . " to do I/O with";
119             }
120              
121 7         28 return $self;
122             }
123              
124             ## IPC::Run uses this ctor, since it preparses things and needs more
125             ## smarts.
126             sub _new_internal {
127 2444     2444   5950 my $class = shift;
128 2444   33     13891 $class = ref $class || $class;
129              
130 2444 50 33     9636 $class = "IPC::Run::Win32IO"
131             if Win32_MODE && $class eq "IPC::Run::IO";
132              
133 2444         3900 my IPC::Run::IO $self;
134 2444         6413 $self = bless {}, $class;
135              
136 2444         11256 my ( $type, $kfd, $pty_id, $internal, $binmode, @filters ) = @_;
137              
138             # Older perls (<=5.00503, at least) don't do list assign to
139             # psuedo-hashes well.
140 2444         8607 $self->{TYPE} = $type;
141 2444         6198 $self->{KFD} = $kfd;
142 2444         5403 $self->{PTY_ID} = $pty_id;
143 2444         9558 $self->binmode($binmode);
144 2444         6729 $self->{FILTERS} = [@filters];
145              
146             ## Add an adapter to the end of the filter chain (which is usually just the
147             ## read/writer sub pushed by IPC::Run) to the DEST or SOURCE, if need be.
148 2444 100       7600 if ( $self->op =~ />/ ) {
149 1543 50       5608 croak "'$_' missing a destination" if _empty $internal;
150 1543         5816 $self->{DEST} = $internal;
151 1543 100       6326 if ( UNIVERSAL::isa( $self->{DEST}, 'CODE' ) ) {
152             ## Put a filter on the end of the filter chain to pass the
153             ## output on to the CODE ref. For SCALAR refs, the last
154             ## filter in the chain writes directly to the scalar itself. See
155             ## _init_filters(). For CODE refs, however, we need to adapt from
156             ## the SCALAR to calling the CODE.
157             unshift(
158 98         877 @{ $self->{FILTERS} },
159             sub {
160 182     182   461 my ($in_ref) = @_;
161              
162 182   66     574 return IPC::Run::input_avail() && do {
163             $self->{DEST}->($$in_ref);
164             $$in_ref = '';
165             1;
166             }
167             }
168 98         150 );
169             }
170             }
171             else {
172 901 50       3492 croak "'$_' missing a source" if _empty $internal;
173 901         2816 $self->{SOURCE} = $internal;
174 901 100       5861 if ( UNIVERSAL::isa( $internal, 'CODE' ) ) {
    100          
175             push(
176 68         1323 @{ $self->{FILTERS} },
177             sub {
178 82     82   1114 my ( $in_ref, $out_ref ) = @_;
179 82 50       658 return 0 if length $$out_ref;
180              
181             return undef
182 82 50       723 if $self->{SOURCE_EMPTY};
183              
184 82         841 my $in = $internal->();
185 82 100       1303 unless ( defined $in ) {
186 46         298 $self->{SOURCE_EMPTY} = 1;
187 46         370 return undef;
188             }
189 36 100       674 return 0 unless length $in;
190 29         423 $$out_ref = $in;
191              
192 29         295 return 1;
193             }
194 68         140 );
195             }
196             elsif ( UNIVERSAL::isa( $internal, 'SCALAR' ) ) {
197             push(
198 558         9231 @{ $self->{FILTERS} },
199             sub {
200 1759     1759   8741 my ( $in_ref, $out_ref ) = @_;
201 1759 50       8387 return 0 if length $$out_ref;
202              
203             ## pump() clears auto_close_ins, finish() sets it.
204             return $self->{HARNESS}->{auto_close_ins} ? undef : 0
205 1759         10948 if IPC::Run::_empty ${ $self->{SOURCE} }
206 1759 100 100     2989 || $self->{SOURCE_EMPTY};
    100          
207              
208 366         3740 $$out_ref = $$internal;
209 109         618 eval { $$internal = '' }
210 366 100       2308 if $self->{HARNESS}->{clear_ins};
211              
212 366         1639 $self->{SOURCE_EMPTY} = $self->{HARNESS}->{auto_close_ins};
213              
214 366         1739 return 1;
215             }
216 558         989 );
217             }
218             }
219              
220 2444         8053 return $self;
221             }
222              
223             =item filename
224              
225             Gets/sets the filename. Returns the value after the name change, if
226             any.
227              
228             =cut
229              
230             sub filename {
231 4     4 1 6 my IPC::Run::IO $self = shift;
232 4 50       9 $self->{FILENAME} = shift if @_;
233 4         14 return $self->{FILENAME};
234             }
235              
236             =item init
237              
238             Does initialization required before this can be run. This includes open()ing
239             the file, if necessary, and clearing the destination scalar if necessary.
240              
241             =cut
242              
243             sub init {
244 2     2 1 3 my IPC::Run::IO $self = shift;
245              
246 2         6 $self->{SOURCE_EMPTY} = 0;
247 1         3 ${ $self->{DEST} } = ''
248 2 100 66     6 if $self->mode =~ /r/ && ref $self->{DEST} eq 'SCALAR';
249              
250 2 50       7 $self->open if defined $self->filename;
251 2         8 $self->{FD} = $self->fileno;
252              
253 2 50       6 if ( !$self->{FILTERS} ) {
254 0         0 $self->{FBUFS} = undef;
255             }
256             else {
257 2         7 @{ $self->{FBUFS} } = map {
258 3         7 my $s = "";
259 3         7 \$s;
260 2         5 } ( @{ $self->{FILTERS} }, '' );
  2         14  
261              
262             $self->{FBUFS}->[0] = $self->{DEST}
263 2 100 66     10 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
264 2         4 push @{ $self->{FBUFS} }, $self->{SOURCE};
  2         4  
265             }
266              
267 2         7 return undef;
268             }
269              
270             =item open
271              
272             If a filename was passed in, opens it. Determines if the handle is open
273             via fileno(). Throws an exception on error.
274              
275             =cut
276              
277             my %open_flags = (
278             '>' => O_RDONLY,
279             '>>' => O_RDONLY,
280             '<' => O_WRONLY | O_CREAT | O_TRUNC,
281             '<<' => O_WRONLY | O_CREAT | O_APPEND,
282             );
283              
284             sub open {
285 2     2 1 10 my IPC::Run::IO $self = shift;
286              
287             croak "IPC::Run::IO: Can't open() a file with no name"
288 2 50       7 unless defined $self->{FILENAME};
289 2 50       20 $self->{HANDLE} = gensym unless $self->{HANDLE};
290              
291 2 50       76 _debug "opening '", $self->filename, "' mode '", $self->mode, "'"
292             if _debugging_data;
293             sysopen(
294             $self->{HANDLE},
295             $self->filename,
296 2 50       6 $open_flags{ $self->op },
297             ) or croak "IPC::Run::IO: $! opening '$self->{FILENAME}', mode '" . $self->mode . "'";
298              
299 2         10 return undef;
300             }
301              
302             =item open_pipe
303              
304             If this is a redirection IO object, this opens the pipe in a platform
305             independent manner.
306              
307             =cut
308              
309             sub _do_open {
310 1921     1921   3061 my $self = shift;
311 1921         4695 my ( $child_debug_fd, $parent_handle ) = @_;
312              
313 1921 100       5611 if ( $self->dir eq "<" ) {
314 640         4074 ( $self->{TFD}, $self->{FD} ) = IPC::Run::_pipe_nb;
315 640 100       3932 if ($parent_handle) {
316 28 50       700 CORE::open $parent_handle, ">&=$self->{FD}"
317             or croak "$! duping write end of pipe for caller";
318             }
319             }
320             else {
321 1281         8379 ( $self->{FD}, $self->{TFD} ) = IPC::Run::_pipe;
322 1281 100       4582 if ($parent_handle) {
323 52 50       6048 CORE::open $parent_handle, "<&=$self->{FD}"
324             or croak "$! duping read end of pipe for caller";
325             }
326             }
327             }
328              
329             sub open_pipe {
330 1921     1921 1 3665 my IPC::Run::IO $self = shift;
331              
332             ## Hmmm, Maybe allow named pipes one day. But until then...
333             croak "IPC::Run::IO: Can't pipe() when a file name has been set"
334 1921 50       5244 if defined $self->{FILENAME};
335              
336 1921         7101 $self->_do_open(@_);
337              
338             ## return ( child_fd, parent_fd )
339             return $self->dir eq "<"
340             ? ( $self->{TFD}, $self->{FD} )
341 1921 100       5983 : ( $self->{FD}, $self->{TFD} );
342             }
343              
344             sub _cleanup { ## Called from Run.pm's _cleanup
345 2143     2143   4643 my $self = shift;
346 2143         11911 undef $self->{FAKE_PIPE};
347             }
348              
349             =item close
350              
351             Closes the handle. Throws an exception on failure.
352              
353              
354             =cut
355              
356             sub close {
357 1671     1671 1 3840 my IPC::Run::IO $self = shift;
358              
359 1671 100       5139 if ( defined $self->{HANDLE} ) {
360             close $self->{HANDLE}
361             or croak(
362             "IPC::Run::IO: $! closing "
363             . (
364             defined $self->{FILENAME}
365 2 0       36 ? "'$self->{FILENAME}'"
    50          
366             : "handle"
367             )
368             );
369             }
370             else {
371 1669         5590 IPC::Run::_close( $self->{FD} );
372             }
373              
374 1671         4618 $self->{FD} = undef;
375              
376 1671         4031 return undef;
377             }
378              
379             =item fileno
380              
381             Returns the fileno of the handle. Throws an exception on failure.
382              
383              
384             =cut
385              
386             sub fileno {
387 4     4 1 7 my IPC::Run::IO $self = shift;
388              
389 4         11 my $fd = fileno $self->{HANDLE};
390             croak(
391             "IPC::Run::IO: $! "
392             . (
393             defined $self->{FILENAME}
394 4 0       10 ? "'$self->{FILENAME}'"
    50          
395             : "handle"
396             )
397             ) unless defined $fd;
398              
399 4         9 return $fd;
400             }
401              
402             =item mode
403              
404             Returns the operator in terms of 'r', 'w', and 'a'. There is a state
405             'ra', unlike Perl's open(), which indicates that data read from the
406             handle or file will be appended to the output if the output is a scalar.
407             This is only meaningful if the output is a scalar, it has no effect if
408             the output is a subroutine.
409              
410             The redirection operators can be a little confusing, so here's a reference
411             table:
412              
413             > r Read from handle in to process
414             < w Write from process out to handle
415             >> ra Read from handle in to process, appending it to existing
416             data if the destination is a scalar.
417             << wa Write from process out to handle, appending to existing
418             data if IPC::Run::IO opened a named file.
419              
420             =cut
421              
422             sub mode {
423 10     10 1 14 my IPC::Run::IO $self = shift;
424              
425 10 50       22 croak "IPC::Run::IO: unexpected arguments for mode(): @_" if @_;
426              
427             ## TODO: Optimize this
428 10 100       86 return ( $self->{TYPE} =~ /{TYPE} =~ /<<|>>/ ? 'a' : '' );
    100          
429             }
430              
431             =item op
432              
433             Returns the operation: '<', '>', '<<', '>>'. See L if you want
434             to spell these 'r', 'w', etc.
435              
436             =cut
437              
438             sub op {
439 2446     2446 1 3996 my IPC::Run::IO $self = shift;
440              
441 2446 50       5539 croak "IPC::Run::IO: unexpected arguments for op(): @_" if @_;
442              
443 2446         18393 return $self->{TYPE};
444             }
445              
446             =item binmode
447              
448             Sets/gets whether this pipe is in binmode or not. No effect off of Win32
449             OSs, of course, and on Win32, no effect after the harness is start()ed.
450              
451             =cut
452              
453             sub binmode {
454 2444     2444 1 3917 my IPC::Run::IO $self = shift;
455              
456 2444 50       7918 $self->{BINMODE} = shift if @_;
457              
458 2444         4369 return $self->{BINMODE};
459             }
460              
461             =item dir
462              
463             Returns the first character of $self->op. This is either "<" or ">".
464              
465             =cut
466              
467             sub dir {
468 8517     8517 1 17152 my IPC::Run::IO $self = shift;
469              
470 8517 50       18620 croak "IPC::Run::IO: unexpected arguments for dir(): @_" if @_;
471              
472 8517         37021 return substr $self->{TYPE}, 0, 1;
473             }
474              
475             ##
476             ## Filter Scaffolding
477             ##
478             #my $filter_op ; ## The op running a filter chain right now
479             #my $filter_num; ## Which filter is being run right now.
480              
481             use vars (
482 117         64257 '$filter_op', ## The op running a filter chain right now
483             '$filter_num' ## Which filter is being run right now.
484 117     117   993 );
  117         285  
485              
486             sub _init_filters {
487 2544     2544   110833 my IPC::Run::IO $self = shift;
488              
489 2544 50       9284 confess "\$self not an IPC::Run::IO" unless UNIVERSAL::isa( $self, "IPC::Run::IO" );
490 2544         6803 $self->{FBUFS} = [];
491              
492             $self->{FBUFS}->[0] = $self->{DEST}
493 2544 100 100     15422 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
494              
495 2544 100 66     11146 return unless $self->{FILTERS} && @{ $self->{FILTERS} };
  2544         10628  
496              
497 1008         2273 push @{ $self->{FBUFS} }, map {
498 2590         3943 my $s = "";
499 2590         6214 \$s;
500 1008         2060 } ( @{ $self->{FILTERS} }, '' );
  1008         2794  
501              
502 1008         1917 push @{ $self->{FBUFS} }, $self->{SOURCE};
  1008         3848  
503             }
504              
505             =item poll
506              
507             TODO: Needs confirmation that this is correct. Was previously undocumented.
508              
509             I believe this is polling the IO for new input and then returns undef if there will never be any more input, 0 if there is none now, but there might be in the future, and TRUE if more input was gotten.
510              
511             =cut
512              
513             sub poll {
514 4707     4707 1 11569 my IPC::Run::IO $self = shift;
515 4707         9453 my ($harness) = @_;
516              
517 4707 100       11385 if ( defined $self->{FD} ) {
518 4675         17245 my $d = $self->dir;
519 4675 100       19297 if ( $d eq "<" ) {
    50          
520 1036 100       6048 if ( vec $harness->{WOUT}, $self->{FD}, 1 ) {
521 884 50       22802 _debug_desc_fd( "filtering data to", $self )
522             if _debugging_details;
523 884         7986 return $self->_do_filters($harness);
524             }
525             }
526             elsif ( $d eq ">" ) {
527 3639 100       11634 if ( vec $harness->{ROUT}, $self->{FD}, 1 ) {
528 2233 50       49551 _debug_desc_fd( "filtering data from", $self )
529             if _debugging_details;
530 2233         8157 return $self->_do_filters($harness);
531             }
532             }
533             }
534 1590         8908 return 0;
535             }
536              
537             sub _do_filters {
538 5081     5081   176470 my IPC::Run::IO $self = shift;
539              
540 5081         17654 ( $self->{HARNESS} ) = @_;
541              
542 5081         10449 my ( $saved_op, $saved_num ) = ( $IPC::Run::filter_op, $IPC::Run::filter_num );
543 5081         10325 $IPC::Run::filter_op = $self;
544 5081         8130 $IPC::Run::filter_num = -1;
545 5081         8064 my $redos = 0;
546 5081         6798 my $r;
547             {
548 5081         6962 $@ = '';
  5081         11366  
549 5081         8134 $r = eval { IPC::Run::get_more_input(); };
  5081         23810  
550              
551             # Detect Resource temporarily unavailable and re-try 200 times (2 seconds), assuming select behaves (which it doesn't always? need ref)
552 5081 50 50     44879 if ( ( $@ || '' ) =~ $IPC::Run::_EAGAIN && $redos++ < 200 ) {
      33        
553 0         0 select( undef, undef, undef, 0.01 );
554 0         0 redo;
555             }
556             }
557 5081         12069 ( $IPC::Run::filter_op, $IPC::Run::filter_num ) = ( $saved_op, $saved_num );
558 5081         9310 $self->{HARNESS} = undef;
559 5081 50       10521 die "ack ", $@ if $@;
560 5081         27780 return $r;
561             }
562              
563             =back
564              
565             =head1 AUTHOR
566              
567             Barrie Slaymaker
568              
569             =head1 TODO
570              
571             Implement bidirectionality.
572              
573             =cut
574              
575             1;