]> git.somenet.org - irc/bugbot.git/blob - lib/IO/SecurePipe.pm
GITOLITE.txt
[irc/bugbot.git] / lib / IO / SecurePipe.pm
1 # IO::SecurePipe.pm
2 # Created by Ian Hickson to make exec() call if IO::Pipe more secure.
3 # Distributed under exactly the same licence terms as IO::Pipe.
4
5 package IO::SecurePipe;
6 use strict;
7 #use Carp;
8 use IO::Pipe;
9 use vars qw(@ISA);
10 @ISA = qw(IO::Pipe);
11
12 my $do_spawn = $^O eq 'os2';
13
14 sub croak {
15     $0 =~ m/^(.*)$/os; # untaint $0 so that we can call it below:
16     exec { $1 } ($1, '--abort'); # do not call shutdown handlers
17     exit(); # exit (implicit in exec() actually)   
18 }
19
20 sub _doit {
21     my $me = shift;
22     my $rw = shift;
23
24     my $pid = $do_spawn ? 0 : fork();
25
26     if($pid) { # Parent
27         return $pid;
28     }
29     elsif(defined $pid) { # Child or spawn
30         my $fh;
31         my $io = $rw ? \*STDIN : \*STDOUT;
32         my ($mode, $save) = $rw ? "r" : "w";
33         if ($do_spawn) {
34           require Fcntl;
35           $save = IO::Handle->new_from_fd($io, $mode);
36           # Close in child:
37           fcntl(shift, Fcntl::F_SETFD(), 1) or croak "fcntl: $!";
38           $fh = $rw ? ${*$me}[0] : ${*$me}[1];
39         } else {
40           shift;
41           $fh = $rw ? $me->reader() : $me->writer(); # close the other end
42         }
43         bless $io, "IO::Handle";
44         $io->fdopen($fh, $mode);
45         $fh->close;
46
47         if ($do_spawn) {
48           $pid = eval { system 1, @_ }; # 1 == P_NOWAIT
49           my $err = $!;
50     
51           $io->fdopen($save, $mode);
52           $save->close or croak "Cannot close $!";
53           croak "IO::Pipe: Cannot spawn-NOWAIT: $err" if not $pid or $pid < 0;
54           return $pid;
55         } else {
56           exec { $_[0] } @_  or  # XXX change here
57             croak "IO::Pipe: Cannot exec: $!";
58         }
59     }
60     else {
61         croak "IO::Pipe: Cannot fork: $!";
62     }
63
64     # NOT Reached
65 }
66
67 1;