File Coverage

blib/lib/Proc/SafePipe.pm
Criterion Covered Total %
statement 39 39 100.0
branch 15 20 75.0
condition 2 3 66.6
subroutine 8 8 100.0
pod 2 2 100.0
total 66 72 91.6


line stmt bran cond sub pod time code
1             # $Id: SafePipe.pm,v 1.1 2000-09-23 21:23:56-04 roderick Exp $
2             #
3             # Copyright (c) 2000 Roderick Schertler. All rights reserved. This
4             # program is free software; you can redistribute it and/or modify it
5             # under the same terms as Perl itself.
6              
7 6     6   7506 use strict;
  6         6  
  6         180  
8 6     6   162 use 5.003_98; # piped close errno resetting
  6         12  
  6         300  
9              
10             =head1 NAME
11              
12             Proc::SafePipe - popen() and `` without calling the shell
13              
14             =head1 SYNOPSIS
15              
16             $fh = popen_noshell 'r', 'decrypt', $input;
17             ($fh, $pid) = popen_noshell 'w', 'ssh', $host, "cat >$output";
18              
19             $all_output = backtick_noshell 'decrypt', $input;
20             @lines = backtick_noshell $cmd, @arg;
21              
22             =head1 DESCRIPTION
23              
24             These functions provide a simple way to read from or write to commands
25             which are run without being interpreted by the shell. They croak if
26             there's a system failure, such as a failed fork.
27              
28             =over 4
29              
30             =cut
31              
32             package Proc::SafePipe;
33              
34 6     6   18 use Carp qw(croak);
  6         6  
  6         294  
35 6     6   24 use Exporter ();
  6         6  
  6         102  
36 6     6   4902 use Symbol qw(gensym);
  6         5214  
  6         348  
37              
38 6     6   36 use vars qw($VERSION @ISA @EXPORT);
  6         6  
  6         1842  
39              
40             $VERSION = 0.01;
41             @ISA = qw(Exporter);
42             @EXPORT = qw(popen_noshell backtick_noshell);
43              
44             =item B I I [I]...
45              
46             This function is similar to popen() except that the I and its
47             related Is are never interpreted by a shell, they are passed to
48             exec() as-is. The I argument must be C<'r'> or C<'w'>.
49              
50             If called in an array context the return value is a list consisting of
51             the filehandle and the PID of the child. In a scalar context only the
52             filehandle is returned.
53              
54             =cut
55              
56             sub popen_noshell {
57 38 100   38 1 1177781 @_ > 1 or croak 'Usage: popen_noshell {r|w} command [arg]...';
58 26         103 my ($type, @cmd) = @_;
59 26 100       119 if ($type eq 'r') { $type = '-|' }
  15 100       37  
60 5         40 elsif ($type eq 'w') { $type = '|-' }
61             else {
62 6         672 croak "Invalid popen mode `$type'"
63             }
64              
65 20         150 my $fh = gensym;
66 20         19858 my $pid = open $fh, $type;
67 20 50       889 defined $pid or croak "Can't fork: $!";
68 20 100       549 if (!$pid) {
69 5         841 local $^W; # disable exec failure warning
70 5 0       89 exec { $cmd[0] } @cmd or croak "Can't exec $cmd[0]: $!";
  5         0  
71             }
72 15 100       1430 wantarray ? ($fh, $pid) : $fh;
73             }
74              
75             =item B I [I]...
76              
77             This function runs the given I with the given Is and
78             returns the output, like C<``> does. The difference is that the
79             arguments are not filtered through a shell, they are exec()ed directly.
80              
81             The return value is either all the output from the command (if in a
82             scalar context) or a list of the lines gathered from the command (in an
83             array context). The exit status of the command is in $?.
84              
85             =cut
86              
87             sub backtick_noshell {
88 9 50   9 1 2716969 @_ >= 1 or croak 'Usage: backtick_noshell command [arg]...';
89 9         68 my @cmd = @_;
90 9         25 my ($fh, @output);
91              
92 9         63 $fh = popen_noshell 'r', @cmd;
93 6         2157952 @output = <$fh>;
94 6 50 66     748 close $fh or !$! or croak "Error closing $fh: $!";
95 6 100       249 wantarray ? @output : join '', @output;
96             }
97              
98             1
99              
100             __END__