File Coverage

blib/lib/IPC/Run/IO.pm
Criterion Covered Total %
statement 186 193 96.3
branch 79 118 66.9
condition 19 40 47.5
subroutine 30 30 100.0
pod 12 12 100.0
total 326 393 82.9


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 126     126   975 use strict;
  126         266  
  126         4193  
66 126     126   633 use warnings;
  126         311  
  126         3726  
67 126     126   661 use Carp;
  126         275  
  126         7320  
68 126     126   789 use Fcntl;
  126         200  
  126         24175  
69 126     126   901 use Symbol;
  126         270  
  126         5908  
70              
71 126     126   728 use IPC::Run::Debug;
  126         355  
  126         11076  
72 126     126   1791 use IPC::Run qw( Win32_MODE );
  126         759  
  126         10592  
73              
74 126     126   930 use vars qw{$VERSION};
  126         303  
  126         11597  
75              
76             BEGIN {
77 126     126   571 $VERSION = '20231003.0';
78 126 50       263166 if (Win32_MODE) {
79 0 0 0     0 eval "use IPC::Run::Win32Helper; require IPC::Run::Win32IO; 1"
      0        
80             or ( $@ && die )
81             or die "$!";
82             }
83             }
84              
85             sub _empty($);
86             *_empty = \&IPC::Run::_empty;
87              
88             =head1 SUBROUTINES
89              
90             =over 4
91              
92             =item new
93              
94             I think it takes >> or << along with some other data.
95              
96             TODO: Needs more thorough documentation. Patches welcome.
97              
98             =cut
99              
100             sub new {
101 7     7 1 13 my $class = shift;
102 7   33     30 $class = ref $class || $class;
103              
104 7         15 my ( $external, $type, $internal ) = ( shift, shift, pop );
105              
106 7 50       42 croak "$class: '$_' is not a valid I/O operator"
107             unless $type =~ /^(?:<>?)$/;
108              
109 7         22 my IPC::Run::IO $self = $class->_new_internal( $type, undef, undef, $internal, undef, @_ );
110              
111 7 50 0     14 if ( !ref $external ) {
    0          
112 7         14 $self->{FILENAME} = $external;
113             }
114             elsif ( ref $external eq 'GLOB' || UNIVERSAL::isa( $external, 'IO::Handle' ) ) {
115 0         0 $self->{HANDLE} = $external;
116 0         0 $self->{DONT_CLOSE} = 1;
117             }
118             else {
119 0         0 croak "$class: cannot accept " . ref($external) . " to do I/O with";
120             }
121              
122 7         21 return $self;
123             }
124              
125             ## IPC::Run uses this ctor, since it preparses things and needs more
126             ## smarts.
127             sub _new_internal {
128 2618     2618   8196 my $class = shift;
129 2618   33     15600 $class = ref $class || $class;
130              
131 2618 50 33     11528 $class = "IPC::Run::Win32IO"
132             if Win32_MODE && $class eq "IPC::Run::IO";
133              
134 2618         4024 my IPC::Run::IO $self;
135 2618         7945 $self = bless {}, $class;
136              
137 2618         11296 my ( $type, $kfd, $pty_id, $internal, $binmode, @filters ) = @_;
138              
139             # Older perls (<=5.00503, at least) don't do list assign to
140             # pseudo-hashes well.
141 2618         8846 $self->{TYPE} = $type;
142 2618         6875 $self->{KFD} = $kfd;
143 2618         9543 $self->{PTY_ID} = $pty_id;
144 2618         16361 $self->binmode($binmode);
145 2618         8378 $self->{FILTERS} = [@filters];
146              
147             ## Add an adapter to the end of the filter chain (which is usually just the
148             ## read/writer sub pushed by IPC::Run) to the DEST or SOURCE, if need be.
149 2618 100       13599 if ( $self->op =~ />/ ) {
150 1709 50       7065 croak "'$_' missing a destination" if _empty $internal;
151 1709         6249 $self->{DEST} = $internal;
152 1709 100       7433 if ( UNIVERSAL::isa( $self->{DEST}, 'CODE' ) ) {
153             ## Put a filter on the end of the filter chain to pass the
154             ## output on to the CODE ref. For SCALAR refs, the last
155             ## filter in the chain writes directly to the scalar itself. See
156             ## _init_filters(). For CODE refs, however, we need to adapt from
157             ## the SCALAR to calling the CODE.
158             unshift(
159 98         1187 @{ $self->{FILTERS} },
160             sub {
161 182     182   934 my ($in_ref) = @_;
162              
163 182   66     817 return IPC::Run::input_avail() && do {
164             $self->{DEST}->($$in_ref);
165             $$in_ref = '';
166             1;
167             }
168             }
169 98         502 );
170             }
171             }
172             else {
173 909 50       3545 croak "'$_' missing a source" if _empty $internal;
174 909         3533 $self->{SOURCE} = $internal;
175 909 100       6441 if ( UNIVERSAL::isa( $internal, 'CODE' ) ) {
    100          
176             push(
177 68         1783 @{ $self->{FILTERS} },
178             sub {
179 82     82   1529 my ( $in_ref, $out_ref ) = @_;
180 82 50       1366 return 0 if length $$out_ref;
181              
182             return undef
183 82 50       1271 if $self->{SOURCE_EMPTY};
184              
185 82         1750 my $in = $internal->();
186 82 100       2213 unless ( defined $in ) {
187 46         1088 $self->{SOURCE_EMPTY} = 1;
188 46         443 return undef;
189             }
190 36 100       1611 return 0 unless length $in;
191 29         269 $$out_ref = $in;
192              
193 29         943 return 1;
194             }
195 68         291 );
196             }
197             elsif ( UNIVERSAL::isa( $internal, 'SCALAR' ) ) {
198             push(
199 558         9334 @{ $self->{FILTERS} },
200             sub {
201 1780     1780   7823 my ( $in_ref, $out_ref ) = @_;
202 1780 50       5601 return 0 if length $$out_ref;
203              
204             ## pump() clears auto_close_ins, finish() sets it.
205             return $self->{HARNESS}->{auto_close_ins} ? undef : 0
206 1780         12216 if IPC::Run::_empty ${ $self->{SOURCE} }
207 1780 100 100     3349 || $self->{SOURCE_EMPTY};
    100          
208              
209 366         3617 $$out_ref = $$internal;
210 109         656 eval { $$internal = '' }
211 366 100       3126 if $self->{HARNESS}->{clear_ins};
212              
213 366         1631 $self->{SOURCE_EMPTY} = $self->{HARNESS}->{auto_close_ins};
214              
215 366         3080 return 1;
216             }
217 558         1283 );
218             }
219             }
220              
221 2618         10613 return $self;
222             }
223              
224             =item filename
225              
226             Gets/sets the filename. Returns the value after the name change, if
227             any.
228              
229             =cut
230              
231             sub filename {
232 4     4 1 8 my IPC::Run::IO $self = shift;
233 4 50       8 $self->{FILENAME} = shift if @_;
234 4         16 return $self->{FILENAME};
235             }
236              
237             =item init
238              
239             Does initialization required before this can be run. This includes open()ing
240             the file, if necessary, and clearing the destination scalar if necessary.
241              
242             =cut
243              
244             sub init {
245 2     2 1 4 my IPC::Run::IO $self = shift;
246              
247 2         7 $self->{SOURCE_EMPTY} = 0;
248 1         4 ${ $self->{DEST} } = ''
249 2 100 66     12 if $self->mode =~ /r/ && ref $self->{DEST} eq 'SCALAR';
250              
251 2 50       8 $self->open if defined $self->filename;
252 2         7 $self->{FD} = $self->fileno;
253              
254 2 50       7 if ( !$self->{FILTERS} ) {
255 0         0 $self->{FBUFS} = undef;
256             }
257             else {
258 2         7 @{ $self->{FBUFS} } = map {
259 3         5 my $s = "";
260 3         7 \$s;
261 2         4 } ( @{ $self->{FILTERS} }, '' );
  2         6  
262              
263             $self->{FBUFS}->[0] = $self->{DEST}
264 2 100 66     11 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
265 2         3 push @{ $self->{FBUFS} }, $self->{SOURCE};
  2         7  
266             }
267              
268 2         6 return undef;
269             }
270              
271             =item open
272              
273             If a filename was passed in, opens it. Determines if the handle is open
274             via fileno(). Throws an exception on error.
275              
276             =cut
277              
278             my %open_flags = (
279             '>' => O_RDONLY,
280             '>>' => O_RDONLY,
281             '<' => O_WRONLY | O_CREAT | O_TRUNC,
282             '<<' => O_WRONLY | O_CREAT | O_APPEND,
283             );
284              
285             sub open {
286 2     2 1 4 my IPC::Run::IO $self = shift;
287              
288             croak "IPC::Run::IO: Can't open() a file with no name"
289 2 50       9 unless defined $self->{FILENAME};
290 2 50       11 $self->{HANDLE} = gensym unless $self->{HANDLE};
291              
292 2 50       81 _debug "opening '", $self->filename, "' mode '", $self->mode, "'"
293             if _debugging_data;
294             sysopen(
295             $self->{HANDLE},
296             $self->filename,
297 2 50       7 $open_flags{ $self->op },
298             ) or croak "IPC::Run::IO: $! opening '$self->{FILENAME}', mode '" . $self->mode . "'";
299              
300 2         25 return undef;
301             }
302              
303             =item open_pipe
304              
305             If this is a redirection IO object, this opens the pipe in a platform
306             independent manner.
307              
308             =cut
309              
310             sub _do_open {
311 2087     2087   3541 my $self = shift;
312 2087         5339 my ( $child_debug_fd, $parent_handle ) = @_;
313              
314 2087 100       5179 if ( $self->dir eq "<" ) {
315 640         5992 ( $self->{TFD}, $self->{FD} ) = IPC::Run::_pipe_nb;
316 640 100       4454 if ($parent_handle) {
317 28 50       6720 CORE::open $parent_handle, ">&=$self->{FD}"
318             or croak "$! duping write end of pipe for caller";
319             }
320             }
321             else {
322 1447         9252 ( $self->{FD}, $self->{TFD} ) = IPC::Run::_pipe;
323 1447 100       5079 if ($parent_handle) {
324 52 50       1364 CORE::open $parent_handle, "<&=$self->{FD}"
325             or croak "$! duping read end of pipe for caller";
326             }
327             }
328             }
329              
330             sub open_pipe {
331 2087     2087 1 4723 my IPC::Run::IO $self = shift;
332              
333             ## Hmmm, Maybe allow named pipes one day. But until then...
334             croak "IPC::Run::IO: Can't pipe() when a file name has been set"
335 2087 50       6771 if defined $self->{FILENAME};
336              
337 2087         8003 $self->_do_open(@_);
338              
339             ## return ( child_fd, parent_fd )
340             return $self->dir eq "<"
341             ? ( $self->{TFD}, $self->{FD} )
342 2087 100       7172 : ( $self->{FD}, $self->{TFD} );
343             }
344              
345             sub _cleanup { ## Called from Run.pm's _cleanup
346 2305     2305   5562 my $self = shift;
347 2305         14642 undef $self->{FAKE_PIPE};
348             }
349              
350             =item close
351              
352             Closes the handle. Throws an exception on failure.
353              
354              
355             =cut
356              
357             sub close {
358 1833     1833 1 7096 my IPC::Run::IO $self = shift;
359              
360 1833 100       7250 if ( defined $self->{HANDLE} ) {
361             close $self->{HANDLE}
362             or croak(
363             "IPC::Run::IO: $! closing "
364             . (
365             defined $self->{FILENAME}
366 2 0       28 ? "'$self->{FILENAME}'"
    50          
367             : "handle"
368             )
369             );
370             }
371             else {
372 1831         7516 IPC::Run::_close( $self->{FD} );
373             }
374              
375 1833         7393 $self->{FD} = undef;
376              
377 1833         5890 return undef;
378             }
379              
380             =item fileno
381              
382             Returns the fileno of the handle. Throws an exception on failure.
383              
384              
385             =cut
386              
387             sub fileno {
388 4     4 1 9 my IPC::Run::IO $self = shift;
389              
390 4         10 my $fd = fileno $self->{HANDLE};
391             croak(
392             "IPC::Run::IO: $! "
393             . (
394             defined $self->{FILENAME}
395 4 0       9 ? "'$self->{FILENAME}'"
    50          
396             : "handle"
397             )
398             ) unless defined $fd;
399              
400 4         8 return $fd;
401             }
402              
403             =item mode
404              
405             Returns the operator in terms of 'r', 'w', and 'a'. There is a state
406             'ra', unlike Perl's open(), which indicates that data read from the
407             handle or file will be appended to the output if the output is a scalar.
408             This is only meaningful if the output is a scalar, it has no effect if
409             the output is a subroutine.
410              
411             The redirection operators can be a little confusing, so here's a reference
412             table:
413              
414             > r Read from handle in to process
415             < w Write from process out to handle
416             >> ra Read from handle in to process, appending it to existing
417             data if the destination is a scalar.
418             << wa Write from process out to handle, appending to existing
419             data if IPC::Run::IO opened a named file.
420              
421             =cut
422              
423             sub mode {
424 10     10 1 15 my IPC::Run::IO $self = shift;
425              
426 10 50       23 croak "IPC::Run::IO: unexpected arguments for mode(): @_" if @_;
427              
428             ## TODO: Optimize this
429 10 100       120 return ( $self->{TYPE} =~ /{TYPE} =~ /<<|>>/ ? 'a' : '' );
    100          
430             }
431              
432             =item op
433              
434             Returns the operation: '<', '>', '<<', '>>'. See L if you want
435             to spell these 'r', 'w', etc.
436              
437             =cut
438              
439             sub op {
440 2620     2620 1 5384 my IPC::Run::IO $self = shift;
441              
442 2620 50       6699 croak "IPC::Run::IO: unexpected arguments for op(): @_" if @_;
443              
444 2620         19528 return $self->{TYPE};
445             }
446              
447             =item binmode
448              
449             Sets/gets whether this pipe is in binmode or not. No effect off of Win32
450             OSs, of course, and on Win32, no effect after the harness is start()ed.
451              
452             =cut
453              
454             sub binmode {
455 2618     2618 1 6500 my IPC::Run::IO $self = shift;
456              
457 2618 50       9897 $self->{BINMODE} = shift if @_;
458              
459 2618         5754 return $self->{BINMODE};
460             }
461              
462             =item dir
463              
464             Returns the first character of $self->op. This is either "<" or ">".
465              
466             =cut
467              
468             sub dir {
469 9245     9245 1 16993 my IPC::Run::IO $self = shift;
470              
471 9245 50       22642 croak "IPC::Run::IO: unexpected arguments for dir(): @_" if @_;
472              
473 9245         45820 return substr $self->{TYPE}, 0, 1;
474             }
475              
476             ##
477             ## Filter Scaffolding
478             ##
479             #my $filter_op ; ## The op running a filter chain right now
480             #my $filter_num; ## Which filter is being run right now.
481              
482             use vars (
483 126         70874 '$filter_op', ## The op running a filter chain right now
484             '$filter_num' ## Which filter is being run right now.
485 126     126   1128 );
  126         244  
