File Coverage

blib/lib/IO/CaptureOutput.pm
Criterion Covered Total %
statement 112 120 93.3
branch 50 58 86.2
condition 50 53 94.3
subroutine 22 23 95.6
pod 3 3 100.0
total 237 257 92.2


line stmt bran cond sub pod time code
1 6     6   266913 use strict;
  6         17  
  6         261  
2 6     6   35 use warnings;
  6         12  
  6         2910  
3              
4             package IO::CaptureOutput;
5             # ABSTRACT: capture STDOUT and STDERR from Perl code, subprocesses or XS
6             our $VERSION = '1.1103'; # VERSION
7              
8 6     6   39 use vars qw/@ISA @EXPORT_OK %EXPORT_TAGS $CarpLevel/;
  6         10  
  6         657  
9 6     6   33 use Exporter;
  6         12  
  6         292  
10 6     6   34 use Carp qw/croak/;
  6         11  
  6         18300  
11             @ISA = 'Exporter';
12             @EXPORT_OK = qw/capture capture_exec qxx capture_exec_combined qxy/;
13             %EXPORT_TAGS = (all => \@EXPORT_OK);
14             $CarpLevel = 0; # help capture report errors at the right level
15              
16             sub _capture (&@) { ## no critic
17 60     60   135 my ($code, $output, $error, $output_file, $error_file) = @_;
18              
19             # check for valid combinations of input
20             {
21 60         96 local $Carp::CarpLevel = 1;
  60         181  
22 60         221 my $error = _validate($output, $error, $output_file, $error_file);
23 60 100       697 croak $error if $error;
24             }
25              
26             # if either $output or $error are defined, then we need a variable for
27             # results; otherwise we only capture to files and don't waste memory
28 58 100 100     216 if ( defined $output || defined $error ) {
29 48         90 for ($output, $error) {
30 96 100       253 $_ = \do { my $s; $s = ''} unless ref $_;
  10         14  
  10         25  
31 96 100 100     605 $$_ = '' if $_ != \undef && !defined($$_);
32             }
33             }
34              
35             # merge if same refs for $output and $error or if both are undef --
36             # i.e. capture \&foo, undef, undef, $merged_file
37             # this means capturing into separate files *requires* at least one
38             # capture variable
39 58   100     736 my $should_merge =
40             (defined $error && defined $output && $output == $error) ||
41             ( !defined $output && !defined $error ) ||
42             0;
43              
44 58         131 my ($capture_out, $capture_err);
45              
46             # undef means capture anonymously; anything other than \undef means
47             # capture to that ref; \undef means skip capture
48 58 100 100     304 if ( !defined $output || $output != \undef ) {
49 56         594 $capture_out = IO::CaptureOutput::_proxy->new(
50             'STDOUT', $output, undef, $output_file
51             );
52             }
53 58 100 100     355 if ( !defined $error || $error != \undef ) {
54 56 100       731 $capture_err = IO::CaptureOutput::_proxy->new(
55             'STDERR', $error, ($should_merge ? 'STDOUT' : undef), $error_file
56             );
57             }
58              
59             # now that output capture is setup, call the subroutine
60             # results get read when IO::CaptureOutput::_proxy objects go out of scope
61 58         380 &$code();
62             }
63              
64             # Extra indirection for symmetry with capture_exec, etc. Gets error reporting
65             # to the right level
66             sub capture (&@) { ## no critic
67 50     50 1 129042 return &_capture;
68             }
69              
70             sub capture_exec {
71 5     5 1 31933 my @args = @_;
72 5         11 my ($output, $error);
73 5     5   67 my $exit = _capture sub { system _shell_quote(@args) }, \$output, \$error;
  5         101  
74 5 100       327 my $success = ($exit == 0 ) ? 1 : 0 ;
75 5         32 $? = $exit;
76 5 100       6383 return wantarray ? ($output, $error, $success, $exit) : $output;
77             }
78              
79             *qxx = \&capture_exec;
80              
81             sub capture_exec_combined {
82 5     5 1 20391 my @args = @_;
83 5         14 my $output;
84 5     5   78 my $exit = _capture sub { system _shell_quote(@args) }, \$output, \$output;
  5         27  
85 5 100       223 my $success = ($exit == 0 ) ? 1 : 0 ;
86 5         54 $? = $exit;
87 5 100       142 return wantarray ? ($output, $success, $exit) : $output;
88             }
89              
90             *qxy = \&capture_exec_combined;
91              
92             # extra quoting required on Win32 systems
93 10     10   165236 *_shell_quote = ($^O =~ /MSWin32/) ? \&_shell_quote_win32 : sub {@_};
94             sub _shell_quote_win32 {
95 0     0   0 my @args;
96 0         0 for (@_) {
97 0 0       0 if (/[ \"]/) { # TODO: check if ^ requires escaping
98 0         0 (my $escaped = $_) =~ s/([\"])/\\$1/g;
99 0         0 push @args, '"' . $escaped . '"';
100 0         0 next;
101             }
102 0         0 push @args, $_
103             }
104 0         0 return @args;
105             }
106              
107             # detect errors and return an error message or empty string;
108             sub _validate {
109 60     60   127 my ($output, $error, $output_file, $error_file) = @_;
110              
111             # default to "ok"
112 60         138 my $msg = q{};
113              
114             # \$out, \$out, $outfile, $errfile
115 60 100 100     1282 if ( defined $output && defined $error
    100 100        
      100        
      100        
      66        
      100        
      100        
      100        
      100        
      100        
116             && defined $output_file && defined $error_file
117             && $output == $error
118             && $output != \undef
119             && $output_file ne $error_file
120             ) {
121 1         3 $msg = "Merged STDOUT and STDERR, but specified different output and error files";
122             }
123             # undef, undef, $outfile, $errfile
124             elsif ( !defined $output && !defined $error
125             && defined $output_file && defined $error_file
126             && $output_file ne $error_file
127             ) {
128 1         3 $msg = "Merged STDOUT and STDERR, but specified different output and error files";
129             }
130              
131 60         180 return $msg;
132             }
133              
134             # Captures everything printed to a filehandle for the lifetime of the object
135             # and then transfers it to a scalar reference
136             package IO::CaptureOutput::_proxy;
137 6     6   10114 use File::Temp 0.16 'tempfile';
  6         231315  
  6         1348  
138 6     6   56 use File::Basename qw/basename/;
  6         13  
  6         824  
139 6     6   39 use Symbol qw/gensym qualify qualify_to_ref/;
  6         13  
  6         370  
140 6     6   34 use Carp;
  6         11  
  6         995  
141              
142 110 50   110   1091 sub _is_wperl { $^O eq 'MSWin32' && basename($^X) eq 'wperl.exe' }
143              
144             sub new {
145 112     112   167 my $class = shift;
146 112         245 my ($orig_fh, $capture_var, $merge_fh, $capture_file) = @_;
147 112         389 $orig_fh = qualify($orig_fh); # e.g. main::STDOUT
148 112         2117 my $fhref = qualify_to_ref($orig_fh); # e.g. \*STDOUT
149              
150             # Duplicate the filehandle
151 112         1165 my $saved_fh;
152             {
153 6     6   113 no strict 'refs'; ## no critic - needed for 5.005
  6         12  
  6         1881  
  112         281  
154 112 100 66     693 if ( defined fileno($orig_fh) && ! _is_wperl() ) {
155 110         291 $saved_fh = gensym;
156 110 50       3565 open $saved_fh, ">&$orig_fh" or croak "Can't redirect <$orig_fh> - $!";
157             }
158             }
159              
160             # Create replacement filehandle if not merging
161 112         173 my ($newio_fh, $newio_file);
162 112 100       208 if ( ! $merge_fh ) {
163 92         225 $newio_fh = gensym;
164 92 100       955 if ($capture_file) {
165 19         32 $newio_file = $capture_file;
166             } else {
167 73         621 (undef, $newio_file) = tempfile;
168             }
169 92 50       44123 open $newio_fh, "+>$newio_file" or croak "Can't write temp file for $orig_fh - $!";
170             }
171             else {
172 20         68 $newio_fh = qualify($merge_fh);
173             }
174              
175             # Redirect (or merge)
176             {
177 6     6   33 no strict 'refs'; ## no critic -- needed for 5.005
  6         9  
  6         2407  
  112         385  
178 112 50       2908 open $fhref, ">&".fileno($newio_fh) or croak "Can't redirect $orig_fh - $!";
179             }
180              
181 112         847 bless [$$, $orig_fh, $saved_fh, $capture_var, $newio_fh, $newio_file, $capture_file], $class;
182             }
183              
184             sub DESTROY {
185 112     112   295374 my $self = shift;
186              
187 112         1060 my ($pid, $orig_fh, $saved_fh, $capture_var, $newio_fh,
188             $newio_file, $capture_file) = @$self;
189 112 100       1579 return unless $pid eq $$; # only cleanup in the process that is capturing
190              
191             # restore the original filehandle
192 110         695 my $fh_ref = Symbol::qualify_to_ref($orig_fh);
193 110         3063 select((select ($fh_ref), $|=1)[0]);
194 110 100       479 if (defined $saved_fh) {
195 108 50       4210 open $fh_ref, ">&". fileno($saved_fh) or croak "Can't restore $orig_fh - $!";
196             }
197             else {
198 2         11 close $fh_ref;
199             }
200              
201             # transfer captured data to the scalar reference if we didn't merge
202             # $newio_file is undef if this file handle is merged to another
203 110 100 100     963 if (ref $capture_var && $newio_file) {
204             # some versions of perl complain about reading from fd 1 or 2
205             # which could happen if STDOUT and STDERR were closed when $newio
206             # was opened, so we just squelch warnings here and continue
207 80         329 local $^W;
208 80         454 seek $newio_fh, 0, 0;
209 80         112 $$capture_var = do {local $/; <$newio_fh>};
  80         361  
  80         2887  
210             }
211 110 100       1473 close $newio_fh if $newio_file;
212              
213             # Cleanup
214 110 100 66     2813 return unless defined $newio_file && -e $newio_file;
215 90 100       392 return if $capture_file; # the "temp" file was explicitly named
216 71 50       15173 unlink $newio_file or carp "Couldn't remove temp file '$newio_file' - $!";
217             }
218              
219             1;
220              
221             __END__
222              
223             =pod
224              
225             =encoding UTF-8
226              
227             =head1 NAME
228              
229             IO::CaptureOutput - capture STDOUT and STDERR from Perl code, subprocesses or XS
230              
231             =head1 VERSION
232              
233             version 1.1103
234              
235             =head1 SYNOPSIS
236              
237             use IO::CaptureOutput qw(capture qxx qxy);
238            
239             # STDOUT and STDERR separately
240             capture { noisy_sub(@args) } \$stdout, \$stderr;
241            
242             # STDOUT and STDERR together
243             capture { noisy_sub(@args) } \$combined, \$combined;
244            
245             # STDOUT and STDERR from external command
246             ($stdout, $stderr, $success) = qxx( @cmd );
247            
248             # STDOUT and STDERR together from external command
249             ($combined, $success) = qxy( @cmd );
250              
251             =head1 DESCRIPTION
252              
253             B<This module is no longer recommended by the maintainer> - see
254             L<Capture::Tiny> instead.
255              
256             This module provides routines for capturing STDOUT and STDERR from perl
257             subroutines, forked system calls (e.g. C<<< system() >>>, C<<< fork() >>>) and from
258             XS or C modules.
259              
260             =head1 NAME
261              
262             =head1 VERSION
263              
264             This documentation describes version %%VERSION%%.
265              
266             =head1 FUNCTIONS
267              
268             The following functions will be exported on demand.
269              
270             =head2 capture()
271              
272             capture \&subroutine, \$stdout, \$stderr;
273              
274             Captures everything printed to C<<< STDOUT >>> and C<<< STDERR >>> for the duration of
275             C<<< &subroutine >>>. C<<< $stdout >>> and C<<< $stderr >>> are optional scalars that will contain
276             C<<< STDOUT >>> and C<<< STDERR >>> respectively.
277              
278             C<<< capture() >>> uses a code prototype so the first argument can be specified directly within
279             brackets if desired.
280              
281             # shorthand with prototype
282             capture { print __PACKAGE__ } \$stdout, \$stderr;
283              
284             Returns the return value(s) of C<<< &subroutine >>>. The sub is called in the same
285             context as C<<< capture() >>> was called e.g.:
286              
287             @rv = capture { wantarray } ; # returns true
288             $rv = capture { wantarray } ; # returns defined, but not true
289             capture { wantarray }; # void, returns undef
290              
291             C<<< capture() >>> is able to capture output from subprocesses and C code, which
292             traditional C<<< tie() >>> methods of output capture are unable to do.
293              
294             B<Note:> C<<< capture() >>> will only capture output that has been written or flushed
295             to the filehandle.
296              
297             If the two scalar references refer to the same scalar, then C<<< STDERR >>> will be
298             merged to C<<< STDOUT >>> before capturing and the scalar will hold the combined
299             output of both.
300              
301             capture \&subroutine, \$combined, \$combined;
302              
303             Normally, C<<< capture() >>> uses anonymous, temporary files for capturing output.
304             If desired, specific file names may be provided instead as additional options.
305              
306             capture \&subroutine, \$stdout, \$stderr, $out_file, $err_file;
307              
308             Files provided will be clobbered, overwriting any previous data, but
309             will persist after the call to C<<< capture() >>> for inspection or other manipulation.
310              
311             By default, when no references are provided to hold STDOUT or STDERR, output
312             is captured and silently discarded.
313              
314             # Capture STDOUT, discard STDERR
315             capture \&subroutine, \$stdout;
316            
317             # Discard STDOUT, capture STDERR
318             capture \&subroutine, undef, \$stderr;
319              
320             However, even when using C<<< undef >>>, output can be captured to specific files.
321              
322             # Capture STDOUT to a specific file, discard STDERR
323             capture \&subroutine, \$stdout, undef, $outfile;
324            
325             # Discard STDOUT, capture STDERR to a specific file
326             capture \&subroutine, undef, \$stderr, undef, $err_file;
327            
328             # Discard both, capture merged output to a specific file
329             capture \&subroutine, undef, undef, $mergedfile;
330              
331             It is a fatal error to merge STDOUT and STDERR and request separate, specific
332             files for capture.
333              
334             # ERROR:
335             capture \&subroutine, \$stdout, \$stdout, $out_file, $err_file;
336             capture \&subroutine, undef, undef, $out_file, $err_file;
337              
338             If either STDOUT or STDERR should be passed through to the terminal instead of
339             captured, provide a reference to undef -- C<<< \undef >>> -- instead of a capture
340             variable.
341              
342             # Capture STDOUT, display STDERR
343             capture \&subroutine, \$stdout, \undef;
344            
345             # Display STDOUT, capture STDERR
346             capture \&subroutine, \undef, \$stderr;
347              
348             =head2 capture_exec()
349              
350             ($stdout, $stderr, $success, $exit_code) = capture_exec(@args);
351              
352             Captures and returns the output from C<<< system(@args) >>>. In scalar context,
353             C<<< capture_exec() >>> will return what was printed to C<<< STDOUT >>>. In list context,
354             it returns what was printed to C<<< STDOUT >>> and C<<< STDERR >>> as well as a success
355             flag and the exit value.
356              
357             $stdout = capture_exec('perl', '-e', 'print "hello world"');
358            
359             ($stdout, $stderr, $success, $exit_code) =
360             capture_exec('perl', '-e', 'warn "Test"');
361              
362             C<<< capture_exec >>> passes its arguments to C<<< system() >>> and on MSWin32 will protect
363             arguments with shell quotes if necessary. This makes it a handy and slightly
364             more portable alternative to backticks, piped C<<< open() >>> and C<<< IPC::Open3 >>>.
365              
366             The C<<< $success >>> flag returned will be true if the command ran successfully and
367             false if it did not (if the command could not be run or if it ran and
368             returned a non-zero exit value). On failure, the raw exit value of the
369             C<<< system() >>> call is available both in the C<<< $exit_code >>> returned and in the C<<< $? >>>
370             variable.
371              
372             ($stdout, $stderr, $success, $exit_code) =
373             capture_exec('perl', '-e', 'warn "Test" and exit 1');
374            
375             if ( ! $success ) {
376             print "The exit code was " . ($exit_code >> 8) . "\n";
377             }
378              
379             See L<perlvar> for more information on interpreting a child process
380             exit code.
381              
382             =head2 capture_exec_combined()
383              
384             ($combined, $success, $exit_code) = capture_exec_combined(
385             'perl', '-e', 'print "hello\n"', 'warn "Test\n"
386             );
387              
388             This is just like C<<< capture_exec() >>>, except that it merges C<<< STDERR >>> with C<<< STDOUT >>>
389             before capturing output.
390              
391             B<Note:> there is no guarantee that text printed to C<<< STDOUT >>> and C<<< STDERR >>> in the
392             subprocess will be appear in order. The actual order will depend on how IO
393             buffering is handled in the subprocess.
394              
395             =head2 qxx()
396              
397             This is an alias for C<<< capture_exec() >>>.
398              
399             =head2 qxy()
400              
401             This is an alias for C<<< capture_exec_combined() >>>.
402              
403             =head1 SEE ALSO
404              
405             =over
406              
407             =item *
408              
409             L<Capture::Tiny>
410              
411             =item *
412              
413             L<IPC::Open3>
414              
415             =item *
416              
417             L<IO::Capture>
418              
419             =item *
420              
421             L<IO::Utils>
422              
423             =item *
424              
425             L<IPC::System::Simple>
426              
427             =back
428              
429             =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
430              
431             =head1 SUPPORT
432              
433             =head2 Bugs / Feature Requests
434              
435             Please report any bugs or feature requests through the issue tracker
436             at L<https://github.com/dagolden/IO-CaptureOutput/issues>.
437             You will be notified automatically of any progress on your issue.
438              
439             =head2 Source Code
440              
441             This is open source software. The code repository is available for
442             public review and contribution under the terms of the license.
443              
444             L<https://github.com/dagolden/IO-CaptureOutput>
445              
446             git clone https://github.com/dagolden/IO-CaptureOutput.git
447              
448             =head1 AUTHORS
449              
450             =over 4
451              
452             =item *
453              
454             Simon Flack <simonflk@cpan.org>
455              
456             =item *
457              
458             David Golden <dagolden@cpan.org>
459              
460             =back
461              
462             =head1 CONTRIBUTORS
463              
464             =over 4
465              
466             =item *
467              
468             Olivier Mengué <dolmen@cpan.org>
469              
470             =item *
471              
472             Tony Cook <tony@develop-help.com>
473              
474             =item *
475              
476             unknown <dgolden@.(none)>
477              
478             =back
479              
480             =head1 COPYRIGHT AND LICENSE
481              
482             This software is copyright (c) 2014 by Simon Flack and David Golden.
483              
484             This is free software; you can redistribute it and/or modify it under
485             the same terms as the Perl 5 programming language system itself.
486              
487             =cut