line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package IPC::Exe; |
2
|
|
|
|
|
|
|
|
3
|
46
|
|
|
46
|
|
3515028
|
use 5.008_008; |
|
46
|
|
|
|
|
139
|
|
|
46
|
|
|
|
|
1706
|
|
4
|
|
|
|
|
|
|
|
5
|
46
|
|
|
46
|
|
232
|
use warnings; |
|
46
|
|
|
|
|
92
|
|
|
46
|
|
|
|
|
1439
|
|
6
|
46
|
|
|
46
|
|
275
|
use strict; |
|
46
|
|
|
|
|
92
|
|
|
46
|
|
|
|
|
2683
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
BEGIN { |
9
|
46
|
|
|
46
|
|
591
|
require Exporter; |
10
|
46
|
|
|
|
|
138
|
*import = \&Exporter::import; |
11
|
|
|
|
|
|
|
|
12
|
46
|
|
|
|
|
48
|
our $VERSION = "2.002001"; |
13
|
46
|
|
|
|
|
1191
|
our @EXPORT_OK = qw(exe bg); |
14
|
|
|
|
|
|
|
} |
15
|
|
|
|
|
|
|
|
16
|
46
|
|
|
46
|
|
276
|
use Carp qw(carp croak); |
|
46
|
|
|
|
|
47
|
|
|
46
|
|
|
|
|
2810
|
|
17
|
46
|
|
|
46
|
|
1311
|
use Data::Dumper qw(Dumper); |
|
46
|
|
|
|
|
10796
|
|
|
46
|
|
|
|
|
1745
|
|
18
|
46
|
|
|
46
|
|
189
|
use File::Spec (); |
|
46
|
|
|
|
|
47
|
|
|
46
|
|
|
|
|
1601
|
|
19
|
46
|
|
|
46
|
|
230
|
use Scalar::Util qw(tainted); |
|
46
|
|
|
|
|
47
|
|
|
46
|
|
|
|
|
2164
|
|
20
|
46
|
|
|
46
|
|
30369
|
use Symbol qw(gensym); |
|
46
|
|
|
|
|
39390
|
|
|
46
|
|
|
|
|
3542
|
|
21
|
46
|
|
|
46
|
|
36801
|
use Time::HiRes qw(usleep); |
|
46
|
|
|
|
|
144194
|
|
|
46
|
|
|
|
|
320
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
++$Carp::Internal{$_} for __PACKAGE__; |
24
|
|
|
|
|
|
|
|
25
|
46
|
|
|
46
|
|
14705
|
use constant NON_UNIX => ($^O =~ /^(?:MSWin32|os2)$/); |
|
46
|
|
|
|
|
92
|
|
|
46
|
|
|
|
|
6101
|
|
26
|
46
|
|
|
46
|
|
275
|
use constant OPEN_RDWR_RX => qr/^\s*(\d*)\s*(\+?[<>].*)/; |
|
46
|
|
|
|
|
47
|
|
|
46
|
|
|
|
|
411820
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# default environment variables to check for taint |
29
|
|
|
|
|
|
|
our @TAINT_ENV = qw(PATH PATHEXT IFS CDPATH ENV BASH_ENV PERL5SHELL); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
our $is_forked = 0; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# if set, fallback to forked child/parent process to ensure execution |
34
|
|
|
|
|
|
|
our $bg_fallback = 0; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my $DEVNULL = File::Spec->devnull(); |
37
|
|
|
|
|
|
|
|
38
|
7914
|
100
|
|
7914
|
|
199141
|
sub _reftype { Scalar::Util::reftype($_[0]) || "" } |
39
|
94
|
|
|
94
|
|
884
|
sub _is_fh { eval { defined(fileno($_[0])) } } |
|
94
|
|
|
|
|
8275
|
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
sub _stringify_args { |
42
|
27
|
|
|
27
|
|
303
|
local $Data::Dumper::Indent = 0; |
43
|
27
|
|
|
|
|
193
|
local $Data::Dumper::Useqq = 1; |
44
|
27
|
|
|
|
|
502
|
local $Data::Dumper::Terse = 1; |
45
|
27
|
|
|
|
|
139
|
return join(", " => map { Dumper($_) } @_); |
|
27
|
|
|
|
|
373
|
|
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# exit thread/process |
49
|
|
|
|
|
|
|
sub _quit { |
50
|
4
|
|
50
|
4
|
|
114
|
my $status = shift || 0; |
51
|
4
|
|
|
|
|
10
|
$^E = 0; |
52
|
4
|
50
|
|
|
|
63
|
$! = $status == -1 ? 255 : $status; |
53
|
4
|
|
|
|
|
64
|
$? = $! << 8; |
54
|
4
|
50
|
|
|
|
959
|
threads->exit($status) if threads->can("exit"); |
55
|
4
|
|
|
|
|
3974
|
exit($status); |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# escape LIST to be passed to exec() in a portable way |
59
|
|
|
|
|
|
|
sub _escape_cmd_list { |
60
|
0
|
|
|
|
|
0
|
return NON_UNIX |
61
|
|
|
|
|
|
|
? map { |
62
|
40
|
50
|
|
40
|
|
4317
|
(my $x = $_) |
63
|
0
|
0
|
|
|
|
0
|
=~ s/(\\"|")/$1 eq '"' ? '\\"' : '\\\\\\"'/ge; |
64
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
0
|
$x =~ /[\[\](){}<>'"`~!@^&+=|;,\s]/ |
66
|
|
|
|
|
|
|
? qq("$x") |
67
|
|
|
|
|
|
|
: $x; |
68
|
|
|
|
|
|
|
} @_ |
69
|
|
|
|
|
|
|
: @_; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub _check_taint { |
73
|
4
|
|
|
4
|
|
10
|
my (@bad_args, @bad_env); |
74
|
|
|
|
|
|
|
|
75
|
4
|
|
|
|
|
5
|
my $i = -1; |
76
|
4
|
|
|
|
|
8
|
for my $v (@_) |
77
|
|
|
|
|
|
|
{ |
78
|
7
|
|
|
|
|
8
|
++$i; |
79
|
7
|
100
|
|
|
|
36
|
push(@bad_args, [ $v, $i ]) if tainted($v); |
80
|
|
|
|
|
|
|
} |
81
|
4
|
|
|
|
|
10
|
for my $v (@TAINT_ENV) |
82
|
|
|
|
|
|
|
{ |
83
|
28
|
100
|
|
|
|
137
|
push(@bad_env, $v) if tainted($ENV{$v}); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# die if environment / arguments are tainted |
87
|
4
|
100
|
100
|
|
|
24
|
if (@bad_args || @bad_env) |
88
|
|
|
|
|
|
|
{ |
89
|
1
|
|
|
|
|
183
|
croak("IPC::Exe::exe() called with tainted vars:\n ", |
90
|
1
|
|
|
|
|
153
|
join("\n " => map { "\$ENV{$_}" } @bad_env), "\n ", |
91
|
2
|
|
|
|
|
27
|
join("\n " => map { "<$_->[0]> at index $_->[1]" } @bad_args), "\n", |
92
|
|
|
|
|
|
|
); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
2
|
|
|
|
|
5
|
return; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub _fh_slot { |
99
|
26
|
|
|
26
|
|
130
|
my ($slots, $n) = @_; |
100
|
26
|
|
|
|
|
483
|
$n += 0; |
101
|
|
|
|
|
|
|
|
102
|
26
|
|
66
|
|
|
292
|
my $FH_name = qw(STDIN STDOUT STDERR)[$n] || "FH[$n]"; |
103
|
26
|
100
|
66
|
|
|
242
|
my $FH = ($n <= 2) |
104
|
|
|
|
|
|
|
? (\*STDIN, \*STDOUT, \*STDERR)[$n] |
105
|
|
|
|
|
|
|
: ($slots->[$n] ||= gensym()); |
106
|
|
|
|
|
|
|
|
107
|
26
|
|
|
|
|
217
|
return ($FH, $FH_name); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub exe { |
111
|
1171
|
100
|
33
|
1171
|
1
|
12543558
|
_check_taint(@_) if $] >= 5.008 && ${^TAINT}; |
112
|
|
|
|
|
|
|
|
113
|
1169
|
100
|
|
|
|
4639
|
return () if @_ == 0; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# exe(sub { .. }) returns (sub { .. }) itself |
116
|
1124
|
100
|
100
|
|
|
5045
|
return $_[0] if @_ == 1 && _reftype($_[0]) eq "CODE"; |
117
|
|
|
|
|
|
|
|
118
|
1079
|
|
|
|
|
2434
|
my $args = \@_; |
119
|
1079
|
100
|
|
1060
|
|
13674
|
return sub { _exe(@_ ? [ @_ ] : undef, @{ $args }) }; |
|
1060
|
|
|
|
|
11201
|
|
|
1060
|
|
|
|
|
17634
|
|
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
sub _exe { |
122
|
|
|
|
|
|
|
# record error variables |
123
|
1060
|
|
|
1060
|
|
29303
|
my @status = ($?, -+-$!, -+-$^E, $@); |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# ref to arguments passed to closure |
126
|
1060
|
|
|
|
|
1999
|
my $_args = shift; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# merge options hash reference, if available |
129
|
1060
|
|
|
|
|
16922
|
my %opt = ( |
130
|
|
|
|
|
|
|
pid => undef, |
131
|
|
|
|
|
|
|
stdin => 0, |
132
|
|
|
|
|
|
|
stdout => 0, |
133
|
|
|
|
|
|
|
stderr => 0, |
134
|
|
|
|
|
|
|
autoflush => 1, |
135
|
|
|
|
|
|
|
binmode_io => undef, |
136
|
|
|
|
|
|
|
); |
137
|
1060
|
|
|
|
|
2575
|
my $opt_ref = $_[0]; |
138
|
1060
|
100
|
|
|
|
6345
|
if (_reftype($opt_ref) eq "HASH") |
139
|
|
|
|
|
|
|
{ |
140
|
14
|
|
|
|
|
51
|
@opt{keys %{ $opt_ref }} = values %{ $opt_ref }; |
|
14
|
|
|
|
|
49
|
|
|
14
|
|
|
|
|
93
|
|
141
|
14
|
|
|
|
|
41
|
shift; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# propagate $opt{binmode_io} to set binmode down chain of executions |
145
|
1060
|
50
|
|
|
|
18273
|
local $IPC::Exe::_binmode_io = defined($opt{binmode_io}) |
146
|
|
|
|
|
|
|
? $opt{binmode_io} |
147
|
|
|
|
|
|
|
: $IPC::Exe::_binmode_io; |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# propagate $opt{stdin} down chain of executions |
150
|
1060
|
|
100
|
|
|
29073
|
local $IPC::Exe::_stdin = $IPC::Exe::_stdin || !(!$opt{stdin}); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# setup input filehandle to write to STDIN |
153
|
1060
|
|
|
|
|
2039
|
my ($FOR_STDIN, $TO_STDIN); |
154
|
1060
|
100
|
|
|
|
6400
|
if ($opt{stdin}) |
155
|
|
|
|
|
|
|
{ |
156
|
12
|
50
|
0
|
|
|
633
|
pipe($FOR_STDIN, $TO_STDIN) |
157
|
|
|
|
|
|
|
or carp("IPC::Exe::exe() cannot create pipe to STDIN", "\n ", $!) |
158
|
|
|
|
|
|
|
and return (); |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# make filehandle hot |
161
|
12
|
50
|
|
|
|
159
|
select((select($TO_STDIN), $| = 1)[0]) if $opt{autoflush}; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# setup output filehandle to read from STDERR |
165
|
1060
|
|
|
|
|
1331
|
my ($FROM_STDERR, $BY_STDERR); |
166
|
1060
|
100
|
|
|
|
2703
|
if ($opt{stderr}) |
167
|
|
|
|
|
|
|
{ |
168
|
6
|
50
|
0
|
|
|
314
|
pipe($FROM_STDERR, $BY_STDERR) |
169
|
|
|
|
|
|
|
or carp("IPC::Exe::exe() cannot create pipe from STDERR", "\n ", $!) |
170
|
|
|
|
|
|
|
and return (); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# make filehandle hot |
173
|
6
|
50
|
|
|
|
112
|
select((select($BY_STDERR), $| = 1)[0]) if $opt{autoflush}; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# obtain CODE references, if available, for READER & PREEXEC subroutines |
177
|
1060
|
|
|
|
|
1848
|
my ($Preexec, $Reader); |
178
|
1060
|
100
|
|
|
|
4149
|
$Preexec = shift if _reftype($_[0]) eq "CODE"; |
179
|
1060
|
100
|
|
|
|
4010
|
$Reader = pop if _reftype($_[-1]) eq "CODE"; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# obtain redirects |
182
|
1060
|
|
|
|
|
3440
|
my @redirs; |
183
|
1060
|
|
|
|
|
4892
|
unshift(@redirs, pop) while ref($_[-1]); |
184
|
1060
|
100
|
|
|
|
2496
|
if (@redirs) |
185
|
|
|
|
|
|
|
{ |
186
|
291
|
|
|
|
|
763
|
my $old_preexec; |
187
|
291
|
50
|
|
|
|
1117
|
$old_preexec = $Preexec if $Preexec; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
$Preexec = sub { |
190
|
9
|
|
|
9
|
|
152
|
my @FHops; |
191
|
9
|
50
|
|
|
|
48
|
@FHops = $old_preexec->(@_) if $old_preexec; |
192
|
9
|
|
|
|
|
88
|
return (@FHops, @redirs); |
193
|
291
|
|
|
|
|
13889
|
}; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
# what is left is the command LIST |
197
|
1060
|
|
|
|
|
7480
|
my @cmd_list = @_; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# ban undefined values in LIST |
200
|
1060
|
100
|
|
|
|
3776
|
if (grep { !defined($_) } @cmd_list) |
|
2869
|
|
|
|
|
7502
|
|
201
|
|
|
|
|
|
|
{ |
202
|
26
|
|
|
|
|
338
|
carp("IPC::Exe::exe() cannot execute undef argument(s) below:", "\n ", |
203
|
|
|
|
|
|
|
_stringify_args(@cmd_list), "\n"); |
204
|
26
|
|
|
|
|
40612
|
return (); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# as a precaution, do not continue if no PREEXEC or LIST found |
208
|
1034
|
50
|
66
|
|
|
6666
|
return () unless defined($Preexec) || @cmd_list; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# duplicate stdin to be restored later |
211
|
1034
|
|
|
|
|
1673
|
my $ORIGSTDIN; |
212
|
1034
|
50
|
0
|
|
|
53105
|
NON_UNIX |
|
|
50
|
|
|
|
|
|
213
|
|
|
|
|
|
|
? open($ORIGSTDIN, "<&=STDIN") |
214
|
|
|
|
|
|
|
: open($ORIGSTDIN, "<&STDIN") |
215
|
|
|
|
|
|
|
or carp("IPC::Exe::exe() cannot dup STDIN", "\n ", $!) |
216
|
|
|
|
|
|
|
and return (); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# safe pipe open to forked child connected to opened filehandle |
219
|
1034
|
|
|
|
|
6671
|
my $gotchild = _pipe_from_fork(my $EXE_READ, my $EXE_GO); |
220
|
1034
|
|
|
|
|
24740
|
my $defined_child = defined($gotchild); |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# check if fork was successful |
223
|
1034
|
50
|
|
|
|
15351
|
unless ($defined_child) |
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
|
|
0
|
carp("IPC::Exe::exe() cannot fork child", "\n ", $!); |
226
|
0
|
|
|
|
|
0
|
return (); |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# parent reads stdout of child process |
230
|
1034
|
100
|
|
|
|
36225
|
if ($gotchild) |
231
|
|
|
|
|
|
|
{ |
232
|
|
|
|
|
|
|
# unneeded stuff |
233
|
990
|
|
|
|
|
143774
|
undef $_ for $Preexec, $_args, @redirs; |
234
|
990
|
100
|
|
|
|
14460
|
close($FOR_STDIN) if $FOR_STDIN; |
235
|
990
|
100
|
|
|
|
3559
|
close($BY_STDERR) if $BY_STDERR; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# set binmode if required |
238
|
990
|
50
|
33
|
|
|
3333
|
if (defined($IPC::Exe::_binmode_io) |
239
|
|
|
|
|
|
|
&& index($IPC::Exe::_binmode_io, ":") == 0) |
240
|
|
|
|
|
|
|
{ |
241
|
0
|
|
|
|
|
0
|
my $layer = $IPC::Exe::_binmode_io; |
242
|
|
|
|
|
|
|
|
243
|
0
|
0
|
|
|
|
0
|
if ($opt{stdin}) |
244
|
|
|
|
|
|
|
{ |
245
|
0
|
0
|
|
|
|
0
|
binmode($TO_STDIN, $layer) or croak(<<"EOT", " ", $!); |
246
|
|
|
|
|
|
|
IPC::Exe::exe() cannot set binmode STDIN_WRITEHANDLE for layer "$layer" |
247
|
|
|
|
|
|
|
EOT |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
0
|
0
|
|
|
|
0
|
binmode($EXE_READ, $layer) or croak(<<"EOT", " ", $!); |
251
|
|
|
|
|
|
|
IPC::Exe::exe() cannot set binmode STDOUT_READHANDLE for layer "$layer" |
252
|
|
|
|
|
|
|
EOT |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
990
|
|
|
|
|
1583
|
my (@ret, @status_reader); |
256
|
|
|
|
|
|
|
|
257
|
990
|
100
|
|
|
|
8436
|
if ($Reader) |
|
|
100
|
|
|
|
|
|
258
|
|
|
|
|
|
|
{ |
259
|
|
|
|
|
|
|
# non-Unix: reset to default $IPC::Exe::_preexec_wait time |
260
|
798
|
|
|
|
|
7897
|
local $IPC::Exe::_preexec_wait; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# temporarily replace stdin |
263
|
798
|
100
|
|
|
|
224168
|
$IPC::Exe::_stdin |
|
|
50
|
|
|
|
|
|
264
|
|
|
|
|
|
|
? open(*STDIN, "<&=", $EXE_READ) |
265
|
|
|
|
|
|
|
: open(*STDIN, "<&", $EXE_READ) |
266
|
|
|
|
|
|
|
or croak("IPC::Exe::exe() cannot replace STDIN", "\n ", $!); |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# create local package-scope $IPC::Exe::PIPE |
269
|
798
|
|
|
|
|
8114
|
local our $PIPE = $EXE_READ; |
270
|
|
|
|
|
|
|
|
271
|
798
|
|
|
|
|
49850
|
($?, $!, $^E, my $err) = @status; |
272
|
|
|
|
|
|
|
|
273
|
798
|
|
|
|
|
12228
|
my $failed = ! eval { |
274
|
798
|
|
|
|
|
1400
|
$@ = $err; |
275
|
798
|
|
|
|
|
87864
|
@ret = $Reader->($gotchild, @cmd_list); |
276
|
737
|
|
|
|
|
1307324611
|
$err = $@; |
277
|
737
|
|
|
|
|
3355
|
1; |
278
|
|
|
|
|
|
|
}; |
279
|
|
|
|
|
|
|
|
280
|
781
|
100
|
|
|
|
15147
|
@status_reader = ($?, -+-$!, -+-$^E, $failed ? $@ : $err); |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# restore stdin |
283
|
781
|
50
|
|
|
|
37500
|
NON_UNIX |
|
|
50
|
|
|
|
|
|
284
|
|
|
|
|
|
|
? open(*STDIN, "<&=", $ORIGSTDIN) |
285
|
|
|
|
|
|
|
: open(*STDIN, "<&", $ORIGSTDIN) |
286
|
|
|
|
|
|
|
or croak("IPC::Exe::exe() cannot restore STDIN", "\n ", $!); |
287
|
|
|
|
|
|
|
|
288
|
781
|
100
|
|
|
|
33639707
|
die $status_reader[3] if $failed; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
elsif (!$opt{stdout}) |
291
|
|
|
|
|
|
|
{ |
292
|
|
|
|
|
|
|
# default &READER just prints stdin |
293
|
187
|
|
|
|
|
2606075684
|
while (my $read = <$EXE_READ>) |
294
|
|
|
|
|
|
|
{ |
295
|
0
|
|
|
|
|
0
|
print $read; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
# do not wait for interactive children |
300
|
929
|
|
|
|
|
2290
|
my $reap = 0; |
301
|
929
|
50
|
66
|
|
|
17657
|
unless ($IPC::Exe::_stdin || $opt{stdout} || $opt{stderr}) |
|
|
|
66
|
|
|
|
|
302
|
|
|
|
|
|
|
{ |
303
|
920
|
|
|
|
|
358308763
|
$reap = waitpid($gotchild, 0); |
304
|
920
|
|
|
|
|
7916
|
$status[0] = $?; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
#print STDERR "reap> $gotchild : $reap | $status[0]\n"; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
# record status and close pipe for default &READER |
310
|
929
|
100
|
66
|
|
|
5567
|
if (!$Reader && !$opt{stdout}) |
311
|
|
|
|
|
|
|
{ |
312
|
187
|
|
|
|
|
1339
|
$ret[0] = $status[0]; |
313
|
187
|
|
|
|
|
4238
|
close($EXE_READ); |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
929
|
|
|
|
|
2231
|
my $ret_pid = $gotchild; |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# reading from failed exec |
319
|
929
|
100
|
100
|
|
|
9525
|
if ($status[0] == -1 || $status[0] == 255 << 8) # 255 (assumed as failed exec) |
320
|
|
|
|
|
|
|
{ |
321
|
|
|
|
|
|
|
# must correctly reap before we decide to return undef PID |
322
|
|
|
|
|
|
|
# if using default &READER, additionally check if we reaped -1 |
323
|
|
|
|
|
|
|
# and return -1 since it looks like a failed exec |
324
|
|
|
|
|
|
|
|
325
|
232
|
100
|
100
|
|
|
9393
|
$ret_pid = undef |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
326
|
|
|
|
|
|
|
if (!$Reader && !$opt{stdout} # using default &READER |
327
|
|
|
|
|
|
|
&& ($reap == $gotchild || $reap == -1 || $reap == 0) |
328
|
|
|
|
|
|
|
&& ($ret[0] = -1)) # return -1 |
329
|
|
|
|
|
|
|
|| $reap == $gotchild; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# writing to failed exec |
333
|
929
|
50
|
100
|
|
|
4564
|
if ($status[0] == -1 && $Reader && $reap == $gotchild && @ret) |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
334
|
|
|
|
|
|
|
{ |
335
|
|
|
|
|
|
|
# child PID is undef if exec failed |
336
|
0
|
|
|
|
|
0
|
$ret[0] = undef; |
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# assign scalar references if provided |
340
|
929
|
100
|
|
|
|
8087
|
${ $opt{pid} } = $ret_pid if _reftype($opt{pid}) eq "SCALAR"; |
|
3
|
|
|
|
|
120
|
|
341
|
929
|
50
|
|
|
|
5560
|
${ $opt{stdin} } = $TO_STDIN if _reftype($opt{stdin}) eq "SCALAR"; |
|
0
|
|
|
|
|
0
|
|
342
|
929
|
50
|
|
|
|
2602
|
${ $opt{stdout} } = $EXE_READ if _reftype($opt{stdout}) eq "SCALAR"; |
|
0
|
|
|
|
|
0
|
|
343
|
929
|
100
|
|
|
|
2858
|
${ $opt{stderr} } = $FROM_STDERR if _reftype($opt{stderr}) eq "SCALAR"; |
|
3
|
|
|
|
|
48
|
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# collect child PIDs & filehandle(s) |
346
|
929
|
100
|
66
|
|
|
2877
|
unshift(@ret, |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
347
|
|
|
|
|
|
|
_reftype($opt{pid}) ne "SCALAR" ? $ret_pid : (), |
348
|
|
|
|
|
|
|
$opt{stdin} && _reftype($opt{stdin}) ne "SCALAR" ? $TO_STDIN : (), |
349
|
|
|
|
|
|
|
$opt{stdout} && _reftype($opt{stdout}) ne "SCALAR" ? $EXE_READ : (), |
350
|
|
|
|
|
|
|
$opt{stderr} && _reftype($opt{stderr}) ne "SCALAR" ? $FROM_STDERR : (), |
351
|
|
|
|
|
|
|
); |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# restore exit status |
354
|
929
|
100
|
|
|
|
15017
|
($?, $!, $^E, $@) = @status_reader ? @status_reader : @status; |
355
|
|
|
|
|
|
|
|
356
|
929
|
|
|
|
|
2537
|
undef $Reader; |
357
|
|
|
|
|
|
|
|
358
|
929
|
|
|
|
|
65145
|
return @ret[0 .. $#ret]; # return LIST instead of ARRAY |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
else # child performs exec() |
361
|
|
|
|
|
|
|
{ |
362
|
|
|
|
|
|
|
# set package-scope $IPC::Exe::is_forked |
363
|
44
|
|
|
|
|
2951
|
$is_forked = 1; |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# disassociate any ties with parent |
366
|
44
|
|
|
|
|
2216
|
untie(*STDIN); |
367
|
44
|
|
|
|
|
598
|
untie(*STDOUT); |
368
|
44
|
|
|
|
|
1221
|
untie(*STDERR); |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# unneeded stuff |
371
|
44
|
|
|
|
|
527
|
undef $Reader; |
372
|
44
|
100
|
|
|
|
3211
|
close($TO_STDIN) if $TO_STDIN; |
373
|
44
|
100
|
|
|
|
2822
|
close($FROM_STDERR) if $FROM_STDERR; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# change STDIN if input filehandle was required |
376
|
44
|
100
|
|
|
|
1528
|
if ($FOR_STDIN) |
377
|
|
|
|
|
|
|
{ |
378
|
3
|
50
|
|
|
|
292
|
open(*STDIN, "<&=", $FOR_STDIN) |
379
|
|
|
|
|
|
|
or croak("IPC::Exe::exe() cannot change STDIN", "\n ", $!); |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# collect STDERR if error filehandle was required |
383
|
44
|
100
|
|
|
|
1111
|
if ($BY_STDERR) |
384
|
|
|
|
|
|
|
{ |
385
|
2
|
50
|
|
|
|
304
|
open(*STDERR, ">&=", $BY_STDERR) |
386
|
|
|
|
|
|
|
or croak("IPC::Exe::exe() cannot collect STDERR", "\n ", $!); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# set binmode if required |
390
|
44
|
50
|
33
|
|
|
7577
|
if (defined($IPC::Exe::_binmode_io) |
391
|
|
|
|
|
|
|
&& index($IPC::Exe::_binmode_io, ":") == 0) |
392
|
|
|
|
|
|
|
{ |
393
|
0
|
|
|
|
|
0
|
my $layer = $IPC::Exe::_binmode_io; |
394
|
|
|
|
|
|
|
|
395
|
0
|
0
|
0
|
|
|
0
|
binmode(*STDIN, $layer) and binmode(*STDOUT, $layer) |
396
|
|
|
|
|
|
|
or croak(<<"EOT", " ", $!); |
397
|
|
|
|
|
|
|
IPC::Exe::exe() cannot set binmode STDIN and STDOUT for layer "$layer" |
398
|
|
|
|
|
|
|
EOT |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# call PREEXEC subroutine if defined |
402
|
44
|
|
|
|
|
388
|
my @FHops; |
403
|
44
|
100
|
|
|
|
403
|
if ($Preexec) |
404
|
|
|
|
|
|
|
{ |
405
|
21
|
|
|
|
|
5593
|
local ($?, $!, $^E, $@) = @status; |
406
|
21
|
100
|
|
|
|
1618
|
@FHops = $Preexec->($_args ? @{ $_args } : ()); |
|
5
|
|
|
|
|
599
|
|
407
|
21
|
|
|
|
|
5102
|
undef $_ for $Preexec, $_args, @redirs; |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
# manually flush STDERR and STDOUT |
411
|
44
|
50
|
|
|
|
1410
|
select((select(*STDERR), $| = ($|++, print "")[0])[0]) if _is_fh(*STDERR); |
412
|
44
|
50
|
|
|
|
1052
|
select((select(*STDOUT), $| = ($|++, print "")[0])[0]) if _is_fh(*STDOUT); |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# only exec() LIST if defined |
415
|
44
|
100
|
|
|
|
266
|
unless (@cmd_list) |
416
|
|
|
|
|
|
|
{ |
417
|
|
|
|
|
|
|
# non-Unix: signal parent "process" to restore filehandles |
418
|
4
|
50
|
33
|
|
|
288
|
if (NON_UNIX && _is_fh($EXE_GO)) |
419
|
|
|
|
|
|
|
{ |
420
|
0
|
|
|
|
|
0
|
print $EXE_GO "exe_no_exec\n"; |
421
|
0
|
|
|
|
|
0
|
close($EXE_GO); |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
4
|
|
|
|
|
84
|
_quit(0); |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
# perform redirections |
428
|
40
|
|
|
|
|
586
|
my @FHs; |
429
|
40
|
|
|
|
|
504
|
for (@FHops) |
430
|
|
|
|
|
|
|
{ |
431
|
21
|
100
|
|
|
|
464
|
if (ref($_)) |
432
|
|
|
|
|
|
|
{ |
433
|
13
|
|
|
|
|
27
|
my $is_sysopen = 0; |
434
|
|
|
|
|
|
|
|
435
|
13
|
100
|
|
|
|
76
|
if (_reftype($_) =~ /REF|SCALAR/) |
436
|
|
|
|
|
|
|
{ |
437
|
12
|
|
|
|
|
71
|
$_ = ${ $_ }; |
|
12
|
|
|
|
|
161
|
|
438
|
12
|
|
|
|
|
39
|
++$is_sysopen; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# open / sysopen |
442
|
13
|
100
|
|
|
|
177
|
if (_reftype($_) eq "ARRAY") |
443
|
|
|
|
|
|
|
{ |
444
|
1
|
|
|
|
|
3
|
my @args = @{ $_ }; |
|
1
|
|
|
|
|
3
|
|
445
|
1
|
|
|
|
|
3
|
my $FH_name; |
446
|
|
|
|
|
|
|
|
447
|
1
|
50
|
33
|
|
|
41
|
if (!$is_sysopen && defined($args[0])) |
448
|
|
|
|
|
|
|
{ |
449
|
1
|
|
|
|
|
38
|
my ($src, $op) = ($args[0] =~ OPEN_RDWR_RX); |
450
|
|
|
|
|
|
|
|
451
|
1
|
50
|
|
|
|
4
|
if (defined($op)) |
452
|
|
|
|
|
|
|
{ |
453
|
1
|
0
|
|
|
|
4
|
$src = (index($op, "<") == -1) ? 1 : 0 |
|
|
50
|
|
|
|
|
|
454
|
|
|
|
|
|
|
if $src eq ""; |
455
|
|
|
|
|
|
|
|
456
|
1
|
|
|
|
|
18
|
(my $FH, $FH_name) = _fh_slot(\@FHs, $src); |
457
|
1
|
|
|
|
|
5
|
shift @args; |
458
|
1
|
|
|
|
|
4
|
unshift @args, ($FH, $op); |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
1
|
50
|
|
|
|
25
|
my $error_msg = |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
463
|
|
|
|
|
|
|
"IPC::Exe::exe() failed " |
464
|
|
|
|
|
|
|
. ($is_sysopen ? "sysopen" : "open") . "( " |
465
|
|
|
|
|
|
|
. ($FH_name ? "$FH_name, " : "") |
466
|
|
|
|
|
|
|
. _stringify_args( |
467
|
|
|
|
|
|
|
$FH_name ? () : $args[0], |
468
|
|
|
|
|
|
|
@args[1 .. $#args], |
469
|
|
|
|
|
|
|
) . " )"; |
470
|
|
|
|
|
|
|
|
471
|
1
|
50
|
0
|
|
|
415
|
croak($error_msg, "\n ", $! = 22) |
|
|
50
|
|
|
|
|
|
472
|
|
|
|
|
|
|
if $is_sysopen |
473
|
|
|
|
|
|
|
? (@args < 3 || @args > 4) |
474
|
|
|
|
|
|
|
: (@args == 0); |
475
|
|
|
|
|
|
|
|
476
|
1
|
0
|
|
|
|
85
|
$is_sysopen |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
477
|
|
|
|
|
|
|
? (@args == 4 |
478
|
|
|
|
|
|
|
? sysopen($args[0], $args[1], $args[2], $args[3]) |
479
|
|
|
|
|
|
|
: sysopen($args[0], $args[1], $args[2]) |
480
|
|
|
|
|
|
|
) |
481
|
|
|
|
|
|
|
: open( |
482
|
|
|
|
|
|
|
$args[0], |
483
|
|
|
|
|
|
|
@args >= 2 ? $args[1] : (), |
484
|
|
|
|
|
|
|
@args >= 3 ? $args[2] : (), |
485
|
|
|
|
|
|
|
@args[3 .. $#args], |
486
|
|
|
|
|
|
|
) |
487
|
|
|
|
|
|
|
or croak($error_msg, "\n ", $!); |
488
|
|
|
|
|
|
|
|
489
|
1
|
|
|
|
|
10
|
next; |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
|
493
|
20
|
50
|
|
|
|
95
|
next unless defined($_); |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
# set binmode |
496
|
20
|
50
|
|
|
|
359
|
if (/^\s*([012])\s*(:.*)$/) |
497
|
|
|
|
|
|
|
{ |
498
|
0
|
|
|
|
|
0
|
my $FH_name = qw(STDIN STDOUT STDERR)[$1]; |
499
|
0
|
|
|
|
|
0
|
my $layer = $2; |
500
|
0
|
0
|
|
|
|
0
|
$layer = ":raw" if $layer eq ":"; |
501
|
|
|
|
|
|
|
|
502
|
0
|
0
|
|
|
|
0
|
binmode((*STDIN, *STDOUT, *STDERR)[$1], $layer) |
503
|
|
|
|
|
|
|
or croak(<<"EOT", " ", $!); |
504
|
|
|
|
|
|
|
IPC::Exe::exe() cannot set binmode $FH_name for layer "$layer" |
505
|
|
|
|
|
|
|
EOT |
506
|
0
|
|
|
|
|
0
|
next; |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# silence filehandles |
510
|
20
|
100
|
|
|
|
1209
|
if (/^\s*(\d*)\s*>\s*(?:null|#)\s*$/) |
511
|
|
|
|
|
|
|
{ |
512
|
11
|
100
|
|
|
|
547
|
my $src = ($1 eq "") ? 1 : $1; |
513
|
11
|
|
|
|
|
206
|
my ($FH, $FH_name) = _fh_slot(\@FHs, $src); |
514
|
|
|
|
|
|
|
|
515
|
11
|
50
|
|
|
|
3914
|
open($FH, ">", $DEVNULL) |
516
|
|
|
|
|
|
|
or croak(<<"EOT", " ", $!); |
517
|
|
|
|
|
|
|
IPC::Exe::exe() cannot silence $FH_name (does $DEVNULL exist?) |
518
|
|
|
|
|
|
|
EOT |
519
|
11
|
|
|
|
|
189
|
next; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# swap filehandles |
523
|
9
|
50
|
|
|
|
90
|
if (/^\s*(\d+)\s*><\s*(\d+)\s*$/) |
524
|
|
|
|
|
|
|
{ |
525
|
0
|
|
|
|
|
0
|
my ($FH1, $FH_name1) = _fh_slot(\@FHs, $1); |
526
|
0
|
|
|
|
|
0
|
my ($FH2, $FH_name2) = _fh_slot(\@FHs, $2); |
527
|
|
|
|
|
|
|
|
528
|
0
|
|
|
|
|
0
|
my $SWAP; |
529
|
0
|
|
|
|
|
0
|
local $! = 9; |
530
|
0
|
0
|
0
|
|
|
0
|
_is_fh($FH1) && _is_fh($FH2) |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
531
|
|
|
|
|
|
|
&& open($SWAP, ">&", $FH1) |
532
|
|
|
|
|
|
|
&& open($FH1, ">&", $FH2) |
533
|
|
|
|
|
|
|
&& open($FH2, ">&=", $SWAP) |
534
|
|
|
|
|
|
|
or croak(<<"EOT", " ", $!); |
535
|
|
|
|
|
|
|
IPC::Exe::exe() cannot swap $FH_name1 and $FH_name2 |
536
|
|
|
|
|
|
|
EOT |
537
|
0
|
|
|
|
|
0
|
next; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
# redirect/close filehandles |
541
|
9
|
|
|
|
|
117
|
my ($src, $op, $tgt) = |
542
|
|
|
|
|
|
|
/^\s*(\d*)\s*(\+?(?:<|>>?)&=?)\s*(\d+|-)\s*$/; |
543
|
|
|
|
|
|
|
|
544
|
9
|
100
|
|
|
|
51
|
if (defined($op)) |
545
|
|
|
|
|
|
|
{ |
546
|
8
|
0
|
|
|
|
42
|
$src = (index($op, "<") == -1) ? 1 : 0 |
|
|
50
|
|
|
|
|
|
547
|
|
|
|
|
|
|
if $src eq ""; |
548
|
|
|
|
|
|
|
|
549
|
8
|
|
|
|
|
58
|
my ($FH1, $FH_name1) = _fh_slot(\@FHs, $src); |
550
|
|
|
|
|
|
|
|
551
|
8
|
100
|
|
|
|
31
|
if ($tgt eq "-") |
552
|
|
|
|
|
|
|
{ |
553
|
2
|
50
|
|
|
|
10
|
close($FH1) or croak(<<"EOT", " ", $!); |
554
|
|
|
|
|
|
|
IPC::Exe::exe() failed to close $FH_name1 |
555
|
|
|
|
|
|
|
EOT |
556
|
2
|
|
|
|
|
5
|
next; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
6
|
|
|
|
|
153
|
my ($FH2, $FH_name2) = _fh_slot(\@FHs, $tgt); |
560
|
|
|
|
|
|
|
|
561
|
6
|
|
|
|
|
33
|
local $! = 9; |
562
|
6
|
50
|
33
|
|
|
51
|
_is_fh($FH2) && open($FH1, $op, $FH2) |
563
|
|
|
|
|
|
|
or croak(<<"EOT", " ", $!); |
564
|
|
|
|
|
|
|
IPC::Exe::exe() failed redirect $FH_name1 $op $FH_name2 |
565
|
|
|
|
|
|
|
EOT |
566
|
6
|
|
|
|
|
54
|
next; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
1
|
50
|
|
|
|
6
|
if ($_ =~ OPEN_RDWR_RX) |
570
|
|
|
|
|
|
|
{ |
571
|
0
|
|
|
|
|
0
|
$_ = [ $_ ]; |
572
|
0
|
|
|
|
|
0
|
redo; |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# non-Unix: escape command so that it feels Unix-like |
577
|
40
|
|
|
|
|
1092
|
my @cmd = _escape_cmd_list(@cmd_list); |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
# non-Unix: signal parent "process" to restore filehandles |
580
|
40
|
|
33
|
|
|
1314
|
my $restore_fh = (NON_UNIX && _is_fh($EXE_GO)); |
581
|
|
|
|
|
|
|
|
582
|
46
|
|
|
46
|
|
776
|
no warnings qw(exec); |
|
46
|
|
|
|
|
146
|
|
|
46
|
|
|
|
|
2763
|
|
583
|
|
|
|
|
|
|
# XXX: be quiet about "Attempt to free unreferenced scalar" for Win32 |
584
|
46
|
|
|
46
|
|
276
|
no warnings qw(internal); |
|
46
|
|
|
|
|
93
|
|
|
46
|
|
|
|
|
100726
|
|
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# assume exit status 255 indicates failed exec |
587
|
40
|
|
|
|
|
0
|
($restore_fh ? print $EXE_GO "exe_with_exec\n" : 1) |
588
|
40
|
50
|
0
|
|
|
923
|
and exec { $cmd[0] } @cmd |
|
|
0
|
33
|
|
|
|
|
589
|
|
|
|
|
|
|
or carp("IPC::Exe::exe() failed to exec the command below", " - ", $!, "\n ", |
590
|
|
|
|
|
|
|
_stringify_args(@cmd), "\n") |
591
|
|
|
|
|
|
|
and _quit(-1); |
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
sub bg { |
596
|
45
|
50
|
|
45
|
1
|
360
|
return () if @_ == 0; |
597
|
|
|
|
|
|
|
|
598
|
0
|
|
|
|
|
0
|
my $args = \@_; |
599
|
0
|
0
|
|
0
|
|
0
|
return sub { _bg(@_ ? [ @_ ] : undef, @{ $args }) }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
sub _bg { |
602
|
|
|
|
|
|
|
# record error variables |
603
|
0
|
|
|
0
|
|
0
|
my @status = ($?, -+-$!, -+-$^E, $@); |
604
|
0
|
|
|
|
|
0
|
local ($?, $!, $^E, $@); |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
# ref to arguments passed to closure |
607
|
0
|
|
|
|
|
0
|
my $_args = shift; |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
# merge options hash reference, if available |
610
|
0
|
|
|
|
|
0
|
my %opt = ( |
611
|
|
|
|
|
|
|
wait => 2, |
612
|
|
|
|
|
|
|
); |
613
|
0
|
|
|
|
|
0
|
my $opt_ref = $_[0]; |
614
|
0
|
0
|
|
|
|
0
|
if (_reftype($opt_ref) eq "HASH") |
615
|
|
|
|
|
|
|
{ |
616
|
0
|
|
|
|
|
0
|
@opt{keys %{ $opt_ref }} = values %{ $opt_ref }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
617
|
0
|
|
|
|
|
0
|
shift; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# CODE reference for BACKGROUND subroutine |
621
|
0
|
|
|
|
|
0
|
my $Background; |
622
|
0
|
0
|
|
|
|
0
|
$Background = shift if _reftype($_[0]) eq "CODE"; |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# do not continue if no BACKGROUND found |
625
|
0
|
0
|
|
|
|
0
|
return () unless defined($Background); |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# non-Unix: set longer $IPC::Exe::_preexec_wait time |
628
|
0
|
|
|
|
|
0
|
local $IPC::Exe::_preexec_wait = 2; |
629
|
0
|
0
|
0
|
|
|
0
|
if (defined($opt{wait}) && $opt{wait} >= 0) |
630
|
|
|
|
|
|
|
{ |
631
|
0
|
|
|
|
|
0
|
$IPC::Exe::_preexec_wait = $opt{wait}; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
# dup(2) stdout |
635
|
0
|
|
|
|
|
0
|
my $ORIGSTDOUT; |
636
|
0
|
0
|
0
|
|
|
0
|
open($ORIGSTDOUT, ">&STDOUT") |
637
|
|
|
|
|
|
|
or carp("IPC::Exe::bg() cannot dup STDOUT", "\n ", $!) |
638
|
|
|
|
|
|
|
and return (); |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
# double fork -- immediately wait() for child, |
641
|
|
|
|
|
|
|
# and init daemon will wait() for grandchild, once child exits |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
# safe pipe open to forked child connected to opened filehandle |
644
|
0
|
|
|
|
|
0
|
my $gotchild = _pipe_from_fork(my $BG_READ, my $BG_GO1); |
645
|
0
|
|
|
|
|
0
|
my $defined_child = defined($gotchild); |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
# check if fork was successful |
648
|
0
|
0
|
|
|
|
0
|
unless ($defined_child) |
649
|
|
|
|
|
|
|
{ |
650
|
0
|
0
|
|
|
|
0
|
if ($bg_fallback) |
651
|
|
|
|
|
|
|
{ |
652
|
0
|
|
|
|
|
0
|
carp("IPC::Exe::bg() cannot fork child, will try fork again", "\n ", $!); |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
else |
655
|
|
|
|
|
|
|
{ |
656
|
0
|
0
|
|
|
|
0
|
carp("IPC::Exe::bg() cannot fork child", "\n ", $!) and return (); |
657
|
|
|
|
|
|
|
} |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
# parent reads stdout of child process |
661
|
0
|
0
|
|
|
|
0
|
if ($gotchild) |
662
|
|
|
|
|
|
|
{ |
663
|
|
|
|
|
|
|
# background: parent reads output from child, |
664
|
|
|
|
|
|
|
# and waits for child to exit |
665
|
0
|
|
|
|
|
0
|
my $grandpid = readline($BG_READ); |
666
|
0
|
|
|
|
|
0
|
waitpid($gotchild, 0); |
667
|
0
|
|
|
|
|
0
|
my $status = $?; |
668
|
0
|
|
|
|
|
0
|
close($BG_READ); |
669
|
0
|
0
|
|
|
|
0
|
return $status ? $gotchild : -+-$grandpid; |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
else |
672
|
|
|
|
|
|
|
{ |
673
|
|
|
|
|
|
|
# background: perform second fork |
674
|
0
|
0
|
|
|
|
0
|
my $gotgrand = NON_UNIX |
675
|
|
|
|
|
|
|
? _pipe_from_fork(my $DUMMY, my $BG_GO2) |
676
|
|
|
|
|
|
|
: fork(); |
677
|
0
|
|
|
|
|
0
|
my $defined_grand = defined($gotgrand); |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
# check if second fork was successful |
680
|
0
|
0
|
|
|
|
0
|
if ($defined_child) |
681
|
|
|
|
|
|
|
{ |
682
|
0
|
0
|
|
|
|
0
|
$defined_grand or carp(<<"EOT", " ", $!); |
683
|
|
|
|
|
|
|
IPC::Exe::bg() cannot fork grandchild, using child instead |
684
|
|
|
|
|
|
|
-> parent must wait |
685
|
|
|
|
|
|
|
EOT |
686
|
|
|
|
|
|
|
} |
687
|
|
|
|
|
|
|
else |
688
|
|
|
|
|
|
|
{ |
689
|
0
|
0
|
|
|
|
0
|
if ($defined_grand) |
690
|
|
|
|
|
|
|
{ |
691
|
0
|
0
|
|
|
|
0
|
$gotgrand and carp(<<"EOT", " ", $!); |
692
|
|
|
|
|
|
|
IPC::Exe::bg() managed to fork child, using child now |
693
|
|
|
|
|
|
|
-> parent must wait |
694
|
|
|
|
|
|
|
EOT |
695
|
|
|
|
|
|
|
} |
696
|
|
|
|
|
|
|
else |
697
|
|
|
|
|
|
|
{ |
698
|
0
|
|
|
|
|
0
|
carp(<<"EOT", " ", $!); |
699
|
|
|
|
|
|
|
IPC::Exe::bg() cannot fork child again, using parent instead |
700
|
|
|
|
|
|
|
-> parent does all the work |
701
|
|
|
|
|
|
|
EOT |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
} |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
# send grand/child's PID to parent process somehow |
706
|
0
|
|
|
|
|
0
|
my $childpid; |
707
|
0
|
0
|
0
|
|
|
0
|
if ($defined_grand && $gotgrand) |
708
|
|
|
|
|
|
|
{ |
709
|
0
|
0
|
|
|
|
0
|
if ($defined_child) |
710
|
|
|
|
|
|
|
{ |
711
|
|
|
|
|
|
|
# child writes grandchild's PID to parent process |
712
|
0
|
|
|
|
|
0
|
print { *STDOUT } "$gotgrand\n"; |
|
0
|
|
|
|
|
0
|
|
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
else |
715
|
|
|
|
|
|
|
{ |
716
|
|
|
|
|
|
|
# parent returns child's PID later |
717
|
0
|
|
|
|
|
0
|
$childpid = $gotgrand; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
# child exits once grandchild is forked |
722
|
|
|
|
|
|
|
# grandchild calls BACKGROUND subroutine |
723
|
0
|
0
|
|
|
|
0
|
unless ($gotgrand) |
|
|
0
|
|
|
|
|
|
724
|
|
|
|
|
|
|
{ |
725
|
|
|
|
|
|
|
# set package-scope $IPC::Exe::is_forked |
726
|
0
|
|
|
|
|
0
|
$is_forked = 1; |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
# disassociate any ties with parent |
729
|
0
|
|
|
|
|
0
|
untie(*STDIN); |
730
|
0
|
|
|
|
|
0
|
untie(*STDOUT); |
731
|
0
|
|
|
|
|
0
|
untie(*STDERR); |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
# restore stdout |
734
|
0
|
0
|
|
|
|
0
|
open(*STDOUT, ">&=", $ORIGSTDOUT) |
735
|
|
|
|
|
|
|
or croak("IPC::Exe::bg() cannot restore STDOUT", "\n ", $!); |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
# non-Unix: signal parent/child "process" to restore filehandles |
738
|
0
|
0
|
|
|
|
0
|
if (NON_UNIX) |
739
|
|
|
|
|
|
|
{ |
740
|
0
|
0
|
|
|
|
0
|
if (_is_fh($BG_GO2)) |
741
|
|
|
|
|
|
|
{ |
742
|
0
|
|
|
|
|
0
|
print $BG_GO2 "bg2\n"; |
743
|
0
|
|
|
|
|
0
|
close($BG_GO2); |
744
|
|
|
|
|
|
|
} |
745
|
|
|
|
|
|
|
|
746
|
0
|
0
|
|
|
|
0
|
if (_is_fh($BG_GO1)) |
747
|
|
|
|
|
|
|
{ |
748
|
0
|
|
|
|
|
0
|
print $BG_GO1 "bg1\n"; |
749
|
0
|
|
|
|
|
0
|
close($BG_GO1); |
750
|
|
|
|
|
|
|
} |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
# BACKGROUND subroutine does not need to return |
754
|
0
|
|
|
|
|
0
|
($?, $!, $^E, $@) = @status; |
755
|
0
|
0
|
|
|
|
0
|
$Background->($_args ? @{ $_args } : ()); |
|
0
|
|
|
|
|
0
|
|
756
|
0
|
|
|
|
|
0
|
undef $_ for $Background, $_args; |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
elsif (!$defined_child) |
759
|
|
|
|
|
|
|
{ |
760
|
|
|
|
|
|
|
# parent must wait to reap child |
761
|
0
|
|
|
|
|
0
|
waitpid($gotgrand, 0); |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
# $gotchild $gotgrand exit |
765
|
|
|
|
|
|
|
# --------- --------- ---- |
766
|
|
|
|
|
|
|
# childpid grandpid both child & grandchild |
767
|
|
|
|
|
|
|
# childpid undef child |
768
|
|
|
|
|
|
|
# undef childpid child |
769
|
|
|
|
|
|
|
# undef undef none (parent executes BACKGROUND subroutine) |
770
|
0
|
0
|
0
|
|
|
0
|
_quit(0) if $defined_child && $defined_grand; |
771
|
0
|
0
|
0
|
|
|
0
|
_quit(10) if $defined_child && !$defined_grand; |
772
|
0
|
0
|
0
|
|
|
0
|
_quit(10) if !$defined_child && $defined_grand && !$gotgrand; |
|
|
|
0
|
|
|
|
|
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
# falls back here if forks were unsuccessful |
775
|
0
|
|
|
|
|
0
|
return $childpid; |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
} |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
# child writes while parent reads |
780
|
|
|
|
|
|
|
# simulate open(FILEHANDLE, "-|"); |
781
|
|
|
|
|
|
|
# http://perldoc.perl.org/perlfork.html#CAVEATS-AND-LIMITATIONS |
782
|
|
|
|
|
|
|
sub _pipe_from_fork ($$) { |
783
|
1034
|
|
|
1034
|
|
1293
|
my $pid; |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
# cannot fork on these platforms |
786
|
1034
|
50
|
|
|
|
29287
|
return undef if $^O =~ /^(?:VMS|dos|MacOS|riscos|amigaos|vmesa)$/; |
787
|
|
|
|
|
|
|
|
788
|
1034
|
50
|
|
|
|
3656
|
if (NON_UNIX) |
789
|
|
|
|
|
|
|
{ |
790
|
|
|
|
|
|
|
# dup(2) stdin/stdout/stderr to be restored later |
791
|
0
|
|
|
|
|
0
|
my ($ORIGSTDIN, $ORIGSTDOUT, $ORIGSTDERR); |
792
|
|
|
|
|
|
|
|
793
|
0
|
0
|
0
|
|
|
0
|
open($ORIGSTDIN, "<&STDIN") |
794
|
|
|
|
|
|
|
or carp("IPC::Exe cannot dup STDIN", "\n ", $!) |
795
|
|
|
|
|
|
|
and return undef; |
796
|
|
|
|
|
|
|
|
797
|
0
|
0
|
0
|
|
|
0
|
open($ORIGSTDOUT, ">&STDOUT") |
798
|
|
|
|
|
|
|
or carp("IPC::Exe cannot dup STDOUT", "\n ", $!) |
799
|
|
|
|
|
|
|
and return undef; |
800
|
|
|
|
|
|
|
|
801
|
0
|
0
|
0
|
|
|
0
|
open($ORIGSTDERR, ">&STDERR") |
802
|
|
|
|
|
|
|
or carp("IPC::Exe cannot dup STDERR", "\n ", $!) |
803
|
|
|
|
|
|
|
and return undef; |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
# create pipe for READHANDLE and WRITEHANDLE |
806
|
0
|
0
|
|
|
|
0
|
pipe($_[0], my $WRITE) or return undef; |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
# create pipe for READYHANDLE and GOHANDLE |
809
|
0
|
0
|
|
|
|
0
|
pipe(my $READY, $_[1]) or return undef; |
810
|
0
|
|
|
|
|
0
|
select((select($_[1]), $| = 1)[0]); |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
# fork is emulated with threads on Win32 |
813
|
0
|
0
|
|
|
|
0
|
if (defined($pid = fork())) |
814
|
|
|
|
|
|
|
{ |
815
|
0
|
0
|
|
|
|
0
|
if ($pid) |
816
|
|
|
|
|
|
|
{ |
817
|
0
|
|
|
|
|
0
|
close($WRITE); |
818
|
0
|
|
|
|
|
0
|
close($_[1]); |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
# block until signalled to GO! |
821
|
|
|
|
|
|
|
#print STDERR "go> " . readline($READY); |
822
|
0
|
|
|
|
|
0
|
readline($READY); |
823
|
0
|
|
|
|
|
0
|
close($READY); |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
# restore filehandles after slight delay to allow exec to happen |
826
|
0
|
|
|
|
|
0
|
my $wait = 0; # default |
827
|
0
|
0
|
|
|
|
0
|
$wait = $IPC::Exe::_preexec_wait |
828
|
|
|
|
|
|
|
if defined($IPC::Exe::_preexec_wait); |
829
|
|
|
|
|
|
|
|
830
|
0
|
|
|
|
|
0
|
usleep($wait * 1e6); |
831
|
|
|
|
|
|
|
#print STDERR "wait> $wait\n"; |
832
|
|
|
|
|
|
|
|
833
|
0
|
0
|
|
|
|
0
|
open(*STDIN, "<&=", $ORIGSTDIN) |
834
|
|
|
|
|
|
|
or croak("IPC::Exe cannot restore STDIN", "\n ", $!); |
835
|
|
|
|
|
|
|
|
836
|
0
|
0
|
|
|
|
0
|
open(*STDOUT, ">&=", $ORIGSTDOUT) |
837
|
|
|
|
|
|
|
or croak("IPC::Exe cannot restore STDOUT", "\n ", $!); |
838
|
|
|
|
|
|
|
|
839
|
0
|
0
|
|
|
|
0
|
open(*STDERR, ">&=", $ORIGSTDERR) |
840
|
|
|
|
|
|
|
or croak("IPC::Exe cannot restore STDERR", "\n ", $!); |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
else |
843
|
|
|
|
|
|
|
{ |
844
|
0
|
|
|
|
|
0
|
close($_[0]); |
845
|
0
|
|
|
|
|
0
|
close($READY); |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
# file descriptors are not "process"-persistent on Win32 |
848
|
0
|
0
|
|
|
|
0
|
open(*STDOUT, ">&=", $WRITE) |
849
|
|
|
|
|
|
|
or croak("IPC::Exe cannot establish IPC after fork", "\n ", $!); |
850
|
|
|
|
|
|
|
} |
851
|
|
|
|
|
|
|
} |
852
|
|
|
|
|
|
|
} |
853
|
|
|
|
|
|
|
else |
854
|
|
|
|
|
|
|
{ |
855
|
|
|
|
|
|
|
# need this form to allow close($_[0]) to set $? properly |
856
|
1034
|
|
|
|
|
2571753
|
$pid = open($_[0], "-|"); |
857
|
|
|
|
|
|
|
} |
858
|
|
|
|
|
|
|
|
859
|
1034
|
|
|
|
|
67560
|
return $pid; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
'IPC::Exe'; |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
__END__ |