File Coverage

blib/lib/Dpkg/IPC.pm
Criterion Covered Total %
statement 146 160 91.2
branch 91 124 73.3
condition 19 35 54.2
subroutine 10 10 100.0
pod 2 2 100.0
total 268 331 80.9


line stmt bran cond sub pod time code
1             # Copyright © 2008-2009 Raphaël Hertzog
2             # Copyright © 2008 Frank Lichtenheld
3             # Copyright © 2008-2010, 2012-2015 Guillem Jover
4             #
5             # This program is free software; you can redistribute it and/or modify
6             # it under the terms of the GNU General Public License as published by
7             # the Free Software Foundation; either version 2 of the License, or
8             # (at your option) any later version.
9             #
10             # This program is distributed in the hope that it will be useful,
11             # but WITHOUT ANY WARRANTY; without even the implied warranty of
12             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13             # GNU General Public License for more details.
14             #
15             # You should have received a copy of the GNU General Public License
16             # along with this program. If not, see .
17              
18             package Dpkg::IPC;
19              
20 547     547   303279 use strict;
  547         1091  
  547         16350  
21 547     547   3267 use warnings;
  547         1088  
  547         27334  
22              
23             our $VERSION = '1.02';
24             our @EXPORT = qw(
25             spawn
26             wait_child
27             );
28              
29 547     547   3261 use Carp;
  547         564  
  547         29096  
30 547     547   2801 use Exporter qw(import);
  547         1091  
  547         13804  
31              
32 547     547   5224 use Dpkg::ErrorHandling;
  547         568  
  547         55893  
33 547     547   3857 use Dpkg::Gettext;
  547         1104  
  547         993452  
