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 121     121   1062 use strict;
  121         217  
  121         3246  
66 121     121   538 use warnings;
  121         221  
  121         2696  
67 121     121   500 use Carp;
  121         271  
  121         5440  
68 121     121   591 use Fcntl;
  121         171  
  121         17908  
69 121     121   612 use Symbol;
  121         223  
  121         4640  
70              
71 121     121   531 use IPC::Run::Debug;
  121         209  
  121         6663  
72 121     121   1273 use IPC::Run qw( Win32_MODE );
  121         212  
  121         6412  
73              
74 121     121   603 use vars qw{$VERSION};
  121         211  
  121         8897  
75              
76             BEGIN {
77 121     121   371 $VERSION = '20220807.0';
78 121 50       215293 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 12 my $class = shift;
102 7   33     23 $class = ref $class || $class;
103              
104 7         13 my ( $external, $type, $internal ) = ( shift, shift, pop );
105              
106 7 50       33 croak "$class: '$_' is not a valid I/O operator"
107             unless $type =~ /^(?:<>?)$/;
108              
109 7         18 my IPC::Run::IO $self = $class->_new_internal( $type, undef, undef, $internal, undef, @_ );
110              
111 7 50 0     10 if ( !ref $external ) {
    0          
112 7         12 $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         19 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   6474 my $class = shift;
129 2618   33     12547 $class = ref $class || $class;
130              
131 2618 50 33     8945 $class = "IPC::Run::Win32IO"
132             if Win32_MODE && $class eq "IPC::Run::IO";
133              
134 2618         3807 my IPC::Run::IO $self;
135 2618         6377 $self = bless {}, $class;
136              
137 2618         8483 my ( $type, $kfd, $pty_id, $internal, $binmode, @filters ) = @_;
138              
139             # Older perls (<=5.00503, at least) don't do list assign to
140             # psuedo-hashes well.
141 2618         7250 $self->{TYPE} = $type;
142 2618         5473 $self->{KFD} = $kfd;
143 2618         5190 $self->{PTY_ID} = $pty_id;
144 2618         9367 $self->binmode($binmode);
145 2618         5595 $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       7277 if ( $self->op =~ />/ ) {
150 1709 50       5167 croak "'$_' missing a destination" if _empty $internal;
151 1709         4876 $self->{DEST} = $internal;
152 1709 100       6325 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         716 @{ $self->{FILTERS} },
160             sub {
161 182     182   662 my ($in_ref) = @_;
162              
163 182   66     695 return IPC::Run::input_avail() && do {
164             $self->{DEST}->($$in_ref);
165             $$in_ref = '';
166             1;
167             }
168             }
169 98         291 );
170             }
171             }
172             else {
173 909 50       3148 croak "'$_' missing a source" if _empty $internal;
174 909         2494 $self->{SOURCE} = $internal;
175 909 100       4926 if ( UNIVERSAL::isa( $internal, 'CODE' ) ) {
    100          
176             push(
177 68         1017 @{ $self->{FILTERS} },
178             sub {
179 82     82   661 my ( $in_ref, $out_ref ) = @_;
180 82 50       628 return 0 if length $$out_ref;
181              
182             return undef
183 82 50       462 if $self->{SOURCE_EMPTY};
184              
185 82         517 my $in = $internal->();
186 82 100       1064 unless ( defined $in ) {
187 46         264 $self->{SOURCE_EMPTY} = 1;
188 46         191 return undef;
189             }
190 36 100       376 return 0 unless length $in;
191 29         213 $$out_ref = $in;
192              
193 29         223 return 1;
194             }
195 68         129 );
196             }
197             elsif ( UNIVERSAL::isa( $internal, 'SCALAR' ) ) {
198             push(
199 558         6618 @{ $self->{FILTERS} },
200             sub {
201 1783     1783   5418 my ( $in_ref, $out_ref ) = @_;
202 1783 50       3858 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 1783         7691 if IPC::Run::_empty ${ $self->{SOURCE} }
207 1783 100 100     2156 || $self->{SOURCE_EMPTY};
    100          
208              
209 366         3057 $$out_ref = $$internal;
210 109         544 eval { $$internal = '' }
211 366 100       2768 if $self->{HARNESS}->{clear_ins};
212              
213 366         1145 $self->{SOURCE_EMPTY} = $self->{HARNESS}->{auto_close_ins};
214              
215 366         2345 return 1;
216             }
217 558         1770 );
218             }
219             }
220              
221 2618         7576 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 6 my IPC::Run::IO $self = shift;
233 4 50       16 $self->{FILENAME} = shift if @_;
234 4         12 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 3 my IPC::Run::IO $self = shift;
246              
247 2         5 $self->{SOURCE_EMPTY} = 0;
248 1         2 ${ $self->{DEST} } = ''
249 2 100 66     4 if $self->mode =~ /r/ && ref $self->{DEST} eq 'SCALAR';
250              
251 2 50       5 $self->open if defined $self->filename;
252 2         6 $self->{FD} = $self->fileno;
253              
254 2 50       5 if ( !$self->{FILTERS} ) {
255 0         0 $self->{FBUFS} = undef;
256             }
257             else {
258 2         5 @{ $self->{FBUFS} } = map {
259 3         5 my $s = "";
260 3         5 \$s;
261 2         14 } ( @{ $self->{FILTERS} }, '' );
  2         6  
262              
263             $self->{FBUFS}->[0] = $self->{DEST}
264 2 100 66     10 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
265 2         2 push @{ $self->{FBUFS} }, $self->{SOURCE};
  2         26  
266             }
267              
268 2         9 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 2 my IPC::Run::IO $self = shift;
287              
288             croak "IPC::Run::IO: Can't open() a file with no name"
289 2 50       14 unless defined $self->{FILENAME};
290 2 50       8 $self->{HANDLE} = gensym unless $self->{HANDLE};
291              
292 2 50       59 _debug "opening '", $self->filename, "' mode '", $self->mode, "'"
293             if _debugging_data;
294             sysopen(
295             $self->{HANDLE},
296             $self->filename,
297 2 50       5 $open_flags{ $self->op },
298             ) or croak "IPC::Run::IO: $! opening '$self->{FILENAME}', mode '" . $self->mode . "'";
299              
300 2         8 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   3651 my $self = shift;
312 2087         4497 my ( $child_debug_fd, $parent_handle ) = @_;
313              
314 2087 100       5053 if ( $self->dir eq "<" ) {
315 640         4444 ( $self->{TFD}, $self->{FD} ) = IPC::Run::_pipe_nb;
316 640 100       2805 if ($parent_handle) {
317 28 50       588 CORE::open $parent_handle, ">&=$self->{FD}"
318             or croak "$! duping write end of pipe for caller";
319             }
320             }
321             else {
322 1447         6332 ( $self->{FD}, $self->{TFD} ) = IPC::Run::_pipe;
323 1447 100       5195 if ($parent_handle) {
324 52 50       1089 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 3482 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       4289 if defined $self->{FILENAME};
336              
337 2087         9946 $self->_do_open(@_);
338              
339             ## return ( child_fd, parent_fd )
340             return $self->dir eq "<"
341             ? ( $self->{TFD}, $self->{FD} )
342 2087 100       5623 : ( $self->{FD}, $self->{TFD} );
343             }
344              
345             sub _cleanup { ## Called from Run.pm's _cleanup
346 2305     2305   3718 my $self = shift;
347 2305         10245 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 3860 my IPC::Run::IO $self = shift;
359              
360 1833 100       5473 if ( defined $self->{HANDLE} ) {
361             close $self->{HANDLE}
362             or croak(
363             "IPC::Run::IO: $! closing "
364             . (
365             defined $self->{FILENAME}
366 2 0       24 ? "'$self->{FILENAME}'"
    50          
367             : "handle"
368             )
369             );
370             }
371             else {
372 1831         6189 IPC::Run::_close( $self->{FD} );
373             }
374              
375 1833         5694 $self->{FD} = undef;
376              
377 1833         3280 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 5 my IPC::Run::IO $self = shift;
389              
390 4         8 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         7 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 12 my IPC::Run::IO $self = shift;
425              
426 10 50       18 croak "IPC::Run::IO: unexpected arguments for mode(): @_" if @_;
427              
428             ## TODO: Optimize this
429 10 100       65 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 4388 my IPC::Run::IO $self = shift;
441              
442 2620 50       5190 croak "IPC::Run::IO: unexpected arguments for op(): @_" if @_;
443              
444 2620         13290 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 3882 my IPC::Run::IO $self = shift;
456              
457 2618 50       6973 $self->{BINMODE} = shift if @_;
458              
459 2618         4291 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 9130     9130 1 13838 my IPC::Run::IO $self = shift;
470              
471 9130 50       15830 croak "IPC::Run::IO: unexpected arguments for dir(): @_" if @_;
472              
473 9130         34570 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 121         56604 '$filter_op', ## The op running a filter chain right now
484             '$filter_num' ## Which filter is being run right now.
485 121     121   864 );
  121         285  
486              
487             sub _init_filters {
488 2734     2734   99785 my IPC::Run::IO $self = shift;
489              
490 2734 50       8892 confess "\$self not an IPC::Run::IO" unless UNIVERSAL::isa( $self, "IPC::Run::IO" );
491 2734         7295 $self->{FBUFS} = [];
492              
493             $self->{FBUFS}->[0] = $self->{DEST}
494 2734 100 100     15426 if $self->{DEST} && ref $self->{DEST} eq 'SCALAR';
495              
496 2734 100 66     10693 return unless $self->{FILTERS} && @{ $self->{FILTERS} };
  2734         9955  
497              
498 1032         2243 push @{ $self->{FBUFS} }, map {
499 2686         3786 my $s = "";
500 2686         7308 \$s;
501 1032         1555 } ( @{ $self->{FILTERS} }, '' );
  1032         2236  
502              
503 1032         1947 push @{ $self->{FBUFS} }, $self->{SOURCE};
  1032         3325  
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 4988     4988 1 9082 my IPC::Run::IO $self = shift;
516 4988         8467 my ($harness) = @_;
517              
518 4988 100       12272 if ( defined $self->{FD} ) {
519 4956         15915 my $d = $self->dir;
520 4956 100       14800 if ( $d eq "<" ) {
    50          
521 1060 100       4713 if ( vec $harness->{WOUT}, $self->{FD}, 1 ) {
522 888 50       17352 _debug_desc_fd( "filtering data to", $self )
523             if _debugging_details;
524 888         7812 return $self->_do_filters($harness);
525             }
526             }
527             elsif ( $d eq ">" ) {
528 3896 100       11205 if ( vec $harness->{ROUT}, $self->{FD}, 1 ) {
529 2557 50       48573 _debug_desc_fd( "filtering data from", $self )
530             if _debugging_details;
531 2557         9484 return $self->_do_filters($harness);
532             }
533             }
534             }
535 1543         7629 return 0;
536             }
537              
538             sub _do_filters {
539 5513     5513   159806 my IPC::Run::IO $self = shift;
540              
541 5513         17339 ( $self->{HARNESS} ) = @_;
542              
543 5513         10144 my ( $saved_op, $saved_num ) = ( $IPC::Run::filter_op, $IPC::Run::filter_num );
544 5513         10154 $IPC::Run::filter_op = $self;
545 5513         6895 $IPC::Run::filter_num = -1;
546 5513         7068 my $redos = 0;
547 5513         6954 my $r;
548             {
549 5513         6391 $@ = '';
  5513         7971  
550 5513         6686 $r = eval { IPC::Run::get_more_input(); };
  5513         18150  
551              
552             # Detect Resource temporarily unavailable and re-try 200 times (2 seconds), assuming select behaves (which it doesn't always? need ref)
553 5513 50 50     40548 if ( ( $@ || '' ) =~ $IPC::Run::_EAGAIN && $redos++ < 200 ) {
      33        
554 0         0 select( undef, undef, undef, 0.01 );
555 0         0 redo;
556             }
557             }
558 5513         11493 ( $IPC::Run::filter_op, $IPC::Run::filter_num ) = ( $saved_op, $saved_num );
559 5513         7751 $self->{HARNESS} = undef;
560 5513 50       8954 die "ack ", $@ if $@;
561 5513         26461 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;