486              
487             sub _init_filters {
488 2734     2734   150733 my IPC::Run::IO $self = shift;
489              
490 2734 50       11157 confess "\$self not an IPC::Run::IO" unless UNIVERSAL::isa( $self, "IPC::Run::IO" );
491 2734         7858 $self->{FBUFS} = [];
492              
493             $self->{FBUFS}->[0] = $self->{DEST}
494 2734 100 100     17469 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
495              
496 2734 100 66     13360 return unless $self->{FILTERS} && @{ $self->{FILTERS} };
  2734         13424  
497              
498 1032         2373 push @{ $self->{FBUFS} }, map {
499 2686         4997 my $s = "";
500 2686         8277 \$s;
501 1032         2267 } ( @{ $self->{FILTERS} }, '' );
  1032         3325  
502              
503 1032         2460 push @{ $self->{FBUFS} }, $self->{SOURCE};
  1032         4466  
504             }
505              
506             =item poll
507              
508             TODO: Needs confirmation that this is correct. Was previously undocumented.
509              
510             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.
511              
512             =cut
513              
514             sub poll {
515 5103     5103 1 12455 my IPC::Run::IO $self = shift;
516 5103         11949 my ($harness) = @_;
517              
518 5103 100       15171 if ( defined $self->{FD} ) {
519 5071         21454 my $d = $self->dir;
520 5071 100       22341 if ( $d eq "<" ) {
    50          
521 1057 100       7762 if ( vec $harness->{WOUT}, $self->{FD}, 1 ) {
522 888 50       25783 _debug_desc_fd( "filtering data to", $self )
523             if _debugging_details;
524 888         8199 return $self->_do_filters($harness);
525             }
526             }
527             elsif ( $d eq ">" ) {
528 4014 100       16213 if ( vec $harness->{ROUT}, $self->{FD}, 1 ) {
529 2557 50       63569 _debug_desc_fd( "filtering data from", $self )
530             if _debugging_details;
531 2557         13179 return $self->_do_filters($harness);
532             }
533             }
534             }
535 1658         13150 return 0;
536             }
537              
538             sub _do_filters {
539 5510     5510   226806 my IPC::Run::IO $self = shift;
540              
541 5510         20030 ( $self->{HARNESS} ) = @_;
542              
543 5510         13595 my ( $saved_op, $saved_num ) = ( $IPC::Run::filter_op, $IPC::Run::filter_num );
544 5510         12783 $IPC::Run::filter_op = $self;
545 5510         10033 $IPC::Run::filter_num = -1;
546 5510         8379 my $redos = 0;
547 5510         7530 my $r;
548             {
549 5510         8980 $@ = '';
  5510         9922  
550 5510         10525 $r = eval { IPC::Run::get_more_input(); };
  5510         26623  
551              
552             # Detect Resource temporarily unavailable and re-try 200 times (2 seconds), assuming select behaves (which it doesn't always? need ref)
553 5510 50 50     51226 if ( ( $@ || '' ) =~ $IPC::Run::_EAGAIN && $redos++ < 200 ) {
      33        
554 0         0 select( undef, undef, undef, 0.01 );
555 0         0 redo;
556             }
557             }
558 5510         14770 ( $IPC::Run::filter_op, $IPC::Run::filter_num ) = ( $saved_op, $saved_num );
559 5510         11294 $self->{HARNESS} = undef;
560 5510 50       13248 die "ack ", $@ if $@;
561 5510         34326 return $r;
562             }
563              
564             =back
565              
566             =head1 AUTHOR
567              
568             Barrie Slaymaker
569              
570             =head1 TODO
571              
572             Implement bidirectionality.
573              
574             =cut
575              
576             1;