34              
35             =encoding utf8
36              
37             =head1 NAME
38              
39             Dpkg::IPC - helper functions for IPC
40              
41             =head1 DESCRIPTION
42              
43             Dpkg::IPC offers helper functions to allow you to execute
44             other programs in an easy, yet flexible way, while hiding
45             all the gory details of IPC (Inter-Process Communication)
46             from you.
47              
48             =head1 FUNCTIONS
49              
50             =over 4
51              
52             =item $pid = spawn(%opts)
53              
54             Creates a child process and executes another program in it.
55             The arguments are interpreted as a hash of options, specifying
56             how to handle the in and output of the program to execute.
57             Returns the pid of the child process (unless the wait_child
58             option was given).
59              
60             Any error will cause the function to exit with one of the
61             Dpkg::ErrorHandling functions.
62              
63             Options:
64              
65             =over 4
66              
67             =item exec
68              
69             Can be either a scalar, i.e. the name of the program to be
70             executed, or an array reference, i.e. the name of the program
71             plus additional arguments. Note that the program will never be
72             executed via the shell, so you can't specify additional arguments
73             in the scalar string and you can't use any shell facilities like
74             globbing.
75              
76             Mandatory Option.
77              
78             =item from_file, to_file, error_to_file
79              
80             Filename as scalar. Standard input/output/error of the
81             child process will be redirected to the file specified.
82              
83             =item from_handle, to_handle, error_to_handle
84              
85             Filehandle. Standard input/output/error of the child process will be
86             dup'ed from the handle.
87              
88             =item from_pipe, to_pipe, error_to_pipe
89              
90             Scalar reference or object based on IO::Handle. A pipe will be opened for
91             each of the two options and either the reading (C and
92             C) or the writing end (C) will be returned in
93             the referenced scalar. Standard input/output/error of the child process
94             will be dup'ed to the other ends of the pipes.
95              
96             =item from_string, to_string, error_to_string
97              
98             Scalar reference. Standard input/output/error of the child
99             process will be redirected to the string given as reference. Note
100             that it wouldn't be strictly necessary to use a scalar reference
101             for C, as the string is not modified in any way. This was
102             chosen only for reasons of symmetry with C and
103             C. C and C imply the
104             C option.
105              
106             =item wait_child
107              
108             Scalar. If containing a true value, wait_child() will be called before
109             returning. The return value of spawn() will be a true value, not the pid.
110              
111             =item nocheck
112              
113             Scalar. Option of the wait_child() call.
114              
115             =item timeout
116              
117             Scalar. Option of the wait_child() call.
118              
119             =item chdir
120              
121             Scalar. The child process will chdir in the indicated directory before
122             calling exec.
123              
124             =item env
125              
126             Hash reference. The child process will populate %ENV with the items of the
127             hash before calling exec. This allows exporting environment variables.
128              
129             =item delete_env
130              
131             Array reference. The child process will remove all environment variables
132             listed in the array before calling exec.
133              
134             =item sig
135              
136             Hash reference. The child process will populate %SIG with the items of the
137             hash before calling exec. This allows setting signal dispositions.
138              
139             =item delete_sig
140              
141             Array reference. The child process will reset all signals listed in the
142             array to their default dispositions before calling exec.
143              
144             =back
145              
146             =cut
147              
148             sub _sanity_check_opts {
149 133939     133939   442995 my (%opts) = @_;
150              
151             croak 'exec parameter is mandatory in spawn()'
152 133939 50       536518 unless $opts{exec};
153              
154 133939         351314 my $to = my $error_to = my $from = 0;
155 133939         386550 foreach my $thing (qw(file handle string pipe)) {
156 535756 100       1134653 $to++ if $opts{"to_$thing"};
157 535756 100       1140662 $error_to++ if $opts{"error_to_$thing"};
158 535756 100       1262012 $from++ if $opts{"from_$thing"};
159             }
160 133939 50       420418 croak 'not more than one of to_* parameters is allowed'
161             if $to > 1;
162 133939 50       356134 croak 'not more than one of error_to_* parameters is allowed'
163             if $error_to > 1;
164 133939 50       404266 croak 'not more than one of from_* parameters is allowed'
165             if $from > 1;
166              
167 133939         299378 foreach my $param (qw(to_string error_to_string from_string)) {
168 401817 50 33     3453863 if (exists $opts{$param} and
      66        
169             (not ref $opts{$param} or ref $opts{$param} ne 'SCALAR')) {
170 0         0 croak "parameter $param must be a scalar reference";
171             }
172             }
173              
174 133939         375400 foreach my $param (qw(to_pipe error_to_pipe from_pipe)) {
175 401817 50 33     971817 if (exists $opts{$param} and
      66        
176             (not ref $opts{$param} or (ref $opts{$param} ne 'SCALAR' and
177             not $opts{$param}->isa('IO::Handle')))) {
178 0         0 croak "parameter $param must be a scalar reference or " .
179             'an IO::Handle object';
180             }
181             }
182              
183 133939 50 66     532203 if (exists $opts{timeout} and defined($opts{timeout}) and
      66        
184             $opts{timeout} !~ /^\d+$/) {
185 0         0 croak 'parameter timeout must be an integer';
186             }
187              
188 133939 50 66     402923 if (exists $opts{env} and ref($opts{env}) ne 'HASH') {
189 0         0 croak 'parameter env must be a hash reference';
190             }
191              
192 133939 50 66     466889 if (exists $opts{delete_env} and ref($opts{delete_env}) ne 'ARRAY') {
193 0         0 croak 'parameter delete_env must be an array reference';
194             }
195              
196 133939 50 33     402313 if (exists $opts{sig} and ref($opts{sig}) ne 'HASH') {
197 0         0 croak 'parameter sig must be a hash reference';
198             }
199              
200 133939 50 33     400204 if (exists $opts{delete_sig} and ref($opts{delete_sig}) ne 'ARRAY') {
201 0         0 croak 'parameter delete_sig must be an array reference';
202             }
203              
204 133939         433014 return %opts;
205             }
206              
207             sub spawn {
208 133939     133939 1 787527 my (%opts) = @_;
209 133939         257197 my @prog;
210              
211 133939         702393 _sanity_check_opts(%opts);
212 133939   50     2002081 $opts{close_in_child} //= [];
213 133939 100       2582851 if (ref($opts{exec}) =~ /ARRAY/) {
    50          
214 133927         388157 push @prog, @{$opts{exec}};
  133927         575096  
215             } elsif (not ref($opts{exec})) {
216 12         32 push @prog, $opts{exec};
217             } else {
218 0         0 croak 'invalid exec parameter in spawn()';
219             }
220 133939         306431 my ($from_string_pipe, $to_string_pipe, $error_to_string_pipe);
221 133939 100       393503 if ($opts{to_string}) {
222 10         30 $opts{to_pipe} = \$to_string_pipe;
223 10         23 $opts{wait_child} = 1;
224             }
225 133939 100       491603 if ($opts{error_to_string}) {
226 133907         449586 $opts{error_to_pipe} = \$error_to_string_pipe;
227 133907         292467 $opts{wait_child} = 1;
228             }
229 133939 100       442815 if ($opts{from_string}) {
230 5         10 $opts{from_pipe} = \$from_string_pipe;
231             }
232             # Create pipes if needed
233 133939         246920 my ($input_pipe, $output_pipe, $error_pipe);
234 133939 100       524296 if ($opts{from_pipe}) {
235 18 50       798 pipe($opts{from_handle}, $input_pipe)
236             or syserr(g_('pipe for %s'), "@prog");
237 18         49 ${$opts{from_pipe}} = $input_pipe;
  18         51  
238 18         29 push @{$opts{close_in_child}}, $input_pipe;
  18         61  
239             }
240 133939 100       458370 if ($opts{to_pipe}) {
241             pipe($output_pipe, $opts{to_handle})
242 19 50       853 or syserr(g_('pipe for %s'), "@prog");
243 19         62 ${$opts{to_pipe}} = $output_pipe;
  19         67  
244 19         45 push @{$opts{close_in_child}}, $output_pipe;
  19         69  
245             }
246 133939 100       481685 if ($opts{error_to_pipe}) {
247             pipe($error_pipe, $opts{error_to_handle})
248 133907 50       7188170 or syserr(g_('pipe for %s'), "@prog");
249 133907         443067 ${$opts{error_to_pipe}} = $error_pipe;
  133907         431742  
250 133907         269089 push @{$opts{close_in_child}}, $error_pipe;
  133907         398973  
251             }
252             # Fork and exec
253 133939         116143793 my $pid = fork();
254 133939 50       2608996 syserr(g_('cannot fork for %s'), "@prog") unless defined $pid;
255 133939 100       422513 if (not $pid) {
256             # Define environment variables
257 528 100       43406 if ($opts{env}) {
258 2         29 foreach (keys %{$opts{env}}) {
  2         147  
259 6         294 $ENV{$_} = $opts{env}{$_};
260             }
261             }
262 528 100       19941 if ($opts{delete_env}) {
263 2         58 delete $ENV{$_} foreach (@{$opts{delete_env}});
  2         76  
264             }
265             # Define signal dispositions.
266 528 50       16730 if ($opts{sig}) {
267 0         0 foreach (keys %{$opts{sig}}) {
  0         0  
268 0         0 $SIG{$_} = $opts{sig}{$_};
269             }
270             }
271 528 50       13239 if ($opts{delete_sig}) {
272 0         0 delete $SIG{$_} foreach (@{$opts{delete_sig}});
  0         0  
273             }
274             # Change the current directory
275 528 100       10763 if ($opts{chdir}) {
276 2 50       240 chdir($opts{chdir}) or syserr(g_('chdir to %s'), $opts{chdir});
277             }
278             # Redirect STDIN if needed
279 528 100       23722 if ($opts{from_file}) {
    100          
280             open(STDIN, '<', $opts{from_file})
281 3 50       430 or syserr(g_('cannot open %s'), $opts{from_file});
282             } elsif ($opts{from_handle}) {
283             open(STDIN, '<&', $opts{from_handle})
284 8 50       1143 or syserr(g_('reopen stdin'));
285             # has been duped, can be closed
286 8         13740 push @{$opts{close_in_child}}, $opts{from_handle};
  8         156  
287             }
288             # Redirect STDOUT if needed
289 528 100       19778 if ($opts{to_file}) {
    100          
290             open(STDOUT, '>', $opts{to_file})
291 3 50       244 or syserr(g_('cannot write %s'), $opts{to_file});
292             } elsif ($opts{to_handle}) {
293             open(STDOUT, '>&', $opts{to_handle})
294 8 50       471 or syserr(g_('reopen stdout'));
295             # has been duped, can be closed
296 8         100 push @{$opts{close_in_child}}, $opts{to_handle};
  8         56  
297             }
298             # Redirect STDERR if needed
299 528 50       15465 if ($opts{error_to_file}) {
    100          
300             open(STDERR, '>', $opts{error_to_file})
301 0 0       0 or syserr(g_('cannot write %s'), $opts{error_to_file});
302             } elsif ($opts{error_to_handle}) {
303             open(STDERR, '>&', $opts{error_to_handle})
304 518 50       88136 or syserr(g_('reopen stdout'));
305             # has been duped, can be closed
306 518         10134 push @{$opts{close_in_child}}, $opts{error_to_handle};
  518         10008  
307             }
308             # Close some inherited filehandles
309 528         4855 close($_) foreach (@{$opts{close_in_child}});
  528         19776  
310             # Execute the program
311 528 0       7358 exec({ $prog[0] } @prog) or syserr(g_('unable to execute %s'), "@prog");
  528         0  
312             }
313             # Close handle that we can't use any more
314 133411 100       454962 close($opts{from_handle}) if exists $opts{from_handle};
315 133411 100       360279 close($opts{to_handle}) if exists $opts{to_handle};
316 133411 100       6547450 close($opts{error_to_handle}) if exists $opts{error_to_handle};
317              
318 133411 100       600534 if ($opts{from_string}) {
319 4         60 print { $from_string_pipe } ${$opts{from_string}};
  4         64  
  4         88  
320 4         80 close($from_string_pipe);
321             }
322 133411 100       405903 if ($opts{to_string}) {
323 7         352 local $/ = undef;
324 7         400 ${$opts{to_string}} = readline($to_string_pipe);
  7         4780282  
325             }
326 133411 100       2763690 if ($opts{error_to_string}) {
327 133389         6418141 local $/ = undef;
328 133389         1251891 ${$opts{error_to_string}} = readline($error_to_string_pipe);
  133389         110133314671  
329             }
330 133411 100       2271794 if ($opts{wait_child}) {
331 133396         2745077 my $cmdline = "@prog";
332 133396 100       764888 if ($opts{env}) {
333 3         13 foreach (keys %{$opts{env}}) {
  3         71  
334 9         63 $cmdline = "$_=\"" . $opts{env}{$_} . "\" $cmdline";
335             }
336             }
337             wait_child($pid, nocheck => $opts{nocheck},
338 133396         5151283 timeout => $opts{timeout}, cmdline => $cmdline);
339 133395         14398920 return 1;
340             }
341              
342 15         2508 return $pid;
343             }
344              
345              
346             =item wait_child($pid, %opts)
347              
348             Takes as first argument the pid of the process to wait for.
349             Remaining arguments are taken as a hash of options. Returns
350             nothing. Fails if the child has been ended by a signal or
351             if it exited non-zero.
352              
353             Options:
354              
355             =over 4
356              
357             =item cmdline
358              
359             String to identify the child process in error messages.
360             Defaults to "child process".
361              
362             =item nocheck
363              
364             If true do not check the return status of the child (and thus
365             do not fail it has been killed or if it exited with a
366             non-zero return code).
367              
368             =item timeout
369              
370             Set a maximum time to wait for the process, after that kill the process and
371             fail with an error message.
372              
373             =back
374              
375             =cut
376              
377             sub wait_child {
378 133411     133411 1 4893012 my ($pid, %opts) = @_;
379 133411   66     810838 $opts{cmdline} //= g_('child process');
380 133411 50       617868 croak 'no PID set, cannot wait end of process' unless $pid;
381 133411         533899 eval {
382 133411     1   9132199 local $SIG{ALRM} = sub { die "alarm\n" };
  1         78  
383 133411 100       844870 alarm($opts{timeout}) if defined($opts{timeout});
384 133411 50       11713583 $pid == waitpid($pid, 0) or syserr(g_('wait for %s'), $opts{cmdline});
385 133410 100       3106809 alarm(0) if defined($opts{timeout});
386             };
387 133411 100       820144 if ($@) {
388 1 50       16 die $@ unless $@ eq "alarm\n";
389 1         67 kill 'TERM', $pid;
390             error(P_("%s didn't complete in %d second",
391             "%s didn't complete in %d seconds",
392             $opts{timeout}),
393 1         54 $opts{cmdline}, $opts{timeout});
394             }
395 133410 100       887094 unless ($opts{nocheck}) {
396 16 50       303 subprocerr($opts{cmdline}) if $?;
397             }
398             }
399              
400             1;
401             __END__