File Coverage

lib/Rex/Interface/Exec/IOReader.pm
Criterion Covered Total %
statement 42 59 71.1
branch 22 38 57.8
condition 1 2 50.0
subroutine 4 4 100.0
pod 0 1 0.0
total 69 104 66.3


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Interface::Exec::IOReader;
6              
7 58     58   963 use v5.12.5;
  58         287  
8 58     58   416 use warnings;
  58         189  
  58         2717  
9              
10             our $VERSION = '1.14.2.2'; # TRIAL VERSION
11              
12 58     58   444 use IO::Select;
  58         162  
  58         31375  
13              
14             sub io_read {
15 2     2 0 37 my ( $self, $out_fh, $err_fh, $pid, $option ) = @_;
16 2         16 my ( $out, $err, $out_line, $err_line );
17              
18 2         43 my $selector = IO::Select->new();
19 2         72 $selector->add($out_fh);
20 2         181 $selector->add($err_fh);
21              
22 2   50     107 my $rex_int_conf = Rex::Commands::get("rex_internals") || {};
23 2         6 my $buffer_size = 1024;
24 2 50       16 if ( exists $rex_int_conf->{read_buffer_size} ) {
25 0         0 $buffer_size = $rex_int_conf->{read_buffer_size};
26             }
27              
28 2         13 my ( $last_line_stdout, $last_line_stderr ) = ( "", "" );
29              
30 2         13 while ( my @ready = $selector->can_read ) {
31 14341         578218 foreach my $fh (@ready) {
32 14583         21390 my $buf = "";
33              
34 14583         115569 my $len = sysread $fh, $buf, $buffer_size;
35 14583 100       36667 $selector->remove($fh) unless $len;
36              
37 14583         25669 $buf =~ s/\r?\n/\n/g; # normalize EOL characters
38              
39             # append buffer to the proper overall output
40 14583 100       29507 $out .= $buf if $fh == $out_fh;
41 14583 100       31451 $err .= $buf if $fh == $err_fh;
42              
43 14583 100       27605 if ( $buf =~ /\n/ ) { # buffer has one or more newlines
44 1         9 my @line_chunks = split /\n/, $buf;
45              
46 1         8 my $partial_last_chunk = '';
47 1 50       10 if ( $buf !~ /\n$/ ) { # last chunk is partial
48 0         0 $partial_last_chunk = pop @line_chunks;
49             }
50              
51 1         17 foreach my $chunk (@line_chunks) {
52 1 50       26 if ( $fh == $out_fh ) {
    50          
53 0         0 $out_line .= $chunk;
54             $self->execute_line_based_operation( $out_line, $option )
55 0 0       0 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
56 0         0 $out_line = '';
57             }
58             elsif ( $fh == $err_fh ) {
59 1         3 $err_line .= $chunk;
60             $self->execute_line_based_operation( $err_line, $option )
61 1 50       35 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
62 1         3 $err_line = '';
63             }
64             }
65              
66 1 50       15 if ($partial_last_chunk) { # append partial chunk to line if present
67 0 0       0 $out_line .= $partial_last_chunk if $fh == $out_fh;
68 0 0       0 $err_line .= $partial_last_chunk if $fh == $err_fh;
69             }
70              
71             }
72             else { # buffer doesn't have any newlines
73 14582 100       24246 $out_line .= $buf if $fh == $out_fh;
74 14582 100       53336 $err_line .= $buf if $fh == $err_fh;
75             }
76             }
77             }
78              
79 2 100       39 unless ($out) {
80 1         2 $out = $last_line_stdout;
81             $self->execute_line_based_operation( $out, $option )
82 1 50       5 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
83             }
84              
85 2 50       24 unless ($err) {
86 0         0 $err = $last_line_stderr;
87             $self->execute_line_based_operation( $err, $option )
88 0 0       0 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
89             }
90              
91             END_OPEN:
92              
93 2         694 return ( $out, $err );
94             }
95              
96             1;