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   1004 use v5.12.5;
  58         281  
8 58     58   399 use warnings;
  58         165  
  58         2790  
9              
10             our $VERSION = '1.14.2.3'; # TRIAL VERSION
11              
12 58     58   447 use IO::Select;
  58         1808  
  58         31150  
13              
14             sub io_read {
15 2     2 0 32 my ( $self, $out_fh, $err_fh, $pid, $option ) = @_;
16 2         24 my ( $out, $err, $out_line, $err_line );
17              
18 2         66 my $selector = IO::Select->new();
19 2         85 $selector->add($out_fh);
20 2         200 $selector->add($err_fh);
21              
22 2   50     112 my $rex_int_conf = Rex::Commands::get("rex_internals") || {};
23 2         15 my $buffer_size = 1024;
24 2 50       27 if ( exists $rex_int_conf->{read_buffer_size} ) {
25 0         0 $buffer_size = $rex_int_conf->{read_buffer_size};
26             }
27              
28 2         11 my ( $last_line_stdout, $last_line_stderr ) = ( "", "" );
29              
30 2         21 while ( my @ready = $selector->can_read ) {
31 15248         610895 foreach my $fh (@ready) {
32 15490         22012 my $buf = "";
33              
34 15490         127015 my $len = sysread $fh, $buf, $buffer_size;
35 15490 100       39022 $selector->remove($fh) unless $len;
36              
37 15490         27855 $buf =~ s/\r?\n/\n/g; # normalize EOL characters
38              
39             # append buffer to the proper overall output
40 15490 100       31815 $out .= $buf if $fh == $out_fh;
41 15490 100       33618 $err .= $buf if $fh == $err_fh;
42              
43 15490 100       29694 if ( $buf =~ /\n/ ) { # buffer has one or more newlines
44 1         11 my @line_chunks = split /\n/, $buf;
45              
46 1         4 my $partial_last_chunk = '';
47 1 50       11 if ( $buf !~ /\n$/ ) { # last chunk is partial
48 0         0 $partial_last_chunk = pop @line_chunks;
49             }
50              
51 1         3 foreach my $chunk (@line_chunks) {
52 1 50       4 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       21 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
62 1         8 $err_line = '';
63             }
64             }
65              
66 1 50       8 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 15489 100       26447 $out_line .= $buf if $fh == $out_fh;
74 15489 100       56964 $err_line .= $buf if $fh == $err_fh;
75             }
76             }
77             }
78              
79 2 100       49 unless ($out) {
80 1         4 $out = $last_line_stdout;
81             $self->execute_line_based_operation( $out, $option )
82 1 50       10 && do { kill( 'KILL', $pid ); goto END_OPEN };
  0         0  
  0         0  
83             }
84              
85 2 50       16 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         766 return ( $out, $err );
94             }
95              
96             1;