1b39c5158Smillertpackage IPC::Cmd; 2b39c5158Smillert 3b39c5158Smillertuse strict; 4b39c5158Smillert 5b39c5158SmillertBEGIN { 6b39c5158Smillert 7b39c5158Smillert use constant IS_VMS => $^O eq 'VMS' ? 1 : 0; 8b39c5158Smillert use constant IS_WIN32 => $^O eq 'MSWin32' ? 1 : 0; 9b46d8ef2Safresh1 use constant IS_HPUX => $^O eq 'hpux' ? 1 : 0; 10b39c5158Smillert use constant IS_WIN98 => (IS_WIN32 and !Win32::IsWinNT()) ? 1 : 0; 11b39c5158Smillert use constant ALARM_CLASS => __PACKAGE__ . '::TimeOut'; 12b39c5158Smillert use constant SPECIAL_CHARS => qw[< > | &]; 13b39c5158Smillert use constant QUOTE => do { IS_WIN32 ? q["] : q['] }; 14b39c5158Smillert 15b39c5158Smillert use Exporter (); 16b39c5158Smillert use vars qw[ @ISA $VERSION @EXPORT_OK $VERBOSE $DEBUG 17b39c5158Smillert $USE_IPC_RUN $USE_IPC_OPEN3 $CAN_USE_RUN_FORKED $WARN 18898184e3Ssthen $INSTANCES $ALLOW_NULL_ARGS 196fb12b70Safresh1 $HAVE_MONOTONIC 20b39c5158Smillert ]; 21b39c5158Smillert 22*56d68f1eSafresh1 $VERSION = '1.04'; 23b39c5158Smillert $VERBOSE = 0; 24b39c5158Smillert $DEBUG = 0; 25b39c5158Smillert $WARN = 1; 26b39c5158Smillert $USE_IPC_RUN = IS_WIN32 && !IS_WIN98; 27b39c5158Smillert $USE_IPC_OPEN3 = not IS_VMS; 28898184e3Ssthen $ALLOW_NULL_ARGS = 0; 29b39c5158Smillert 30b39c5158Smillert $CAN_USE_RUN_FORKED = 0; 31b39c5158Smillert eval { 32b39c5158Smillert require POSIX; POSIX->import(); 33b39c5158Smillert require IPC::Open3; IPC::Open3->import(); 34b39c5158Smillert require IO::Select; IO::Select->import(); 35b39c5158Smillert require IO::Handle; IO::Handle->import(); 36b39c5158Smillert require FileHandle; FileHandle->import(); 376fb12b70Safresh1 require Socket; 38b39c5158Smillert require Time::HiRes; Time::HiRes->import(); 39898184e3Ssthen require Win32 if IS_WIN32; 40b39c5158Smillert }; 41b39c5158Smillert $CAN_USE_RUN_FORKED = $@ || !IS_VMS && !IS_WIN32; 42b39c5158Smillert 436fb12b70Safresh1 eval { 446fb12b70Safresh1 my $wait_start_time = Time::HiRes::clock_gettime(&Time::HiRes::CLOCK_MONOTONIC); 456fb12b70Safresh1 }; 466fb12b70Safresh1 if ($@) { 476fb12b70Safresh1 $HAVE_MONOTONIC = 0; 486fb12b70Safresh1 } 496fb12b70Safresh1 else { 506fb12b70Safresh1 $HAVE_MONOTONIC = 1; 516fb12b70Safresh1 } 526fb12b70Safresh1 53b39c5158Smillert @ISA = qw[Exporter]; 54b39c5158Smillert @EXPORT_OK = qw[can_run run run_forked QUOTE]; 55b39c5158Smillert} 56b39c5158Smillert 57b39c5158Smillertrequire Carp; 58b39c5158Smillertuse File::Spec; 59b39c5158Smillertuse Params::Check qw[check]; 60b39c5158Smillertuse Text::ParseWords (); # import ONLY if needed! 61b39c5158Smillertuse Module::Load::Conditional qw[can_load]; 62b39c5158Smillertuse Locale::Maketext::Simple Style => 'gettext'; 63b39c5158Smillert 649f11ffb7Safresh1local $Module::Load::Conditional::FORCE_SAFE_INC = 1; 659f11ffb7Safresh1 66b39c5158Smillert=pod 67b39c5158Smillert 68b39c5158Smillert=head1 NAME 69b39c5158Smillert 70b39c5158SmillertIPC::Cmd - finding and running system commands made easy 71b39c5158Smillert 72b39c5158Smillert=head1 SYNOPSIS 73b39c5158Smillert 74b39c5158Smillert use IPC::Cmd qw[can_run run run_forked]; 75b39c5158Smillert 76b39c5158Smillert my $full_path = can_run('wget') or warn 'wget is not installed!'; 77b39c5158Smillert 78b39c5158Smillert ### commands can be arrayrefs or strings ### 79b39c5158Smillert my $cmd = "$full_path -b theregister.co.uk"; 80b39c5158Smillert my $cmd = [$full_path, '-b', 'theregister.co.uk']; 81b39c5158Smillert 82b39c5158Smillert ### in scalar context ### 83b39c5158Smillert my $buffer; 84b39c5158Smillert if( scalar run( command => $cmd, 85b39c5158Smillert verbose => 0, 86b39c5158Smillert buffer => \$buffer, 87b39c5158Smillert timeout => 20 ) 88b39c5158Smillert ) { 89b39c5158Smillert print "fetched webpage successfully: $buffer\n"; 90b39c5158Smillert } 91b39c5158Smillert 92b39c5158Smillert 93b39c5158Smillert ### in list context ### 94898184e3Ssthen my( $success, $error_message, $full_buf, $stdout_buf, $stderr_buf ) = 95b39c5158Smillert run( command => $cmd, verbose => 0 ); 96b39c5158Smillert 97b39c5158Smillert if( $success ) { 98b39c5158Smillert print "this is what the command printed:\n"; 99b39c5158Smillert print join "", @$full_buf; 100b39c5158Smillert } 101b39c5158Smillert 1026fb12b70Safresh1 ### run_forked example ### 1036fb12b70Safresh1 my $result = run_forked("$full_path -q -O - theregister.co.uk", {'timeout' => 20}); 1046fb12b70Safresh1 if ($result->{'exit_code'} eq 0 && !$result->{'timeout'}) { 1056fb12b70Safresh1 print "this is what wget returned:\n"; 1066fb12b70Safresh1 print $result->{'stdout'}; 1076fb12b70Safresh1 } 1086fb12b70Safresh1 109b39c5158Smillert ### check for features 110b39c5158Smillert print "IPC::Open3 available: " . IPC::Cmd->can_use_ipc_open3; 111b39c5158Smillert print "IPC::Run available: " . IPC::Cmd->can_use_ipc_run; 112b39c5158Smillert print "Can capture buffer: " . IPC::Cmd->can_capture_buffer; 113b39c5158Smillert 114b39c5158Smillert ### don't have IPC::Cmd be verbose, ie don't print to stdout or 115b39c5158Smillert ### stderr when running commands -- default is '0' 116b39c5158Smillert $IPC::Cmd::VERBOSE = 0; 117b39c5158Smillert 118b39c5158Smillert 119b39c5158Smillert=head1 DESCRIPTION 120b39c5158Smillert 121898184e3SsthenIPC::Cmd allows you to run commands platform independently, 122898184e3Sstheninteractively if desired, but have them still work. 123b39c5158Smillert 124b39c5158SmillertThe C<can_run> function can tell you if a certain binary is installed 125b39c5158Smillertand if so where, whereas the C<run> function can actually execute any 126b39c5158Smillertof the commands you give it and give you a clear return value, as well 127b39c5158Smillertas adhere to your verbosity settings. 128b39c5158Smillert 129b39c5158Smillert=head1 CLASS METHODS 130b39c5158Smillert 131b39c5158Smillert=head2 $ipc_run_version = IPC::Cmd->can_use_ipc_run( [VERBOSE] ) 132b39c5158Smillert 133b39c5158SmillertUtility function that tells you if C<IPC::Run> is available. 134898184e3SsthenIf the C<verbose> flag is passed, it will print diagnostic messages 135898184e3Ssthenif L<IPC::Run> can not be found or loaded. 136b39c5158Smillert 137b39c5158Smillert=cut 138b39c5158Smillert 139b39c5158Smillert 140b39c5158Smillertsub can_use_ipc_run { 141b39c5158Smillert my $self = shift; 142b39c5158Smillert my $verbose = shift || 0; 143b39c5158Smillert 144898184e3Ssthen ### IPC::Run doesn't run on win98 145b39c5158Smillert return if IS_WIN98; 146b39c5158Smillert 1476fb12b70Safresh1 ### if we don't have ipc::run, we obviously can't use it. 148b39c5158Smillert return unless can_load( 149b39c5158Smillert modules => { 'IPC::Run' => '0.55' }, 150b39c5158Smillert verbose => ($WARN && $verbose), 151b39c5158Smillert ); 152b39c5158Smillert 153b39c5158Smillert ### otherwise, we're good to go 154b39c5158Smillert return $IPC::Run::VERSION; 155b39c5158Smillert} 156b39c5158Smillert 157b39c5158Smillert=head2 $ipc_open3_version = IPC::Cmd->can_use_ipc_open3( [VERBOSE] ) 158b39c5158Smillert 159b39c5158SmillertUtility function that tells you if C<IPC::Open3> is available. 160b39c5158SmillertIf the verbose flag is passed, it will print diagnostic messages 161b39c5158Smillertif C<IPC::Open3> can not be found or loaded. 162b39c5158Smillert 163b39c5158Smillert=cut 164b39c5158Smillert 165b39c5158Smillert 166b39c5158Smillertsub can_use_ipc_open3 { 167b39c5158Smillert my $self = shift; 168b39c5158Smillert my $verbose = shift || 0; 169b39c5158Smillert 170898184e3Ssthen ### IPC::Open3 is not working on VMS because of a lack of fork. 171b39c5158Smillert return if IS_VMS; 172b39c5158Smillert 1736fb12b70Safresh1 ### IPC::Open3 works on every non-VMS platform, but it can't 174b39c5158Smillert ### capture buffers on win32 :( 175b39c5158Smillert return unless can_load( 176b39c5158Smillert modules => { map {$_ => '0.0'} qw|IPC::Open3 IO::Select Symbol| }, 177b39c5158Smillert verbose => ($WARN && $verbose), 178b39c5158Smillert ); 179b39c5158Smillert 180b39c5158Smillert return $IPC::Open3::VERSION; 181b39c5158Smillert} 182b39c5158Smillert 183b39c5158Smillert=head2 $bool = IPC::Cmd->can_capture_buffer 184b39c5158Smillert 185b39c5158SmillertUtility function that tells you if C<IPC::Cmd> is capable of 186b39c5158Smillertcapturing buffers in it's current configuration. 187b39c5158Smillert 188b39c5158Smillert=cut 189b39c5158Smillert 190b39c5158Smillertsub can_capture_buffer { 191b39c5158Smillert my $self = shift; 192b39c5158Smillert 193b39c5158Smillert return 1 if $USE_IPC_RUN && $self->can_use_ipc_run; 194898184e3Ssthen return 1 if $USE_IPC_OPEN3 && $self->can_use_ipc_open3; 195b39c5158Smillert return; 196b39c5158Smillert} 197b39c5158Smillert 198b39c5158Smillert=head2 $bool = IPC::Cmd->can_use_run_forked 199b39c5158Smillert 200b39c5158SmillertUtility function that tells you if C<IPC::Cmd> is capable of 201b39c5158Smillertproviding C<run_forked> on the current platform. 202b39c5158Smillert 203b39c5158Smillert=head1 FUNCTIONS 204b39c5158Smillert 205b39c5158Smillert=head2 $path = can_run( PROGRAM ); 206b39c5158Smillert 207898184e3SsthenC<can_run> takes only one argument: the name of a binary you wish 208b39c5158Smillertto locate. C<can_run> works much like the unix binary C<which> or the bash 209b39c5158Smillertcommand C<type>, which scans through your path, looking for the requested 210b39c5158Smillertbinary. 211b39c5158Smillert 212b39c5158SmillertUnlike C<which> and C<type>, this function is platform independent and 213b39c5158Smillertwill also work on, for example, Win32. 214b39c5158Smillert 215898184e3SsthenIf called in a scalar context it will return the full path to the binary 216898184e3Ssthenyou asked for if it was found, or C<undef> if it was not. 217898184e3Ssthen 218898184e3SsthenIf called in a list context and the global variable C<$INSTANCES> is a true 219898184e3Ssthenvalue, it will return a list of the full paths to instances 220898184e3Ssthenof the binary where found in C<PATH>, or an empty list if it was not found. 221b39c5158Smillert 222b39c5158Smillert=cut 223b39c5158Smillert 224b39c5158Smillertsub can_run { 225b39c5158Smillert my $command = shift; 226b39c5158Smillert 227b39c5158Smillert # a lot of VMS executables have a symbol defined 228b39c5158Smillert # check those first 229b39c5158Smillert if ( $^O eq 'VMS' ) { 230b39c5158Smillert require VMS::DCLsym; 231b39c5158Smillert my $syms = VMS::DCLsym->new; 232b39c5158Smillert return $command if scalar $syms->getsym( uc $command ); 233b39c5158Smillert } 234b39c5158Smillert 235b39c5158Smillert require File::Spec; 236b39c5158Smillert require ExtUtils::MakeMaker; 237b39c5158Smillert 238898184e3Ssthen my @possibles; 239898184e3Ssthen 240b39c5158Smillert if( File::Spec->file_name_is_absolute($command) ) { 241b39c5158Smillert return MM->maybe_command($command); 242b39c5158Smillert 243b39c5158Smillert } else { 244b39c5158Smillert for my $dir ( 24591f110e0Safresh1 File::Spec->path, 2469f11ffb7Safresh1 ( IS_WIN32 ? File::Spec->curdir : () ) 247b39c5158Smillert ) { 248898184e3Ssthen next if ! $dir || ! -d $dir; 249898184e3Ssthen my $abs = File::Spec->catfile( IS_WIN32 ? Win32::GetShortPathName( $dir ) : $dir, $command); 250898184e3Ssthen push @possibles, $abs if $abs = MM->maybe_command($abs); 251b39c5158Smillert } 252b39c5158Smillert } 253898184e3Ssthen return @possibles if wantarray and $INSTANCES; 254898184e3Ssthen return shift @possibles; 255b39c5158Smillert} 256b39c5158Smillert 257b39c5158Smillert=head2 $ok | ($ok, $err, $full_buf, $stdout_buff, $stderr_buff) = run( command => COMMAND, [verbose => BOOL, buffer => \$SCALAR, timeout => DIGIT] ); 258b39c5158Smillert 259b39c5158SmillertC<run> takes 4 arguments: 260b39c5158Smillert 261b39c5158Smillert=over 4 262b39c5158Smillert 263b39c5158Smillert=item command 264b39c5158Smillert 265b39c5158SmillertThis is the command to execute. It may be either a string or an array 266b39c5158Smillertreference. 267b39c5158SmillertThis is a required argument. 268b39c5158Smillert 269898184e3SsthenSee L<"Caveats"> for remarks on how commands are parsed and their 270b39c5158Smillertlimitations. 271b39c5158Smillert 272b39c5158Smillert=item verbose 273b39c5158Smillert 274b39c5158SmillertThis controls whether all output of a command should also be printed 275b39c5158Smillertto STDOUT/STDERR or should only be trapped in buffers (NOTE: buffers 276898184e3Ssthenrequire L<IPC::Run> to be installed, or your system able to work with 277898184e3SsthenL<IPC::Open3>). 278b39c5158Smillert 279b39c5158SmillertIt will default to the global setting of C<$IPC::Cmd::VERBOSE>, 280b39c5158Smillertwhich by default is 0. 281b39c5158Smillert 282b39c5158Smillert=item buffer 283b39c5158Smillert 284b39c5158SmillertThis will hold all the output of a command. It needs to be a reference 285b39c5158Smillertto a scalar. 286b39c5158SmillertNote that this will hold both the STDOUT and STDERR messages, and you 287b39c5158Smillerthave no way of telling which is which. 288b39c5158SmillertIf you require this distinction, run the C<run> command in list context 289b39c5158Smillertand inspect the individual buffers. 290b39c5158Smillert 291b39c5158SmillertOf course, this requires that the underlying call supports buffers. See 292898184e3Ssthenthe note on buffers above. 293b39c5158Smillert 294b39c5158Smillert=item timeout 295b39c5158Smillert 296b39c5158SmillertSets the maximum time the command is allowed to run before aborting, 297b39c5158Smillertusing the built-in C<alarm()> call. If the timeout is triggered, the 298b39c5158SmillertC<errorcode> in the return value will be set to an object of the 299898184e3SsthenC<IPC::Cmd::TimeOut> class. See the L<"error message"> section below for 300b39c5158Smillertdetails. 301b39c5158Smillert 302b39c5158SmillertDefaults to C<0>, meaning no timeout is set. 303b39c5158Smillert 304b39c5158Smillert=back 305b39c5158Smillert 306b39c5158SmillertC<run> will return a simple C<true> or C<false> when called in scalar 307b39c5158Smillertcontext. 308b39c5158SmillertIn list context, you will be returned a list of the following items: 309b39c5158Smillert 310b39c5158Smillert=over 4 311b39c5158Smillert 312b39c5158Smillert=item success 313b39c5158Smillert 314b39c5158SmillertA simple boolean indicating if the command executed without errors or 315b39c5158Smillertnot. 316b39c5158Smillert 317b39c5158Smillert=item error message 318b39c5158Smillert 319898184e3SsthenIf the first element of the return value (C<success>) was 0, then some 320b39c5158Smillerterror occurred. This second element is the error message the command 321b39c5158Smillertyou requested exited with, if available. This is generally a pretty 322b39c5158Smillertprinted value of C<$?> or C<$@>. See C<perldoc perlvar> for details on 323b39c5158Smillertwhat they can contain. 324b39c5158SmillertIf the error was a timeout, the C<error message> will be prefixed with 325b39c5158Smillertthe string C<IPC::Cmd::TimeOut>, the timeout class. 326b39c5158Smillert 327b39c5158Smillert=item full_buffer 328b39c5158Smillert 329b39c5158SmillertThis is an array reference containing all the output the command 330b39c5158Smillertgenerated. 331898184e3SsthenNote that buffers are only available if you have L<IPC::Run> installed, 332898184e3Ssthenor if your system is able to work with L<IPC::Open3> -- see below). 333898184e3SsthenOtherwise, this element will be C<undef>. 334b39c5158Smillert 335b39c5158Smillert=item out_buffer 336b39c5158Smillert 337b39c5158SmillertThis is an array reference containing all the output sent to STDOUT the 338898184e3Ssthencommand generated. The notes from L<"full_buffer"> apply. 339b39c5158Smillert 340b39c5158Smillert=item error_buffer 341b39c5158Smillert 342b39c5158SmillertThis is an arrayreference containing all the output sent to STDERR the 343898184e3Ssthencommand generated. The notes from L<"full_buffer"> apply. 344898184e3Ssthen 345b39c5158Smillert 346b39c5158Smillert=back 347b39c5158Smillert 348898184e3SsthenSee the L<"HOW IT WORKS"> section below to see how C<IPC::Cmd> decides 349b39c5158Smillertwhat modules or function calls to use when issuing a command. 350b39c5158Smillert 351b39c5158Smillert=cut 352b39c5158Smillert 353b39c5158Smillert{ my @acc = qw[ok error _fds]; 354b39c5158Smillert 355b39c5158Smillert ### autogenerate accessors ### 356b39c5158Smillert for my $key ( @acc ) { 357b39c5158Smillert no strict 'refs'; 358b39c5158Smillert *{__PACKAGE__."::$key"} = sub { 359b39c5158Smillert $_[0]->{$key} = $_[1] if @_ > 1; 360b39c5158Smillert return $_[0]->{$key}; 361b39c5158Smillert } 362b39c5158Smillert } 363b39c5158Smillert} 364b39c5158Smillert 365b39c5158Smillertsub can_use_run_forked { 366b39c5158Smillert return $CAN_USE_RUN_FORKED eq "1"; 367b39c5158Smillert} 368b39c5158Smillert 3696fb12b70Safresh1sub get_monotonic_time { 3706fb12b70Safresh1 if ($HAVE_MONOTONIC) { 3716fb12b70Safresh1 return Time::HiRes::clock_gettime(&Time::HiRes::CLOCK_MONOTONIC); 3726fb12b70Safresh1 } 3736fb12b70Safresh1 else { 3746fb12b70Safresh1 return time(); 3756fb12b70Safresh1 } 3766fb12b70Safresh1} 3776fb12b70Safresh1 3786fb12b70Safresh1sub adjust_monotonic_start_time { 3796fb12b70Safresh1 my ($ref_vars, $now, $previous) = @_; 3806fb12b70Safresh1 3816fb12b70Safresh1 # workaround only for those systems which don't have 3826fb12b70Safresh1 # Time::HiRes::CLOCK_MONOTONIC (Mac OSX in particular) 3836fb12b70Safresh1 return if $HAVE_MONOTONIC; 3846fb12b70Safresh1 3856fb12b70Safresh1 # don't have previous monotonic value (only happens once 3866fb12b70Safresh1 # in the beginning of the program execution) 3876fb12b70Safresh1 return unless $previous; 3886fb12b70Safresh1 3896fb12b70Safresh1 my $time_diff = $now - $previous; 3906fb12b70Safresh1 3916fb12b70Safresh1 # adjust previously saved time with the skew value which is 3926fb12b70Safresh1 # either negative when clock moved back or more than 5 seconds -- 3936fb12b70Safresh1 # assuming that event loop does happen more often than once 3946fb12b70Safresh1 # per five seconds, which might not be always true (!) but 3956fb12b70Safresh1 # hopefully that's ok, because it's just a workaround 3966fb12b70Safresh1 if ($time_diff > 5 || $time_diff < 0) { 3976fb12b70Safresh1 foreach my $ref_var (@{$ref_vars}) { 3986fb12b70Safresh1 if (defined($$ref_var)) { 3996fb12b70Safresh1 $$ref_var = $$ref_var + $time_diff; 4006fb12b70Safresh1 } 4016fb12b70Safresh1 } 4026fb12b70Safresh1 } 4036fb12b70Safresh1} 4046fb12b70Safresh1 4059f11ffb7Safresh1sub uninstall_signals { 4069f11ffb7Safresh1 return unless defined($IPC::Cmd::{'__old_signals'}); 4079f11ffb7Safresh1 4089f11ffb7Safresh1 foreach my $sig_name (keys %{$IPC::Cmd::{'__old_signals'}}) { 4099f11ffb7Safresh1 $SIG{$sig_name} = $IPC::Cmd::{'__old_signals'}->{$sig_name}; 4109f11ffb7Safresh1 } 4119f11ffb7Safresh1} 4129f11ffb7Safresh1 413898184e3Ssthen# incompatible with POSIX::SigAction 414898184e3Ssthen# 415898184e3Ssthensub install_layered_signal { 416898184e3Ssthen my ($s, $handler_code) = @_; 417898184e3Ssthen 418898184e3Ssthen my %available_signals = map {$_ => 1} keys %SIG; 419898184e3Ssthen 4206fb12b70Safresh1 Carp::confess("install_layered_signal got nonexistent signal name [$s]") 421898184e3Ssthen unless defined($available_signals{$s}); 4226fb12b70Safresh1 Carp::confess("install_layered_signal expects coderef") 423898184e3Ssthen if !ref($handler_code) || ref($handler_code) ne 'CODE'; 424898184e3Ssthen 4259f11ffb7Safresh1 $IPC::Cmd::{'__old_signals'} = {} 4269f11ffb7Safresh1 unless defined($IPC::Cmd::{'__old_signals'}); 4279f11ffb7Safresh1 $IPC::Cmd::{'__old_signals'}->{$s} = $SIG{$s}; 4289f11ffb7Safresh1 429898184e3Ssthen my $previous_handler = $SIG{$s}; 430898184e3Ssthen 431898184e3Ssthen my $sig_handler = sub { 432898184e3Ssthen my ($called_sig_name, @sig_param) = @_; 433898184e3Ssthen 434898184e3Ssthen # $s is a closure referring to real signal name 435898184e3Ssthen # for which this handler is being installed. 436898184e3Ssthen # it is used to distinguish between 437898184e3Ssthen # real signal handlers and aliased signal handlers 438898184e3Ssthen my $signal_name = $s; 439898184e3Ssthen 440898184e3Ssthen # $called_sig_name is a signal name which 441898184e3Ssthen # was passed to this signal handler; 442898184e3Ssthen # it doesn't equal $signal_name in case 443898184e3Ssthen # some signal handlers in %SIG point 444898184e3Ssthen # to other signal handler (CHLD and CLD, 445898184e3Ssthen # ABRT and IOT) 446898184e3Ssthen # 447898184e3Ssthen # initial signal handler for aliased signal 448898184e3Ssthen # calls some other signal handler which 449898184e3Ssthen # should not execute the same handler_code again 450898184e3Ssthen if ($called_sig_name eq $signal_name) { 451898184e3Ssthen $handler_code->($signal_name); 452898184e3Ssthen } 453898184e3Ssthen 454898184e3Ssthen # run original signal handler if any (including aliased) 455898184e3Ssthen # 456898184e3Ssthen if (ref($previous_handler)) { 457898184e3Ssthen $previous_handler->($called_sig_name, @sig_param); 458898184e3Ssthen } 459898184e3Ssthen }; 460898184e3Ssthen 461898184e3Ssthen $SIG{$s} = $sig_handler; 462898184e3Ssthen} 463898184e3Ssthen 464b39c5158Smillert# give process a chance sending TERM, 465b39c5158Smillert# waiting for a while (2 seconds) 466b39c5158Smillert# and killing it with KILL 467b39c5158Smillertsub kill_gently { 468898184e3Ssthen my ($pid, $opts) = @_; 469b39c5158Smillert 470898184e3Ssthen require POSIX; 471898184e3Ssthen 472898184e3Ssthen $opts = {} unless $opts; 473898184e3Ssthen $opts->{'wait_time'} = 2 unless defined($opts->{'wait_time'}); 474898184e3Ssthen $opts->{'first_kill_type'} = 'just_process' unless $opts->{'first_kill_type'}; 475898184e3Ssthen $opts->{'final_kill_type'} = 'just_process' unless $opts->{'final_kill_type'}; 476898184e3Ssthen 477898184e3Ssthen if ($opts->{'first_kill_type'} eq 'just_process') { 478b39c5158Smillert kill(15, $pid); 479898184e3Ssthen } 480898184e3Ssthen elsif ($opts->{'first_kill_type'} eq 'process_group') { 481898184e3Ssthen kill(-15, $pid); 482898184e3Ssthen } 483b39c5158Smillert 4846fb12b70Safresh1 my $do_wait = 1; 485b39c5158Smillert my $child_finished = 0; 486b39c5158Smillert 4876fb12b70Safresh1 my $wait_start_time = get_monotonic_time(); 4886fb12b70Safresh1 my $now; 4896fb12b70Safresh1 my $previous_monotonic_value; 4906fb12b70Safresh1 4916fb12b70Safresh1 while ($do_wait) { 4926fb12b70Safresh1 $previous_monotonic_value = $now; 4936fb12b70Safresh1 $now = get_monotonic_time(); 4946fb12b70Safresh1 4956fb12b70Safresh1 adjust_monotonic_start_time([\$wait_start_time], $now, $previous_monotonic_value); 4966fb12b70Safresh1 4976fb12b70Safresh1 if ($now > $wait_start_time + $opts->{'wait_time'}) { 4986fb12b70Safresh1 $do_wait = 0; 4996fb12b70Safresh1 next; 5006fb12b70Safresh1 } 5016fb12b70Safresh1 502898184e3Ssthen my $waitpid = waitpid($pid, POSIX::WNOHANG); 5036fb12b70Safresh1 504b39c5158Smillert if ($waitpid eq -1) { 505b39c5158Smillert $child_finished = 1; 5066fb12b70Safresh1 $do_wait = 0; 5076fb12b70Safresh1 next; 508b39c5158Smillert } 5096fb12b70Safresh1 510898184e3Ssthen Time::HiRes::usleep(250000); # quarter of a second 511898184e3Ssthen } 512b39c5158Smillert 513898184e3Ssthen if (!$child_finished) { 514898184e3Ssthen if ($opts->{'final_kill_type'} eq 'just_process') { 515898184e3Ssthen kill(9, $pid); 516898184e3Ssthen } 517898184e3Ssthen elsif ($opts->{'final_kill_type'} eq 'process_group') { 518898184e3Ssthen kill(-9, $pid); 519898184e3Ssthen } 520b39c5158Smillert } 521b39c5158Smillert} 522b39c5158Smillert 523b39c5158Smillertsub open3_run { 524b39c5158Smillert my ($cmd, $opts) = @_; 525b39c5158Smillert 526b39c5158Smillert $opts = {} unless $opts; 527b39c5158Smillert 528b39c5158Smillert my $child_in = FileHandle->new; 529b39c5158Smillert my $child_out = FileHandle->new; 530b39c5158Smillert my $child_err = FileHandle->new; 531b39c5158Smillert $child_out->autoflush(1); 532b39c5158Smillert $child_err->autoflush(1); 533b39c5158Smillert 534b39c5158Smillert my $pid = open3($child_in, $child_out, $child_err, $cmd); 535b46d8ef2Safresh1 Time::HiRes::usleep(1) if IS_HPUX; 536b46d8ef2Safresh1 537b46d8ef2Safresh1 # will consider myself orphan if my ppid changes 538b46d8ef2Safresh1 # from this one: 539b46d8ef2Safresh1 my $original_ppid = $opts->{'original_ppid'}; 540b39c5158Smillert 541b39c5158Smillert # push my child's pid to our parent 542b39c5158Smillert # so in case i am killed parent 543b39c5158Smillert # could stop my child (search for 544b39c5158Smillert # child_child_pid in parent code) 545b39c5158Smillert if ($opts->{'parent_info'}) { 546b39c5158Smillert my $ps = $opts->{'parent_info'}; 547b39c5158Smillert print $ps "spawned $pid\n"; 548b39c5158Smillert } 549b39c5158Smillert 550b39c5158Smillert if ($child_in && $child_out->opened && $opts->{'child_stdin'}) { 551b39c5158Smillert # If the child process dies for any reason, 552b39c5158Smillert # the next write to CHLD_IN is likely to generate 553b39c5158Smillert # a SIGPIPE in the parent, which is fatal by default. 554b39c5158Smillert # So you may wish to handle this signal. 555b39c5158Smillert # 556b39c5158Smillert # from http://perldoc.perl.org/IPC/Open3.html, 557b39c5158Smillert # absolutely needed to catch piped commands errors. 558b39c5158Smillert # 559898184e3Ssthen local $SIG{'PIPE'} = sub { 1; }; 560b39c5158Smillert 561b39c5158Smillert print $child_in $opts->{'child_stdin'}; 562b39c5158Smillert } 563b39c5158Smillert close($child_in); 564b39c5158Smillert 565b39c5158Smillert my $child_output = { 566b39c5158Smillert 'out' => $child_out->fileno, 567b39c5158Smillert 'err' => $child_err->fileno, 568b39c5158Smillert $child_out->fileno => { 569b39c5158Smillert 'parent_socket' => $opts->{'parent_stdout'}, 570b39c5158Smillert 'scalar_buffer' => "", 571b39c5158Smillert 'child_handle' => $child_out, 572b39c5158Smillert 'block_size' => ($child_out->stat)[11] || 1024, 573b39c5158Smillert }, 574b39c5158Smillert $child_err->fileno => { 575b39c5158Smillert 'parent_socket' => $opts->{'parent_stderr'}, 576b39c5158Smillert 'scalar_buffer' => "", 577b39c5158Smillert 'child_handle' => $child_err, 578b39c5158Smillert 'block_size' => ($child_err->stat)[11] || 1024, 579b39c5158Smillert }, 580b39c5158Smillert }; 581b39c5158Smillert 582b39c5158Smillert my $select = IO::Select->new(); 583b39c5158Smillert $select->add($child_out, $child_err); 584b39c5158Smillert 585b39c5158Smillert # pass any signal to the child 586b39c5158Smillert # effectively creating process 587b39c5158Smillert # strongly attached to the child: 588b39c5158Smillert # it will terminate only after child 589b39c5158Smillert # has terminated (except for SIGKILL, 590b39c5158Smillert # which is specially handled) 5919f11ffb7Safresh1 SIGNAL: foreach my $s (keys %SIG) { 5929f11ffb7Safresh1 next SIGNAL if $s eq '__WARN__' or $s eq '__DIE__'; # Skip and don't clobber __DIE__ & __WARN__ 593b39c5158Smillert my $sig_handler; 594b39c5158Smillert $sig_handler = sub { 595b39c5158Smillert kill("$s", $pid); 596b39c5158Smillert $SIG{$s} = $sig_handler; 597b39c5158Smillert }; 598b39c5158Smillert $SIG{$s} = $sig_handler; 599b39c5158Smillert } 600b39c5158Smillert 601b39c5158Smillert my $child_finished = 0; 602b39c5158Smillert 6036fb12b70Safresh1 my $real_exit; 6046fb12b70Safresh1 my $exit_value; 605b39c5158Smillert 6066fb12b70Safresh1 while(!$child_finished) { 607b39c5158Smillert 608b39c5158Smillert # parent was killed otherwise we would have got 609b39c5158Smillert # the same signal as parent and process it same way 610b46d8ef2Safresh1 if (getppid() != $original_ppid) { 611898184e3Ssthen 612898184e3Ssthen # end my process group with all the children 613898184e3Ssthen # (i am the process group leader, so my pid 614898184e3Ssthen # equals to the process group id) 615898184e3Ssthen # 616898184e3Ssthen # same thing which is done 617898184e3Ssthen # with $opts->{'clean_up_children'} 618898184e3Ssthen # in run_forked 619898184e3Ssthen # 620898184e3Ssthen kill(-9, $$); 621898184e3Ssthen 62291f110e0Safresh1 POSIX::_exit 1; 623b39c5158Smillert } 624b39c5158Smillert 6256fb12b70Safresh1 my $waitpid = waitpid($pid, POSIX::WNOHANG); 6266fb12b70Safresh1 6276fb12b70Safresh1 # child finished, catch it's exit status 6286fb12b70Safresh1 if ($waitpid ne 0 && $waitpid ne -1) { 6296fb12b70Safresh1 $real_exit = $?; 6306fb12b70Safresh1 $exit_value = $? >> 8; 6316fb12b70Safresh1 } 6326fb12b70Safresh1 6336fb12b70Safresh1 if ($waitpid eq -1) { 634b39c5158Smillert $child_finished = 1; 635b39c5158Smillert } 636b39c5158Smillert 637b39c5158Smillert 6386fb12b70Safresh1 my $ready_fds = []; 6396fb12b70Safresh1 push @{$ready_fds}, $select->can_read(1/100); 6406fb12b70Safresh1 6416fb12b70Safresh1 READY_FDS: while (scalar(@{$ready_fds})) { 6426fb12b70Safresh1 my $fd = shift @{$ready_fds}; 6436fb12b70Safresh1 $ready_fds = [grep {$_ ne $fd} @{$ready_fds}]; 6446fb12b70Safresh1 645b39c5158Smillert my $str = $child_output->{$fd->fileno}; 6466fb12b70Safresh1 Carp::confess("child stream not found: $fd") unless $str; 647b39c5158Smillert 648b39c5158Smillert my $data; 649b39c5158Smillert my $count = $fd->sysread($data, $str->{'block_size'}); 650b39c5158Smillert 651b39c5158Smillert if ($count) { 652b39c5158Smillert if ($str->{'parent_socket'}) { 653b39c5158Smillert my $ph = $str->{'parent_socket'}; 654b39c5158Smillert print $ph $data; 655b39c5158Smillert } 656b39c5158Smillert else { 657b39c5158Smillert $str->{'scalar_buffer'} .= $data; 658b39c5158Smillert } 659b39c5158Smillert } 660b39c5158Smillert elsif ($count eq 0) { 661b39c5158Smillert $select->remove($fd); 662b39c5158Smillert $fd->close(); 663b39c5158Smillert } 664b39c5158Smillert else { 6656fb12b70Safresh1 Carp::confess("error during sysread: " . $!); 666b39c5158Smillert } 667b39c5158Smillert 6686fb12b70Safresh1 push @{$ready_fds}, $select->can_read(1/100) if $child_finished; 6696fb12b70Safresh1 } 6706fb12b70Safresh1 6716fb12b70Safresh1 Time::HiRes::usleep(1); 6726fb12b70Safresh1 } 673b39c5158Smillert 674898184e3Ssthen # since we've successfully reaped the child, 675898184e3Ssthen # let our parent know about this. 676898184e3Ssthen # 677b39c5158Smillert if ($opts->{'parent_info'}) { 678b39c5158Smillert my $ps = $opts->{'parent_info'}; 679898184e3Ssthen 680898184e3Ssthen # child was killed, inform parent 681898184e3Ssthen if ($real_exit & 127) { 682898184e3Ssthen print $ps "$pid killed with " . ($real_exit & 127) . "\n"; 683898184e3Ssthen } 684898184e3Ssthen 685b39c5158Smillert print $ps "reaped $pid\n"; 686b39c5158Smillert } 687b39c5158Smillert 688b39c5158Smillert if ($opts->{'parent_stdout'} || $opts->{'parent_stderr'}) { 689b39c5158Smillert return $exit_value; 690b39c5158Smillert } 691b39c5158Smillert else { 692b39c5158Smillert return { 693b39c5158Smillert 'stdout' => $child_output->{$child_output->{'out'}}->{'scalar_buffer'}, 694b39c5158Smillert 'stderr' => $child_output->{$child_output->{'err'}}->{'scalar_buffer'}, 695b39c5158Smillert 'exit_code' => $exit_value, 696b39c5158Smillert }; 697b39c5158Smillert } 698b39c5158Smillert} 699b39c5158Smillert 700898184e3Ssthen=head2 $hashref = run_forked( COMMAND, { child_stdin => SCALAR, timeout => DIGIT, stdout_handler => CODEREF, stderr_handler => CODEREF} ); 701b39c5158Smillert 702898184e3SsthenC<run_forked> is used to execute some program or a coderef, 703b39c5158Smillertoptionally feed it with some input, get its return code 704898184e3Ssthenand output (both stdout and stderr into separate buffers). 705898184e3SsthenIn addition, it allows to terminate the program 706898184e3Ssthenif it takes too long to finish. 707b39c5158Smillert 708b39c5158SmillertThe important and distinguishing feature of run_forked 709b39c5158Smillertis execution timeout which at first seems to be 710b39c5158Smillertquite a simple task but if you think 711b39c5158Smillertthat the program which you're spawning 712b39c5158Smillertmight spawn some children itself (which 713b39c5158Smillertin their turn could do the same and so on) 714b39c5158Smillertit turns out to be not a simple issue. 715b39c5158Smillert 716b39c5158SmillertC<run_forked> is designed to survive and 717b39c5158Smillertsuccessfully terminate almost any long running task, 718b39c5158Smillerteven a fork bomb in case your system has the resources 719b39c5158Smillertto survive during given timeout. 720b39c5158Smillert 721b39c5158SmillertThis is achieved by creating separate watchdog process 722b39c5158Smillertwhich spawns the specified program in a separate 723b39c5158Smillertprocess session and supervises it: optionally 724b39c5158Smillertfeeds it with input, stores its exit code, 725b39c5158Smillertstdout and stderr, terminates it in case 726b39c5158Smillertit runs longer than specified. 727b39c5158Smillert 728898184e3SsthenInvocation requires the command to be executed or a coderef and optionally a hashref of options: 729b39c5158Smillert 730b39c5158Smillert=over 731b39c5158Smillert 732b39c5158Smillert=item C<timeout> 733b39c5158Smillert 7346fb12b70Safresh1Specify in seconds how long to run the command before it is killed with SIG_KILL (9), 735b39c5158Smillertwhich effectively terminates it and all of its children (direct or indirect). 736b39c5158Smillert 737b39c5158Smillert=item C<child_stdin> 738b39c5158Smillert 739898184e3SsthenSpecify some text that will be passed into the C<STDIN> of the executed program. 740b39c5158Smillert 741b39c5158Smillert=item C<stdout_handler> 742b39c5158Smillert 743898184e3SsthenCoderef of a subroutine to call when a portion of data is received on 744898184e3SsthenSTDOUT from the executing program. 745b39c5158Smillert 746b39c5158Smillert=item C<stderr_handler> 747b39c5158Smillert 748898184e3SsthenCoderef of a subroutine to call when a portion of data is received on 749898184e3SsthenSTDERR from the executing program. 750898184e3Ssthen 7519f11ffb7Safresh1=item C<wait_loop_callback> 7529f11ffb7Safresh1 7539f11ffb7Safresh1Coderef of a subroutine to call inside of the main waiting loop 7549f11ffb7Safresh1(while C<run_forked> waits for the external to finish or fail). 7559f11ffb7Safresh1It is useful to stop running external process before it ends 7569f11ffb7Safresh1by itself, e.g. 7579f11ffb7Safresh1 7589f11ffb7Safresh1 my $r = run_forked("some external command", { 7599f11ffb7Safresh1 'wait_loop_callback' => sub { 7609f11ffb7Safresh1 if (condition) { 7619f11ffb7Safresh1 kill(1, $$); 7629f11ffb7Safresh1 } 7639f11ffb7Safresh1 }, 7649f11ffb7Safresh1 'terminate_on_signal' => 'HUP', 7659f11ffb7Safresh1 }); 7669f11ffb7Safresh1 7679f11ffb7Safresh1Combined with C<stdout_handler> and C<stderr_handler> allows terminating 7689f11ffb7Safresh1external command based on its output. Could also be used as a timer 7699f11ffb7Safresh1without engaging with L<alarm> (signals). 7709f11ffb7Safresh1 7719f11ffb7Safresh1Remember that this code could be called every millisecond (depending 7729f11ffb7Safresh1on the output which external command generates), so try to make it 7739f11ffb7Safresh1as lightweight as possible. 774898184e3Ssthen 775898184e3Ssthen=item C<discard_output> 776898184e3Ssthen 777898184e3SsthenDiscards the buffering of the standard output and standard errors for return by run_forked(). 778898184e3SsthenWith this option you have to use the std*_handlers to read what the command outputs. 779898184e3SsthenUseful for commands that send a lot of output. 780898184e3Ssthen 781898184e3Ssthen=item C<terminate_on_parent_sudden_death> 782898184e3Ssthen 783898184e3SsthenEnable this option if you wish all spawned processes to be killed if the initially spawned 784898184e3Ssthenprocess (the parent) is killed or dies without waiting for child processes. 785b39c5158Smillert 786b39c5158Smillert=back 787b39c5158Smillert 788b39c5158SmillertC<run_forked> will return a HASHREF with the following keys: 789b39c5158Smillert 790b39c5158Smillert=over 791b39c5158Smillert 792b39c5158Smillert=item C<exit_code> 793b39c5158Smillert 794b39c5158SmillertThe exit code of the executed program. 795b39c5158Smillert 796b39c5158Smillert=item C<timeout> 797b39c5158Smillert 798b39c5158SmillertThe number of seconds the program ran for before being terminated, or 0 if no timeout occurred. 799b39c5158Smillert 800b39c5158Smillert=item C<stdout> 801b39c5158Smillert 802898184e3SsthenHolds the standard output of the executed command (or empty string if 803898184e3Ssthenthere was no STDOUT output or if C<discard_output> was used; it's always defined!) 804b39c5158Smillert 805b39c5158Smillert=item C<stderr> 806b39c5158Smillert 807898184e3SsthenHolds the standard error of the executed command (or empty string if 808898184e3Ssthenthere was no STDERR output or if C<discard_output> was used; it's always defined!) 809b39c5158Smillert 810b39c5158Smillert=item C<merged> 811b39c5158Smillert 812b39c5158SmillertHolds the standard output and error of the executed command merged into one stream 813898184e3Ssthen(or empty string if there was no output at all or if C<discard_output> was used; it's always defined!) 814b39c5158Smillert 815b39c5158Smillert=item C<err_msg> 816b39c5158Smillert 817b39c5158SmillertHolds some explanation in the case of an error. 818b39c5158Smillert 819b39c5158Smillert=back 820b39c5158Smillert 821b39c5158Smillert=cut 822b39c5158Smillert 823b39c5158Smillertsub run_forked { 824b39c5158Smillert ### container to store things in 825b39c5158Smillert my $self = bless {}, __PACKAGE__; 826b39c5158Smillert 827b39c5158Smillert if (!can_use_run_forked()) { 828b39c5158Smillert Carp::carp("run_forked is not available: $CAN_USE_RUN_FORKED"); 829b39c5158Smillert return; 830b39c5158Smillert } 831b39c5158Smillert 8326fb12b70Safresh1 require POSIX; 8336fb12b70Safresh1 834b39c5158Smillert my ($cmd, $opts) = @_; 8356fb12b70Safresh1 if (ref($cmd) eq 'ARRAY') { 8366fb12b70Safresh1 $cmd = join(" ", @{$cmd}); 8376fb12b70Safresh1 } 838b39c5158Smillert 839b39c5158Smillert if (!$cmd) { 840b39c5158Smillert Carp::carp("run_forked expects command to run"); 841b39c5158Smillert return; 842b39c5158Smillert } 843b39c5158Smillert 844b39c5158Smillert $opts = {} unless $opts; 845b39c5158Smillert $opts->{'timeout'} = 0 unless $opts->{'timeout'}; 846898184e3Ssthen $opts->{'terminate_wait_time'} = 2 unless defined($opts->{'terminate_wait_time'}); 847898184e3Ssthen 848898184e3Ssthen # turned on by default 849898184e3Ssthen $opts->{'clean_up_children'} = 1 unless defined($opts->{'clean_up_children'}); 850b39c5158Smillert 851b39c5158Smillert # sockets to pass child stdout to parent 852b39c5158Smillert my $child_stdout_socket; 853b39c5158Smillert my $parent_stdout_socket; 854b39c5158Smillert 855b39c5158Smillert # sockets to pass child stderr to parent 856b39c5158Smillert my $child_stderr_socket; 857b39c5158Smillert my $parent_stderr_socket; 858b39c5158Smillert 859b39c5158Smillert # sockets for child -> parent internal communication 860b39c5158Smillert my $child_info_socket; 861b39c5158Smillert my $parent_info_socket; 862b39c5158Smillert 8636fb12b70Safresh1 socketpair($child_stdout_socket, $parent_stdout_socket, &Socket::AF_UNIX, &Socket::SOCK_STREAM, &Socket::PF_UNSPEC) || 8646fb12b70Safresh1 Carp::confess ("socketpair: $!"); 8656fb12b70Safresh1 socketpair($child_stderr_socket, $parent_stderr_socket, &Socket::AF_UNIX, &Socket::SOCK_STREAM, &Socket::PF_UNSPEC) || 8666fb12b70Safresh1 Carp::confess ("socketpair: $!"); 8676fb12b70Safresh1 socketpair($child_info_socket, $parent_info_socket, &Socket::AF_UNIX, &Socket::SOCK_STREAM, &Socket::PF_UNSPEC) || 8686fb12b70Safresh1 Carp::confess ("socketpair: $!"); 869b39c5158Smillert 870b39c5158Smillert $child_stdout_socket->autoflush(1); 871b39c5158Smillert $parent_stdout_socket->autoflush(1); 872b39c5158Smillert $child_stderr_socket->autoflush(1); 873b39c5158Smillert $parent_stderr_socket->autoflush(1); 874b39c5158Smillert $child_info_socket->autoflush(1); 875b39c5158Smillert $parent_info_socket->autoflush(1); 876b39c5158Smillert 8776fb12b70Safresh1 my $start_time = get_monotonic_time(); 878b39c5158Smillert 879b39c5158Smillert my $pid; 880b46d8ef2Safresh1 my $ppid = $$; 881b39c5158Smillert if ($pid = fork) { 882b39c5158Smillert 883b39c5158Smillert # we are a parent 884b39c5158Smillert close($parent_stdout_socket); 885b39c5158Smillert close($parent_stderr_socket); 886b39c5158Smillert close($parent_info_socket); 887b39c5158Smillert 888b39c5158Smillert my $flags; 889b39c5158Smillert 890b39c5158Smillert # prepare sockets to read from child 891b39c5158Smillert 8929f11ffb7Safresh1 $flags = fcntl($child_stdout_socket, POSIX::F_GETFL, 0) || Carp::confess "can't fnctl F_GETFL: $!"; 893898184e3Ssthen $flags |= POSIX::O_NONBLOCK; 8946fb12b70Safresh1 fcntl($child_stdout_socket, POSIX::F_SETFL, $flags) || Carp::confess "can't fnctl F_SETFL: $!"; 895b39c5158Smillert 8969f11ffb7Safresh1 $flags = fcntl($child_stderr_socket, POSIX::F_GETFL, 0) || Carp::confess "can't fnctl F_GETFL: $!"; 897898184e3Ssthen $flags |= POSIX::O_NONBLOCK; 8986fb12b70Safresh1 fcntl($child_stderr_socket, POSIX::F_SETFL, $flags) || Carp::confess "can't fnctl F_SETFL: $!"; 899b39c5158Smillert 9009f11ffb7Safresh1 $flags = fcntl($child_info_socket, POSIX::F_GETFL, 0) || Carp::confess "can't fnctl F_GETFL: $!"; 901898184e3Ssthen $flags |= POSIX::O_NONBLOCK; 9026fb12b70Safresh1 fcntl($child_info_socket, POSIX::F_SETFL, $flags) || Carp::confess "can't fnctl F_SETFL: $!"; 903b39c5158Smillert 904b39c5158Smillert # print "child $pid started\n"; 905b39c5158Smillert 9066fb12b70Safresh1 my $child_output = { 9076fb12b70Safresh1 $child_stdout_socket->fileno => { 9086fb12b70Safresh1 'scalar_buffer' => "", 9096fb12b70Safresh1 'child_handle' => $child_stdout_socket, 9106fb12b70Safresh1 'block_size' => ($child_stdout_socket->stat)[11] || 1024, 9116fb12b70Safresh1 'protocol' => 'stdout', 9126fb12b70Safresh1 }, 9136fb12b70Safresh1 $child_stderr_socket->fileno => { 9146fb12b70Safresh1 'scalar_buffer' => "", 9156fb12b70Safresh1 'child_handle' => $child_stderr_socket, 9166fb12b70Safresh1 'block_size' => ($child_stderr_socket->stat)[11] || 1024, 9176fb12b70Safresh1 'protocol' => 'stderr', 9186fb12b70Safresh1 }, 9196fb12b70Safresh1 $child_info_socket->fileno => { 9206fb12b70Safresh1 'scalar_buffer' => "", 9216fb12b70Safresh1 'child_handle' => $child_info_socket, 9226fb12b70Safresh1 'block_size' => ($child_info_socket->stat)[11] || 1024, 9236fb12b70Safresh1 'protocol' => 'info', 9246fb12b70Safresh1 }, 9256fb12b70Safresh1 }; 9266fb12b70Safresh1 9276fb12b70Safresh1 my $select = IO::Select->new(); 9286fb12b70Safresh1 $select->add($child_stdout_socket, $child_stderr_socket, $child_info_socket); 9296fb12b70Safresh1 930898184e3Ssthen my $child_timedout = 0; 931b39c5158Smillert my $child_finished = 0; 932b39c5158Smillert my $child_stdout = ''; 933b39c5158Smillert my $child_stderr = ''; 934b39c5158Smillert my $child_merged = ''; 935b39c5158Smillert my $child_exit_code = 0; 936898184e3Ssthen my $child_killed_by_signal = 0; 937898184e3Ssthen my $parent_died = 0; 938b39c5158Smillert 9396fb12b70Safresh1 my $last_parent_check = 0; 940b39c5158Smillert my $got_sig_child = 0; 941898184e3Ssthen my $got_sig_quit = 0; 942898184e3Ssthen my $orig_sig_child = $SIG{'CHLD'}; 943898184e3Ssthen 9446fb12b70Safresh1 $SIG{'CHLD'} = sub { $got_sig_child = get_monotonic_time(); }; 945b39c5158Smillert 946898184e3Ssthen if ($opts->{'terminate_on_signal'}) { 947898184e3Ssthen install_layered_signal($opts->{'terminate_on_signal'}, sub { $got_sig_quit = time(); }); 948898184e3Ssthen } 949898184e3Ssthen 950b39c5158Smillert my $child_child_pid; 9516fb12b70Safresh1 my $now; 9526fb12b70Safresh1 my $previous_monotonic_value; 953b39c5158Smillert 954b39c5158Smillert while (!$child_finished) { 9556fb12b70Safresh1 $previous_monotonic_value = $now; 9566fb12b70Safresh1 $now = get_monotonic_time(); 9576fb12b70Safresh1 9586fb12b70Safresh1 adjust_monotonic_start_time([\$start_time, \$last_parent_check, \$got_sig_child], $now, $previous_monotonic_value); 959898184e3Ssthen 960898184e3Ssthen if ($opts->{'terminate_on_parent_sudden_death'}) { 961898184e3Ssthen # check for parent once each five seconds 9626fb12b70Safresh1 if ($now > $last_parent_check + 5) { 963898184e3Ssthen if (getppid() eq "1") { 964898184e3Ssthen kill_gently ($pid, { 965898184e3Ssthen 'first_kill_type' => 'process_group', 966898184e3Ssthen 'final_kill_type' => 'process_group', 967898184e3Ssthen 'wait_time' => $opts->{'terminate_wait_time'} 968898184e3Ssthen }); 969898184e3Ssthen $parent_died = 1; 970898184e3Ssthen } 971898184e3Ssthen 9726fb12b70Safresh1 $last_parent_check = $now; 973898184e3Ssthen } 974898184e3Ssthen } 975898184e3Ssthen 976b39c5158Smillert # user specified timeout 977b39c5158Smillert if ($opts->{'timeout'}) { 9786fb12b70Safresh1 if ($now > $start_time + $opts->{'timeout'}) { 979898184e3Ssthen kill_gently ($pid, { 980898184e3Ssthen 'first_kill_type' => 'process_group', 981898184e3Ssthen 'final_kill_type' => 'process_group', 982898184e3Ssthen 'wait_time' => $opts->{'terminate_wait_time'} 983898184e3Ssthen }); 984b39c5158Smillert $child_timedout = 1; 985b39c5158Smillert } 986b39c5158Smillert } 987b39c5158Smillert 988b39c5158Smillert # give OS 10 seconds for correct return of waitpid, 989b39c5158Smillert # kill process after that and finish wait loop; 990b39c5158Smillert # shouldn't ever happen -- remove this code? 991b39c5158Smillert if ($got_sig_child) { 9926fb12b70Safresh1 if ($now > $got_sig_child + 10) { 993b39c5158Smillert print STDERR "waitpid did not return -1 for 10 seconds after SIG_CHLD, killing [$pid]\n"; 994b39c5158Smillert kill (-9, $pid); 995b39c5158Smillert $child_finished = 1; 996b39c5158Smillert } 997b39c5158Smillert } 998b39c5158Smillert 999898184e3Ssthen if ($got_sig_quit) { 1000898184e3Ssthen kill_gently ($pid, { 1001898184e3Ssthen 'first_kill_type' => 'process_group', 1002898184e3Ssthen 'final_kill_type' => 'process_group', 1003898184e3Ssthen 'wait_time' => $opts->{'terminate_wait_time'} 1004898184e3Ssthen }); 1005898184e3Ssthen $child_finished = 1; 1006898184e3Ssthen } 1007898184e3Ssthen 1008898184e3Ssthen my $waitpid = waitpid($pid, POSIX::WNOHANG); 1009b39c5158Smillert 1010b39c5158Smillert # child finished, catch it's exit status 1011b39c5158Smillert if ($waitpid ne 0 && $waitpid ne -1) { 1012b39c5158Smillert $child_exit_code = $? >> 8; 1013b39c5158Smillert } 1014b39c5158Smillert 1015b39c5158Smillert if ($waitpid eq -1) { 1016b39c5158Smillert $child_finished = 1; 1017b39c5158Smillert } 1018b39c5158Smillert 10196fb12b70Safresh1 my $ready_fds = []; 10206fb12b70Safresh1 push @{$ready_fds}, $select->can_read(1/100); 10216fb12b70Safresh1 10226fb12b70Safresh1 READY_FDS: while (scalar(@{$ready_fds})) { 10236fb12b70Safresh1 my $fd = shift @{$ready_fds}; 10246fb12b70Safresh1 $ready_fds = [grep {$_ ne $fd} @{$ready_fds}]; 10256fb12b70Safresh1 10266fb12b70Safresh1 my $str = $child_output->{$fd->fileno}; 10276fb12b70Safresh1 Carp::confess("child stream not found: $fd") unless $str; 10286fb12b70Safresh1 10296fb12b70Safresh1 my $data = ""; 10306fb12b70Safresh1 my $count = $fd->sysread($data, $str->{'block_size'}); 10316fb12b70Safresh1 10326fb12b70Safresh1 if ($count) { 10336fb12b70Safresh1 # extract all the available lines and store the rest in temporary buffer 10346fb12b70Safresh1 if ($data =~ /(.+\n)([^\n]*)/so) { 10356fb12b70Safresh1 $data = $str->{'scalar_buffer'} . $1; 10366fb12b70Safresh1 $str->{'scalar_buffer'} = $2 || ""; 10376fb12b70Safresh1 } 10386fb12b70Safresh1 else { 10396fb12b70Safresh1 $str->{'scalar_buffer'} .= $data; 10406fb12b70Safresh1 $data = ""; 10416fb12b70Safresh1 } 10426fb12b70Safresh1 } 10436fb12b70Safresh1 elsif ($count eq 0) { 10446fb12b70Safresh1 $select->remove($fd); 10456fb12b70Safresh1 $fd->close(); 10466fb12b70Safresh1 if ($str->{'scalar_buffer'}) { 10476fb12b70Safresh1 $data = $str->{'scalar_buffer'} . "\n"; 10486fb12b70Safresh1 } 10496fb12b70Safresh1 } 10506fb12b70Safresh1 else { 10516fb12b70Safresh1 Carp::confess("error during sysread on [$fd]: " . $!); 10526fb12b70Safresh1 } 10536fb12b70Safresh1 10546fb12b70Safresh1 # $data contains only full lines (or last line if it was unfinished read 10556fb12b70Safresh1 # or now new-line in the output of the child); dat is processed 10566fb12b70Safresh1 # according to the "protocol" of socket 10576fb12b70Safresh1 if ($str->{'protocol'} eq 'info') { 10586fb12b70Safresh1 if ($data =~ /^spawned ([0-9]+?)\n(.*?)/so) { 1059b39c5158Smillert $child_child_pid = $1; 10606fb12b70Safresh1 $data = $2; 1061b39c5158Smillert } 10626fb12b70Safresh1 if ($data =~ /^reaped ([0-9]+?)\n(.*?)/so) { 1063b39c5158Smillert $child_child_pid = undef; 10646fb12b70Safresh1 $data = $2; 1065b39c5158Smillert } 10666fb12b70Safresh1 if ($data =~ /^[\d]+ killed with ([0-9]+?)\n(.*?)/so) { 1067898184e3Ssthen $child_killed_by_signal = $1; 10686fb12b70Safresh1 $data = $2; 1069b39c5158Smillert } 1070b39c5158Smillert 10716fb12b70Safresh1 # we don't expect any other data in info socket, so it's 10726fb12b70Safresh1 # some strange violation of protocol, better know about this 10736fb12b70Safresh1 if ($data) { 10746fb12b70Safresh1 Carp::confess("info protocol violation: [$data]"); 10756fb12b70Safresh1 } 10766fb12b70Safresh1 } 10776fb12b70Safresh1 if ($str->{'protocol'} eq 'stdout') { 1078898184e3Ssthen if (!$opts->{'discard_output'}) { 10796fb12b70Safresh1 $child_stdout .= $data; 10806fb12b70Safresh1 $child_merged .= $data; 1081898184e3Ssthen } 1082b39c5158Smillert 1083b39c5158Smillert if ($opts->{'stdout_handler'} && ref($opts->{'stdout_handler'}) eq 'CODE') { 10846fb12b70Safresh1 $opts->{'stdout_handler'}->($data); 1085b39c5158Smillert } 1086b39c5158Smillert } 10876fb12b70Safresh1 if ($str->{'protocol'} eq 'stderr') { 1088898184e3Ssthen if (!$opts->{'discard_output'}) { 10896fb12b70Safresh1 $child_stderr .= $data; 10906fb12b70Safresh1 $child_merged .= $data; 1091898184e3Ssthen } 10926fb12b70Safresh1 1093b39c5158Smillert if ($opts->{'stderr_handler'} && ref($opts->{'stderr_handler'}) eq 'CODE') { 10946fb12b70Safresh1 $opts->{'stderr_handler'}->($data); 1095b39c5158Smillert } 1096b39c5158Smillert } 1097b39c5158Smillert 10986fb12b70Safresh1 # process may finish (waitpid returns -1) before 10996fb12b70Safresh1 # we've read all of its output because of buffering; 11006fb12b70Safresh1 # so try to read all the way it is possible to read 11016fb12b70Safresh1 # in such case - this shouldn't be too much (unless 11026fb12b70Safresh1 # the buffer size is HUGE -- should introduce 11036fb12b70Safresh1 # another counter in such case, maybe later) 11046fb12b70Safresh1 # 11056fb12b70Safresh1 push @{$ready_fds}, $select->can_read(1/100) if $child_finished; 11066fb12b70Safresh1 } 11076fb12b70Safresh1 11089f11ffb7Safresh1 if ($opts->{'wait_loop_callback'} && ref($opts->{'wait_loop_callback'}) eq 'CODE') { 11099f11ffb7Safresh1 $opts->{'wait_loop_callback'}->(); 11109f11ffb7Safresh1 } 11119f11ffb7Safresh1 1112b39c5158Smillert Time::HiRes::usleep(1); 1113b39c5158Smillert } 1114b39c5158Smillert 1115b39c5158Smillert # $child_pid_pid is not defined in two cases: 1116b39c5158Smillert # * when our child was killed before 1117b39c5158Smillert # it had chance to tell us the pid 1118b39c5158Smillert # of the child it spawned. we can do 1119b39c5158Smillert # nothing in this case :( 1120b39c5158Smillert # * our child successfully reaped its child, 1121b39c5158Smillert # we have nothing left to do in this case 1122b39c5158Smillert # 1123b39c5158Smillert # defined $child_pid_pid means child's child 1124b39c5158Smillert # has not died but nobody is waiting for it, 1125898184e3Ssthen # killing it brutally. 1126b39c5158Smillert # 1127b39c5158Smillert if ($child_child_pid) { 1128b39c5158Smillert kill_gently($child_child_pid); 1129b39c5158Smillert } 1130b39c5158Smillert 1131898184e3Ssthen # in case there are forks in child which 1132898184e3Ssthen # do not forward or process signals (TERM) correctly 1133898184e3Ssthen # kill whole child process group, effectively trying 1134898184e3Ssthen # not to return with some children or their parts still running 1135898184e3Ssthen # 1136898184e3Ssthen # to be more accurate -- we need to be sure 1137898184e3Ssthen # that this is process group created by our child 1138898184e3Ssthen # (and not some other process group with the same pgid, 1139898184e3Ssthen # created just after death of our child) -- fortunately 1140898184e3Ssthen # this might happen only when process group ids 1141898184e3Ssthen # are reused quickly (there are lots of processes 1142898184e3Ssthen # spawning new process groups for example) 1143898184e3Ssthen # 1144898184e3Ssthen if ($opts->{'clean_up_children'}) { 1145898184e3Ssthen kill(-9, $pid); 1146898184e3Ssthen } 1147898184e3Ssthen 1148b39c5158Smillert # print "child $pid finished\n"; 1149b39c5158Smillert 1150b39c5158Smillert close($child_stdout_socket); 1151b39c5158Smillert close($child_stderr_socket); 1152b39c5158Smillert close($child_info_socket); 1153b39c5158Smillert 1154b39c5158Smillert my $o = { 1155b39c5158Smillert 'stdout' => $child_stdout, 1156b39c5158Smillert 'stderr' => $child_stderr, 1157b39c5158Smillert 'merged' => $child_merged, 1158b39c5158Smillert 'timeout' => $child_timedout ? $opts->{'timeout'} : 0, 1159b39c5158Smillert 'exit_code' => $child_exit_code, 1160898184e3Ssthen 'parent_died' => $parent_died, 1161898184e3Ssthen 'killed_by_signal' => $child_killed_by_signal, 1162898184e3Ssthen 'child_pgid' => $pid, 11636fb12b70Safresh1 'cmd' => $cmd, 1164b39c5158Smillert }; 1165b39c5158Smillert 1166b39c5158Smillert my $err_msg = ''; 1167b39c5158Smillert if ($o->{'exit_code'}) { 1168b39c5158Smillert $err_msg .= "exited with code [$o->{'exit_code'}]\n"; 1169b39c5158Smillert } 1170b39c5158Smillert if ($o->{'timeout'}) { 1171b39c5158Smillert $err_msg .= "ran more than [$o->{'timeout'}] seconds\n"; 1172b39c5158Smillert } 1173898184e3Ssthen if ($o->{'parent_died'}) { 1174898184e3Ssthen $err_msg .= "parent died\n"; 1175898184e3Ssthen } 11766fb12b70Safresh1 if ($o->{'stdout'} && !$opts->{'non_empty_stdout_ok'}) { 1177b39c5158Smillert $err_msg .= "stdout:\n" . $o->{'stdout'} . "\n"; 1178b39c5158Smillert } 1179b39c5158Smillert if ($o->{'stderr'}) { 1180b39c5158Smillert $err_msg .= "stderr:\n" . $o->{'stderr'} . "\n"; 1181b39c5158Smillert } 1182898184e3Ssthen if ($o->{'killed_by_signal'}) { 1183898184e3Ssthen $err_msg .= "killed by signal [" . $o->{'killed_by_signal'} . "]\n"; 1184898184e3Ssthen } 1185b39c5158Smillert $o->{'err_msg'} = $err_msg; 1186b39c5158Smillert 1187898184e3Ssthen if ($orig_sig_child) { 1188898184e3Ssthen $SIG{'CHLD'} = $orig_sig_child; 1189898184e3Ssthen } 1190898184e3Ssthen else { 1191898184e3Ssthen delete($SIG{'CHLD'}); 1192898184e3Ssthen } 1193898184e3Ssthen 11949f11ffb7Safresh1 uninstall_signals(); 11959f11ffb7Safresh1 1196b39c5158Smillert return $o; 1197b39c5158Smillert } 1198b39c5158Smillert else { 11996fb12b70Safresh1 Carp::confess("cannot fork: $!") unless defined($pid); 1200b39c5158Smillert 1201b39c5158Smillert # create new process session for open3 call, 1202b39c5158Smillert # so we hopefully can kill all the subprocesses 1203b39c5158Smillert # which might be spawned in it (except for those 1204b39c5158Smillert # which do setsid theirselves -- can't do anything 1205b39c5158Smillert # with those) 1206b39c5158Smillert 1207*56d68f1eSafresh1 POSIX::setsid() == -1 and Carp::confess("Error running setsid: " . $!); 1208b39c5158Smillert 1209898184e3Ssthen if ($opts->{'child_BEGIN'} && ref($opts->{'child_BEGIN'}) eq 'CODE') { 1210898184e3Ssthen $opts->{'child_BEGIN'}->(); 1211898184e3Ssthen } 1212898184e3Ssthen 1213b39c5158Smillert close($child_stdout_socket); 1214b39c5158Smillert close($child_stderr_socket); 1215b39c5158Smillert close($child_info_socket); 1216b39c5158Smillert 1217898184e3Ssthen my $child_exit_code; 1218898184e3Ssthen 1219898184e3Ssthen # allow both external programs 1220898184e3Ssthen # and internal perl calls 1221898184e3Ssthen if (!ref($cmd)) { 1222898184e3Ssthen $child_exit_code = open3_run($cmd, { 1223b39c5158Smillert 'parent_info' => $parent_info_socket, 1224b39c5158Smillert 'parent_stdout' => $parent_stdout_socket, 1225b39c5158Smillert 'parent_stderr' => $parent_stderr_socket, 1226b39c5158Smillert 'child_stdin' => $opts->{'child_stdin'}, 1227b46d8ef2Safresh1 'original_ppid' => $ppid, 1228b39c5158Smillert }); 1229898184e3Ssthen } 1230898184e3Ssthen elsif (ref($cmd) eq 'CODE') { 12316fb12b70Safresh1 # reopen STDOUT and STDERR for child code: 12326fb12b70Safresh1 # https://rt.cpan.org/Ticket/Display.html?id=85912 12336fb12b70Safresh1 open STDOUT, '>&', $parent_stdout_socket || Carp::confess("Unable to reopen STDOUT: $!\n"); 12346fb12b70Safresh1 open STDERR, '>&', $parent_stderr_socket || Carp::confess("Unable to reopen STDERR: $!\n"); 12356fb12b70Safresh1 1236898184e3Ssthen $child_exit_code = $cmd->({ 1237898184e3Ssthen 'opts' => $opts, 1238898184e3Ssthen 'parent_info' => $parent_info_socket, 1239898184e3Ssthen 'parent_stdout' => $parent_stdout_socket, 1240898184e3Ssthen 'parent_stderr' => $parent_stderr_socket, 1241898184e3Ssthen 'child_stdin' => $opts->{'child_stdin'}, 1242898184e3Ssthen }); 1243898184e3Ssthen } 1244898184e3Ssthen else { 1245898184e3Ssthen print $parent_stderr_socket "Invalid command reference: " . ref($cmd) . "\n"; 1246898184e3Ssthen $child_exit_code = 1; 1247898184e3Ssthen } 1248b39c5158Smillert 1249b39c5158Smillert close($parent_stdout_socket); 1250b39c5158Smillert close($parent_stderr_socket); 1251b39c5158Smillert close($parent_info_socket); 1252b39c5158Smillert 1253898184e3Ssthen if ($opts->{'child_END'} && ref($opts->{'child_END'}) eq 'CODE') { 1254898184e3Ssthen $opts->{'child_END'}->(); 1255898184e3Ssthen } 1256898184e3Ssthen 12576fb12b70Safresh1 $| = 1; 125891f110e0Safresh1 POSIX::_exit $child_exit_code; 1259b39c5158Smillert } 1260b39c5158Smillert} 1261b39c5158Smillert 1262b39c5158Smillertsub run { 1263b39c5158Smillert ### container to store things in 1264b39c5158Smillert my $self = bless {}, __PACKAGE__; 1265b39c5158Smillert 1266b39c5158Smillert my %hash = @_; 1267b39c5158Smillert 1268b39c5158Smillert ### if the user didn't provide a buffer, we'll store it here. 1269b39c5158Smillert my $def_buf = ''; 1270b39c5158Smillert 1271b39c5158Smillert my($verbose,$cmd,$buffer,$timeout); 1272b39c5158Smillert my $tmpl = { 1273b39c5158Smillert verbose => { default => $VERBOSE, store => \$verbose }, 1274b39c5158Smillert buffer => { default => \$def_buf, store => \$buffer }, 1275b39c5158Smillert command => { required => 1, store => \$cmd, 1276b39c5158Smillert allow => sub { !ref($_[0]) or ref($_[0]) eq 'ARRAY' }, 1277b39c5158Smillert }, 1278b39c5158Smillert timeout => { default => 0, store => \$timeout }, 1279b39c5158Smillert }; 1280b39c5158Smillert 1281b39c5158Smillert unless( check( $tmpl, \%hash, $VERBOSE ) ) { 1282b39c5158Smillert Carp::carp( loc( "Could not validate input: %1", 1283b39c5158Smillert Params::Check->last_error ) ); 1284b39c5158Smillert return; 1285b39c5158Smillert }; 1286b39c5158Smillert 1287b39c5158Smillert $cmd = _quote_args_vms( $cmd ) if IS_VMS; 1288b39c5158Smillert 1289b39c5158Smillert ### strip any empty elements from $cmd if present 1290898184e3Ssthen if ( $ALLOW_NULL_ARGS ) { 1291898184e3Ssthen $cmd = [ grep { defined } @$cmd ] if ref $cmd; 1292898184e3Ssthen } 1293898184e3Ssthen else { 1294b39c5158Smillert $cmd = [ grep { defined && length } @$cmd ] if ref $cmd; 1295898184e3Ssthen } 1296b39c5158Smillert 1297b39c5158Smillert my $pp_cmd = (ref $cmd ? "@$cmd" : $cmd); 1298b39c5158Smillert print loc("Running [%1]...\n", $pp_cmd ) if $verbose; 1299b39c5158Smillert 1300b39c5158Smillert ### did the user pass us a buffer to fill or not? if so, set this 1301b39c5158Smillert ### flag so we know what is expected of us 1302b39c5158Smillert ### XXX this is now being ignored. in the future, we could add diagnostic 1303b39c5158Smillert ### messages based on this logic 1304b39c5158Smillert #my $user_provided_buffer = $buffer == \$def_buf ? 0 : 1; 1305b39c5158Smillert 1306b39c5158Smillert ### buffers that are to be captured 1307b39c5158Smillert my( @buffer, @buff_err, @buff_out ); 1308b39c5158Smillert 1309b39c5158Smillert ### capture STDOUT 1310b39c5158Smillert my $_out_handler = sub { 1311b39c5158Smillert my $buf = shift; 1312b39c5158Smillert return unless defined $buf; 1313b39c5158Smillert 1314b39c5158Smillert print STDOUT $buf if $verbose; 1315b39c5158Smillert push @buffer, $buf; 1316b39c5158Smillert push @buff_out, $buf; 1317b39c5158Smillert }; 1318b39c5158Smillert 1319b39c5158Smillert ### capture STDERR 1320b39c5158Smillert my $_err_handler = sub { 1321b39c5158Smillert my $buf = shift; 1322b39c5158Smillert return unless defined $buf; 1323b39c5158Smillert 1324b39c5158Smillert print STDERR $buf if $verbose; 1325b39c5158Smillert push @buffer, $buf; 1326b39c5158Smillert push @buff_err, $buf; 1327b39c5158Smillert }; 1328b39c5158Smillert 1329b39c5158Smillert 1330b39c5158Smillert ### flag to indicate we have a buffer captured 1331b39c5158Smillert my $have_buffer = $self->can_capture_buffer ? 1 : 0; 1332b39c5158Smillert 1333b39c5158Smillert ### flag indicating if the subcall went ok 1334b39c5158Smillert my $ok; 1335b39c5158Smillert 13366fb12b70Safresh1 ### don't look at previous errors: 1337b39c5158Smillert local $?; 1338b39c5158Smillert local $@; 1339b39c5158Smillert local $!; 1340b39c5158Smillert 1341b39c5158Smillert ### we might be having a timeout set 1342b39c5158Smillert eval { 1343b39c5158Smillert local $SIG{ALRM} = sub { die bless sub { 1344b39c5158Smillert ALARM_CLASS . 1345b39c5158Smillert qq[: Command '$pp_cmd' aborted by alarm after $timeout seconds] 1346b39c5158Smillert }, ALARM_CLASS } if $timeout; 1347b39c5158Smillert alarm $timeout || 0; 1348b39c5158Smillert 1349b39c5158Smillert ### IPC::Run is first choice if $USE_IPC_RUN is set. 1350898184e3Ssthen if( !IS_WIN32 and $USE_IPC_RUN and $self->can_use_ipc_run( 1 ) ) { 1351b39c5158Smillert ### ipc::run handlers needs the command as a string or an array ref 1352b39c5158Smillert 1353b39c5158Smillert $self->_debug( "# Using IPC::Run. Have buffer: $have_buffer" ) 1354b39c5158Smillert if $DEBUG; 1355b39c5158Smillert 1356b39c5158Smillert $ok = $self->_ipc_run( $cmd, $_out_handler, $_err_handler ); 1357b39c5158Smillert 1358b39c5158Smillert ### since IPC::Open3 works on all platforms, and just fails on 1359b39c5158Smillert ### win32 for capturing buffers, do that ideally 1360b39c5158Smillert } elsif ( $USE_IPC_OPEN3 and $self->can_use_ipc_open3( 1 ) ) { 1361b39c5158Smillert 1362b39c5158Smillert $self->_debug("# Using IPC::Open3. Have buffer: $have_buffer") 1363b39c5158Smillert if $DEBUG; 1364b39c5158Smillert 1365b39c5158Smillert ### in case there are pipes in there; 1366b39c5158Smillert ### IPC::Open3 will call exec and exec will do the right thing 1367898184e3Ssthen 1368898184e3Ssthen my $method = IS_WIN32 ? '_open3_run_win32' : '_open3_run'; 1369898184e3Ssthen 1370898184e3Ssthen $ok = $self->$method( 1371b39c5158Smillert $cmd, $_out_handler, $_err_handler, $verbose 1372b39c5158Smillert ); 1373b39c5158Smillert 1374b39c5158Smillert ### if we are allowed to run verbose, just dispatch the system command 1375b39c5158Smillert } else { 1376b39c5158Smillert $self->_debug( "# Using system(). Have buffer: $have_buffer" ) 1377b39c5158Smillert if $DEBUG; 1378b39c5158Smillert $ok = $self->_system_run( $cmd, $verbose ); 1379b39c5158Smillert } 1380b39c5158Smillert 1381b39c5158Smillert alarm 0; 1382b39c5158Smillert }; 1383b39c5158Smillert 1384b39c5158Smillert ### restore STDIN after duping, or STDIN will be closed for 1385b39c5158Smillert ### this current perl process! 1386b39c5158Smillert $self->__reopen_fds( @{ $self->_fds} ) if $self->_fds; 1387b39c5158Smillert 1388b39c5158Smillert my $err; 1389b39c5158Smillert unless( $ok ) { 1390b39c5158Smillert ### alarm happened 1391b39c5158Smillert if ( $@ and ref $@ and $@->isa( ALARM_CLASS ) ) { 1392b39c5158Smillert $err = $@->(); # the error code is an expired alarm 1393b39c5158Smillert 1394b39c5158Smillert ### another error happened, set by the dispatchub 1395b39c5158Smillert } else { 1396b39c5158Smillert $err = $self->error; 1397b39c5158Smillert } 1398b39c5158Smillert } 1399b39c5158Smillert 1400b39c5158Smillert ### fill the buffer; 1401b39c5158Smillert $$buffer = join '', @buffer if @buffer; 1402b39c5158Smillert 1403b39c5158Smillert ### return a list of flags and buffers (if available) in list 1404b39c5158Smillert ### context, or just a simple 'ok' in scalar 1405b39c5158Smillert return wantarray 1406b39c5158Smillert ? $have_buffer 1407b39c5158Smillert ? ($ok, $err, \@buffer, \@buff_out, \@buff_err) 1408b39c5158Smillert : ($ok, $err ) 1409b39c5158Smillert : $ok 1410b39c5158Smillert 1411b39c5158Smillert 1412b39c5158Smillert} 1413b39c5158Smillert 1414898184e3Ssthensub _open3_run_win32 { 1415898184e3Ssthen my $self = shift; 1416898184e3Ssthen my $cmd = shift; 1417898184e3Ssthen my $outhand = shift; 1418898184e3Ssthen my $errhand = shift; 1419898184e3Ssthen 14206fb12b70Safresh1 require Socket; 14216fb12b70Safresh1 1422898184e3Ssthen my $pipe = sub { 14236fb12b70Safresh1 socketpair($_[0], $_[1], &Socket::AF_UNIX, &Socket::SOCK_STREAM, &Socket::PF_UNSPEC) 1424898184e3Ssthen or return undef; 1425898184e3Ssthen shutdown($_[0], 1); # No more writing for reader 1426898184e3Ssthen shutdown($_[1], 0); # No more reading for writer 1427898184e3Ssthen return 1; 1428898184e3Ssthen }; 1429898184e3Ssthen 1430898184e3Ssthen my $open3 = sub { 1431898184e3Ssthen local (*TO_CHLD_R, *TO_CHLD_W); 1432898184e3Ssthen local (*FR_CHLD_R, *FR_CHLD_W); 1433898184e3Ssthen local (*FR_CHLD_ERR_R, *FR_CHLD_ERR_W); 1434898184e3Ssthen 1435898184e3Ssthen $pipe->(*TO_CHLD_R, *TO_CHLD_W ) or die $^E; 1436898184e3Ssthen $pipe->(*FR_CHLD_R, *FR_CHLD_W ) or die $^E; 1437898184e3Ssthen $pipe->(*FR_CHLD_ERR_R, *FR_CHLD_ERR_W) or die $^E; 1438898184e3Ssthen 1439898184e3Ssthen my $pid = IPC::Open3::open3('>&TO_CHLD_R', '<&FR_CHLD_W', '<&FR_CHLD_ERR_W', @_); 1440898184e3Ssthen 1441898184e3Ssthen return ( $pid, *TO_CHLD_W, *FR_CHLD_R, *FR_CHLD_ERR_R ); 1442898184e3Ssthen }; 1443898184e3Ssthen 1444898184e3Ssthen $cmd = [ grep { defined && length } @$cmd ] if ref $cmd; 1445898184e3Ssthen $cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd ); 1446898184e3Ssthen 1447898184e3Ssthen my ($pid, $to_chld, $fr_chld, $fr_chld_err) = 1448898184e3Ssthen $open3->( ( ref $cmd ? @$cmd : $cmd ) ); 1449898184e3Ssthen 1450898184e3Ssthen my $in_sel = IO::Select->new(); 1451898184e3Ssthen my $out_sel = IO::Select->new(); 1452898184e3Ssthen 1453898184e3Ssthen my %objs; 1454898184e3Ssthen 1455898184e3Ssthen $objs{ fileno( $fr_chld ) } = $outhand; 1456898184e3Ssthen $objs{ fileno( $fr_chld_err ) } = $errhand; 1457898184e3Ssthen $in_sel->add( $fr_chld ); 1458898184e3Ssthen $in_sel->add( $fr_chld_err ); 1459898184e3Ssthen 1460898184e3Ssthen close($to_chld); 1461898184e3Ssthen 1462898184e3Ssthen while ($in_sel->count() + $out_sel->count()) { 1463898184e3Ssthen my ($ins, $outs) = IO::Select::select($in_sel, $out_sel, undef); 1464898184e3Ssthen 1465898184e3Ssthen for my $fh (@$ins) { 1466898184e3Ssthen my $obj = $objs{ fileno($fh) }; 1467898184e3Ssthen my $buf; 1468898184e3Ssthen my $bytes_read = sysread($fh, $buf, 64*1024 ); #, length($buf)); 1469898184e3Ssthen if (!$bytes_read) { 1470898184e3Ssthen $in_sel->remove($fh); 1471898184e3Ssthen } 1472898184e3Ssthen else { 1473898184e3Ssthen $obj->( "$buf" ); 1474898184e3Ssthen } 1475898184e3Ssthen } 1476898184e3Ssthen 1477898184e3Ssthen for my $fh (@$outs) { 1478898184e3Ssthen } 1479898184e3Ssthen } 1480898184e3Ssthen 1481898184e3Ssthen waitpid($pid, 0); 1482898184e3Ssthen 1483898184e3Ssthen ### some error occurred 1484898184e3Ssthen if( $? ) { 1485898184e3Ssthen $self->error( $self->_pp_child_error( $cmd, $? ) ); 1486898184e3Ssthen $self->ok( 0 ); 1487898184e3Ssthen return; 1488898184e3Ssthen } else { 1489898184e3Ssthen return $self->ok( 1 ); 1490898184e3Ssthen } 1491898184e3Ssthen} 1492898184e3Ssthen 1493b39c5158Smillertsub _open3_run { 1494b39c5158Smillert my $self = shift; 1495b39c5158Smillert my $cmd = shift; 1496b39c5158Smillert my $_out_handler = shift; 1497b39c5158Smillert my $_err_handler = shift; 1498b39c5158Smillert my $verbose = shift || 0; 1499b39c5158Smillert 1500b39c5158Smillert ### Following code are adapted from Friar 'abstracts' in the 1501b39c5158Smillert ### Perl Monastery (http://www.perlmonks.org/index.pl?node_id=151886). 1502b39c5158Smillert ### XXX that code didn't work. 1503b39c5158Smillert ### we now use the following code, thanks to theorbtwo 1504b39c5158Smillert 1505b39c5158Smillert ### define them beforehand, so we always have defined FH's 1506b39c5158Smillert ### to read from. 1507b39c5158Smillert use Symbol; 1508b39c5158Smillert my $kidout = Symbol::gensym(); 1509b39c5158Smillert my $kiderror = Symbol::gensym(); 1510b39c5158Smillert 1511b39c5158Smillert ### Dup the filehandle so we can pass 'our' STDIN to the 1512b39c5158Smillert ### child process. This stops us from having to pump input 1513b39c5158Smillert ### from ourselves to the childprocess. However, we will need 1514b39c5158Smillert ### to revive the FH afterwards, as IPC::Open3 closes it. 1515b39c5158Smillert ### We'll do the same for STDOUT and STDERR. It works without 1516b39c5158Smillert ### duping them on non-unix derivatives, but not on win32. 1517b39c5158Smillert my @fds_to_dup = ( IS_WIN32 && !$verbose 1518b39c5158Smillert ? qw[STDIN STDOUT STDERR] 1519b39c5158Smillert : qw[STDIN] 1520b39c5158Smillert ); 1521b39c5158Smillert $self->_fds( \@fds_to_dup ); 1522b39c5158Smillert $self->__dup_fds( @fds_to_dup ); 1523b39c5158Smillert 1524b39c5158Smillert ### pipes have to come in a quoted string, and that clashes with 1525b39c5158Smillert ### whitespace. This sub fixes up such commands so they run properly 1526b39c5158Smillert $cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd ); 1527b39c5158Smillert 15286fb12b70Safresh1 ### don't stringify @$cmd, so spaces in filenames/paths are 1529b39c5158Smillert ### treated properly 1530b39c5158Smillert my $pid = eval { 1531b39c5158Smillert IPC::Open3::open3( 1532b39c5158Smillert '<&STDIN', 1533b39c5158Smillert (IS_WIN32 ? '>&STDOUT' : $kidout), 1534b39c5158Smillert (IS_WIN32 ? '>&STDERR' : $kiderror), 1535b39c5158Smillert ( ref $cmd ? @$cmd : $cmd ), 1536b39c5158Smillert ); 1537b39c5158Smillert }; 1538b39c5158Smillert 1539b39c5158Smillert ### open3 error occurred 1540b39c5158Smillert if( $@ and $@ =~ /^open3:/ ) { 1541b39c5158Smillert $self->ok( 0 ); 1542b39c5158Smillert $self->error( $@ ); 1543b39c5158Smillert return; 1544b39c5158Smillert }; 1545b39c5158Smillert 1546b39c5158Smillert ### use OUR stdin, not $kidin. Somehow, 1547b39c5158Smillert ### we never get the input.. so jump through 1548b39c5158Smillert ### some hoops to do it :( 1549b39c5158Smillert my $selector = IO::Select->new( 1550b39c5158Smillert (IS_WIN32 ? \*STDERR : $kiderror), 1551b39c5158Smillert \*STDIN, 1552b39c5158Smillert (IS_WIN32 ? \*STDOUT : $kidout) 1553b39c5158Smillert ); 1554b39c5158Smillert 1555b39c5158Smillert STDOUT->autoflush(1); STDERR->autoflush(1); STDIN->autoflush(1); 1556b39c5158Smillert $kidout->autoflush(1) if UNIVERSAL::can($kidout, 'autoflush'); 1557b39c5158Smillert $kiderror->autoflush(1) if UNIVERSAL::can($kiderror, 'autoflush'); 1558b39c5158Smillert 1559898184e3Ssthen ### add an explicit break statement 1560b39c5158Smillert ### code courtesy of theorbtwo from #london.pm 1561b39c5158Smillert my $stdout_done = 0; 1562b39c5158Smillert my $stderr_done = 0; 1563b39c5158Smillert OUTER: while ( my @ready = $selector->can_read ) { 1564b39c5158Smillert 1565b39c5158Smillert for my $h ( @ready ) { 1566b39c5158Smillert my $buf; 1567b39c5158Smillert 1568b39c5158Smillert ### $len is the amount of bytes read 1569b39c5158Smillert my $len = sysread( $h, $buf, 4096 ); # try to read 4096 bytes 1570b39c5158Smillert 1571b39c5158Smillert ### see perldoc -f sysread: it returns undef on error, 1572b39c5158Smillert ### so bail out. 1573b39c5158Smillert if( not defined $len ) { 1574b39c5158Smillert warn(loc("Error reading from process: %1", $!)); 1575b39c5158Smillert last OUTER; 1576b39c5158Smillert } 1577b39c5158Smillert 1578b39c5158Smillert ### check for $len. it may be 0, at which point we're 1579b39c5158Smillert ### done reading, so don't try to process it. 1580b39c5158Smillert ### if we would print anyway, we'd provide bogus information 1581b39c5158Smillert $_out_handler->( "$buf" ) if $len && $h == $kidout; 1582b39c5158Smillert $_err_handler->( "$buf" ) if $len && $h == $kiderror; 1583b39c5158Smillert 1584b39c5158Smillert ### Wait till child process is done printing to both 1585b39c5158Smillert ### stdout and stderr. 1586b39c5158Smillert $stdout_done = 1 if $h == $kidout and $len == 0; 1587b39c5158Smillert $stderr_done = 1 if $h == $kiderror and $len == 0; 1588b39c5158Smillert last OUTER if ($stdout_done && $stderr_done); 1589b39c5158Smillert } 1590b39c5158Smillert } 1591b39c5158Smillert 1592b39c5158Smillert waitpid $pid, 0; # wait for it to die 1593b39c5158Smillert 1594b39c5158Smillert ### restore STDIN after duping, or STDIN will be closed for 1595b39c5158Smillert ### this current perl process! 1596b39c5158Smillert ### done in the parent call now 1597b39c5158Smillert # $self->__reopen_fds( @fds_to_dup ); 1598b39c5158Smillert 1599b39c5158Smillert ### some error occurred 1600b39c5158Smillert if( $? ) { 1601b39c5158Smillert $self->error( $self->_pp_child_error( $cmd, $? ) ); 1602b39c5158Smillert $self->ok( 0 ); 1603b39c5158Smillert return; 1604b39c5158Smillert } else { 1605b39c5158Smillert return $self->ok( 1 ); 1606b39c5158Smillert } 1607b39c5158Smillert} 1608b39c5158Smillert 1609898184e3Ssthen### Text::ParseWords::shellwords() uses unix semantics. that will break 1610b39c5158Smillert### on win32 1611b39c5158Smillert{ my $parse_sub = IS_WIN32 1612b39c5158Smillert ? __PACKAGE__->can('_split_like_shell_win32') 1613b39c5158Smillert : Text::ParseWords->can('shellwords'); 1614b39c5158Smillert 1615b39c5158Smillert sub _ipc_run { 1616b39c5158Smillert my $self = shift; 1617b39c5158Smillert my $cmd = shift; 1618b39c5158Smillert my $_out_handler = shift; 1619b39c5158Smillert my $_err_handler = shift; 1620b39c5158Smillert 1621b39c5158Smillert STDOUT->autoflush(1); STDERR->autoflush(1); 1622b39c5158Smillert 1623b39c5158Smillert ### a command like: 1624b39c5158Smillert # [ 1625b39c5158Smillert # '/usr/bin/gzip', 1626b39c5158Smillert # '-cdf', 1627b39c5158Smillert # '/Users/kane/sources/p4/other/archive-extract/t/src/x.tgz', 1628b39c5158Smillert # '|', 1629b39c5158Smillert # '/usr/bin/tar', 1630b39c5158Smillert # '-tf -' 1631b39c5158Smillert # ] 1632b39c5158Smillert ### needs to become: 1633b39c5158Smillert # [ 1634b39c5158Smillert # ['/usr/bin/gzip', '-cdf', 1635b39c5158Smillert # '/Users/kane/sources/p4/other/archive-extract/t/src/x.tgz'] 1636b39c5158Smillert # '|', 1637b39c5158Smillert # ['/usr/bin/tar', '-tf -'] 1638b39c5158Smillert # ] 1639b39c5158Smillert 1640b39c5158Smillert 1641b39c5158Smillert my @command; 1642b39c5158Smillert my $special_chars; 1643b39c5158Smillert 1644b39c5158Smillert my $re = do { my $x = join '', SPECIAL_CHARS; qr/([$x])/ }; 1645b39c5158Smillert if( ref $cmd ) { 1646b39c5158Smillert my $aref = []; 1647b39c5158Smillert for my $item (@$cmd) { 1648b39c5158Smillert if( $item =~ $re ) { 1649b39c5158Smillert push @command, $aref, $item; 1650b39c5158Smillert $aref = []; 1651b39c5158Smillert $special_chars .= $1; 1652b39c5158Smillert } else { 1653b39c5158Smillert push @$aref, $item; 1654b39c5158Smillert } 1655b39c5158Smillert } 1656b39c5158Smillert push @command, $aref; 1657b39c5158Smillert } else { 1658b39c5158Smillert @command = map { if( $_ =~ $re ) { 1659b39c5158Smillert $special_chars .= $1; $_; 1660b39c5158Smillert } else { 1661b39c5158Smillert# [ split /\s+/ ] 1662b39c5158Smillert [ map { m/[ ]/ ? qq{'$_'} : $_ } $parse_sub->($_) ] 1663b39c5158Smillert } 1664b39c5158Smillert } split( /\s*$re\s*/, $cmd ); 1665b39c5158Smillert } 1666b39c5158Smillert 1667b39c5158Smillert ### if there's a pipe in the command, *STDIN needs to 1668b39c5158Smillert ### be inserted *BEFORE* the pipe, to work on win32 1669b39c5158Smillert ### this also works on *nix, so we should do it when possible 1670b39c5158Smillert ### this should *also* work on multiple pipes in the command 1671b39c5158Smillert ### if there's no pipe in the command, append STDIN to the back 1672b39c5158Smillert ### of the command instead. 1673b39c5158Smillert ### XXX seems IPC::Run works it out for itself if you just 16746fb12b70Safresh1 ### don't pass STDIN at all. 1675b39c5158Smillert # if( $special_chars and $special_chars =~ /\|/ ) { 1676b39c5158Smillert # ### only add STDIN the first time.. 1677b39c5158Smillert # my $i; 1678b39c5158Smillert # @command = map { ($_ eq '|' && not $i++) 1679b39c5158Smillert # ? ( \*STDIN, $_ ) 1680b39c5158Smillert # : $_ 1681b39c5158Smillert # } @command; 1682b39c5158Smillert # } else { 1683b39c5158Smillert # push @command, \*STDIN; 1684b39c5158Smillert # } 1685b39c5158Smillert 1686b39c5158Smillert # \*STDIN is already included in the @command, see a few lines up 1687b39c5158Smillert my $ok = eval { IPC::Run::run( @command, 1688b39c5158Smillert fileno(STDOUT).'>', 1689b39c5158Smillert $_out_handler, 1690b39c5158Smillert fileno(STDERR).'>', 1691b39c5158Smillert $_err_handler 1692b39c5158Smillert ) 1693b39c5158Smillert }; 1694b39c5158Smillert 1695b39c5158Smillert ### all is well 1696b39c5158Smillert if( $ok ) { 1697b39c5158Smillert return $self->ok( $ok ); 1698b39c5158Smillert 1699b39c5158Smillert ### some error occurred 1700b39c5158Smillert } else { 1701b39c5158Smillert $self->ok( 0 ); 1702b39c5158Smillert 1703b39c5158Smillert ### if the eval fails due to an exception, deal with it 1704b39c5158Smillert ### unless it's an alarm 1705b39c5158Smillert if( $@ and not UNIVERSAL::isa( $@, ALARM_CLASS ) ) { 1706b39c5158Smillert $self->error( $@ ); 1707b39c5158Smillert 1708b39c5158Smillert ### if it *is* an alarm, propagate 1709b39c5158Smillert } elsif( $@ ) { 1710b39c5158Smillert die $@; 1711b39c5158Smillert 1712b39c5158Smillert ### some error in the sub command 1713b39c5158Smillert } else { 1714b39c5158Smillert $self->error( $self->_pp_child_error( $cmd, $? ) ); 1715b39c5158Smillert } 1716b39c5158Smillert 1717b39c5158Smillert return; 1718b39c5158Smillert } 1719b39c5158Smillert } 1720b39c5158Smillert} 1721b39c5158Smillert 1722b39c5158Smillertsub _system_run { 1723b39c5158Smillert my $self = shift; 1724b39c5158Smillert my $cmd = shift; 1725b39c5158Smillert my $verbose = shift || 0; 1726b39c5158Smillert 1727b39c5158Smillert ### pipes have to come in a quoted string, and that clashes with 1728b39c5158Smillert ### whitespace. This sub fixes up such commands so they run properly 1729b39c5158Smillert $cmd = $self->__fix_cmd_whitespace_and_special_chars( $cmd ); 1730b39c5158Smillert 1731b39c5158Smillert my @fds_to_dup = $verbose ? () : qw[STDOUT STDERR]; 1732b39c5158Smillert $self->_fds( \@fds_to_dup ); 1733b39c5158Smillert $self->__dup_fds( @fds_to_dup ); 1734b39c5158Smillert 1735b39c5158Smillert ### system returns 'true' on failure -- the exit code of the cmd 1736b39c5158Smillert $self->ok( 1 ); 1737b39c5158Smillert system( ref $cmd ? @$cmd : $cmd ) == 0 or do { 1738b39c5158Smillert $self->error( $self->_pp_child_error( $cmd, $? ) ); 1739b39c5158Smillert $self->ok( 0 ); 1740b39c5158Smillert }; 1741b39c5158Smillert 1742b39c5158Smillert ### done in the parent call now 1743b39c5158Smillert #$self->__reopen_fds( @fds_to_dup ); 1744b39c5158Smillert 1745b39c5158Smillert return unless $self->ok; 1746b39c5158Smillert return $self->ok; 1747b39c5158Smillert} 1748b39c5158Smillert 1749b39c5158Smillert{ my %sc_lookup = map { $_ => $_ } SPECIAL_CHARS; 1750b39c5158Smillert 1751b39c5158Smillert 1752b39c5158Smillert sub __fix_cmd_whitespace_and_special_chars { 1753b39c5158Smillert my $self = shift; 1754b39c5158Smillert my $cmd = shift; 1755b39c5158Smillert 1756b39c5158Smillert ### command has a special char in it 1757b39c5158Smillert if( ref $cmd and grep { $sc_lookup{$_} } @$cmd ) { 1758b39c5158Smillert 1759b39c5158Smillert ### since we have special chars, we have to quote white space 1760b39c5158Smillert ### this *may* conflict with the parsing :( 1761b39c5158Smillert my $fixed; 1762b39c5158Smillert my @cmd = map { / / ? do { $fixed++; QUOTE.$_.QUOTE } : $_ } @$cmd; 1763b39c5158Smillert 1764b39c5158Smillert $self->_debug( "# Quoted $fixed arguments containing whitespace" ) 1765b39c5158Smillert if $DEBUG && $fixed; 1766b39c5158Smillert 1767b39c5158Smillert ### stringify it, so the special char isn't escaped as argument 1768b39c5158Smillert ### to the program 1769b39c5158Smillert $cmd = join ' ', @cmd; 1770b39c5158Smillert } 1771b39c5158Smillert 1772b39c5158Smillert return $cmd; 1773b39c5158Smillert } 1774b39c5158Smillert} 1775b39c5158Smillert 1776b39c5158Smillert### Command-line arguments (but not the command itself) must be quoted 1777b39c5158Smillert### to ensure case preservation. Borrowed from Module::Build with adaptations. 1778b39c5158Smillert### Patch for this supplied by Craig Berry, see RT #46288: [PATCH] Add argument 1779b39c5158Smillert### quoting for run() on VMS 1780b39c5158Smillertsub _quote_args_vms { 1781b39c5158Smillert ### Returns a command string with proper quoting so that the subprocess 1782b39c5158Smillert ### sees this same list of args, or if we get a single arg that is an 1783b39c5158Smillert ### array reference, quote the elements of it (except for the first) 1784b39c5158Smillert ### and return the reference. 1785b39c5158Smillert my @args = @_; 1786b39c5158Smillert my $got_arrayref = (scalar(@args) == 1 1787b39c5158Smillert && UNIVERSAL::isa($args[0], 'ARRAY')) 1788b39c5158Smillert ? 1 1789b39c5158Smillert : 0; 1790b39c5158Smillert 1791b39c5158Smillert @args = split(/\s+/, $args[0]) unless $got_arrayref || scalar(@args) > 1; 1792b39c5158Smillert 1793b39c5158Smillert my $cmd = $got_arrayref ? shift @{$args[0]} : shift @args; 1794b39c5158Smillert 1795b39c5158Smillert ### Do not quote qualifiers that begin with '/' or previously quoted args. 1796b39c5158Smillert map { if (/^[^\/\"]/) { 1797b39c5158Smillert $_ =~ s/\"/""/g; # escape C<"> by doubling 1798b39c5158Smillert $_ = q(").$_.q("); 1799b39c5158Smillert } 1800b39c5158Smillert } 1801b39c5158Smillert ($got_arrayref ? @{$args[0]} 1802b39c5158Smillert : @args 1803b39c5158Smillert ); 1804b39c5158Smillert 1805b39c5158Smillert $got_arrayref ? unshift(@{$args[0]}, $cmd) : unshift(@args, $cmd); 1806b39c5158Smillert 1807b39c5158Smillert return $got_arrayref ? $args[0] 1808b39c5158Smillert : join(' ', @args); 1809b39c5158Smillert} 1810b39c5158Smillert 1811b39c5158Smillert 1812b39c5158Smillert### XXX this is cribbed STRAIGHT from M::B 0.30 here: 1813b39c5158Smillert### http://search.cpan.org/src/KWILLIAMS/Module-Build-0.30/lib/Module/Build/Platform/Windows.pm:split_like_shell 1814b39c5158Smillert### XXX this *should* be integrated into text::parsewords 1815b39c5158Smillertsub _split_like_shell_win32 { 1816b39c5158Smillert # As it turns out, Windows command-parsing is very different from 1817b39c5158Smillert # Unix command-parsing. Double-quotes mean different things, 1818b39c5158Smillert # backslashes don't necessarily mean escapes, and so on. So we 1819b39c5158Smillert # can't use Text::ParseWords::shellwords() to break a command string 1820b39c5158Smillert # into words. The algorithm below was bashed out by Randy and Ken 1821b39c5158Smillert # (mostly Randy), and there are a lot of regression tests, so we 1822b39c5158Smillert # should feel free to adjust if desired. 1823b39c5158Smillert 1824b39c5158Smillert local $_ = shift; 1825b39c5158Smillert 1826b39c5158Smillert my @argv; 1827b39c5158Smillert return @argv unless defined() && length(); 1828b39c5158Smillert 1829b39c5158Smillert my $arg = ''; 1830b39c5158Smillert my( $i, $quote_mode ) = ( 0, 0 ); 1831b39c5158Smillert 1832b39c5158Smillert while ( $i < length() ) { 1833b39c5158Smillert 1834b39c5158Smillert my $ch = substr( $_, $i , 1 ); 1835b39c5158Smillert my $next_ch = substr( $_, $i+1, 1 ); 1836b39c5158Smillert 1837b39c5158Smillert if ( $ch eq '\\' && $next_ch eq '"' ) { 1838b39c5158Smillert $arg .= '"'; 1839b39c5158Smillert $i++; 1840b39c5158Smillert } elsif ( $ch eq '\\' && $next_ch eq '\\' ) { 1841b39c5158Smillert $arg .= '\\'; 1842b39c5158Smillert $i++; 1843b39c5158Smillert } elsif ( $ch eq '"' && $next_ch eq '"' && $quote_mode ) { 1844b39c5158Smillert $quote_mode = !$quote_mode; 1845b39c5158Smillert $arg .= '"'; 1846b39c5158Smillert $i++; 1847b39c5158Smillert } elsif ( $ch eq '"' && $next_ch eq '"' && !$quote_mode && 1848b39c5158Smillert ( $i + 2 == length() || 1849b39c5158Smillert substr( $_, $i + 2, 1 ) eq ' ' ) 1850b39c5158Smillert ) { # for cases like: a"" => [ 'a' ] 1851b39c5158Smillert push( @argv, $arg ); 1852b39c5158Smillert $arg = ''; 1853b39c5158Smillert $i += 2; 1854b39c5158Smillert } elsif ( $ch eq '"' ) { 1855b39c5158Smillert $quote_mode = !$quote_mode; 1856b39c5158Smillert } elsif ( $ch eq ' ' && !$quote_mode ) { 1857898184e3Ssthen push( @argv, $arg ) if defined( $arg ) && length( $arg ); 1858b39c5158Smillert $arg = ''; 1859b39c5158Smillert ++$i while substr( $_, $i + 1, 1 ) eq ' '; 1860b39c5158Smillert } else { 1861b39c5158Smillert $arg .= $ch; 1862b39c5158Smillert } 1863b39c5158Smillert 1864b39c5158Smillert $i++; 1865b39c5158Smillert } 1866b39c5158Smillert 1867b39c5158Smillert push( @argv, $arg ) if defined( $arg ) && length( $arg ); 1868b39c5158Smillert return @argv; 1869b39c5158Smillert} 1870b39c5158Smillert 1871b39c5158Smillert 1872b39c5158Smillert 1873b39c5158Smillert{ use File::Spec; 1874b39c5158Smillert use Symbol; 1875b39c5158Smillert 1876b39c5158Smillert my %Map = ( 1877b39c5158Smillert STDOUT => [qw|>&|, \*STDOUT, Symbol::gensym() ], 1878b39c5158Smillert STDERR => [qw|>&|, \*STDERR, Symbol::gensym() ], 1879b39c5158Smillert STDIN => [qw|<&|, \*STDIN, Symbol::gensym() ], 1880b39c5158Smillert ); 1881b39c5158Smillert 1882b39c5158Smillert ### dups FDs and stores them in a cache 1883b39c5158Smillert sub __dup_fds { 1884b39c5158Smillert my $self = shift; 1885b39c5158Smillert my @fds = @_; 1886b39c5158Smillert 1887b39c5158Smillert __PACKAGE__->_debug( "# Closing the following fds: @fds" ) if $DEBUG; 1888b39c5158Smillert 1889b39c5158Smillert for my $name ( @fds ) { 1890b39c5158Smillert my($redir, $fh, $glob) = @{$Map{$name}} or ( 1891b39c5158Smillert Carp::carp(loc("No such FD: '%1'", $name)), next ); 1892b39c5158Smillert 1893b39c5158Smillert ### MUST use the 2-arg version of open for dup'ing for 1894898184e3Ssthen ### 5.6.x compatibility. 5.8.x can use 3-arg open 1895b39c5158Smillert ### see perldoc5.6.2 -f open for details 1896b39c5158Smillert open $glob, $redir . fileno($fh) or ( 1897b39c5158Smillert Carp::carp(loc("Could not dup '$name': %1", $!)), 1898b39c5158Smillert return 1899b39c5158Smillert ); 1900b39c5158Smillert 1901b39c5158Smillert ### we should re-open this filehandle right now, not 1902b39c5158Smillert ### just dup it 1903b39c5158Smillert ### Use 2-arg version of open, as 5.5.x doesn't support 1904b39c5158Smillert ### 3-arg version =/ 1905b39c5158Smillert if( $redir eq '>&' ) { 1906b39c5158Smillert open( $fh, '>' . File::Spec->devnull ) or ( 1907b39c5158Smillert Carp::carp(loc("Could not reopen '$name': %1", $!)), 1908b39c5158Smillert return 1909b39c5158Smillert ); 1910b39c5158Smillert } 1911b39c5158Smillert } 1912b39c5158Smillert 1913b39c5158Smillert return 1; 1914b39c5158Smillert } 1915b39c5158Smillert 1916b39c5158Smillert ### reopens FDs from the cache 1917b39c5158Smillert sub __reopen_fds { 1918b39c5158Smillert my $self = shift; 1919b39c5158Smillert my @fds = @_; 1920b39c5158Smillert 1921b39c5158Smillert __PACKAGE__->_debug( "# Reopening the following fds: @fds" ) if $DEBUG; 1922b39c5158Smillert 1923b39c5158Smillert for my $name ( @fds ) { 1924b39c5158Smillert my($redir, $fh, $glob) = @{$Map{$name}} or ( 1925b39c5158Smillert Carp::carp(loc("No such FD: '%1'", $name)), next ); 1926b39c5158Smillert 1927b39c5158Smillert ### MUST use the 2-arg version of open for dup'ing for 1928898184e3Ssthen ### 5.6.x compatibility. 5.8.x can use 3-arg open 1929b39c5158Smillert ### see perldoc5.6.2 -f open for details 1930b39c5158Smillert open( $fh, $redir . fileno($glob) ) or ( 1931b39c5158Smillert Carp::carp(loc("Could not restore '$name': %1", $!)), 1932b39c5158Smillert return 1933b39c5158Smillert ); 1934b39c5158Smillert 1935b39c5158Smillert ### close this FD, we're not using it anymore 1936b39c5158Smillert close $glob; 1937b39c5158Smillert } 1938b39c5158Smillert return 1; 1939b39c5158Smillert 1940b39c5158Smillert } 1941b39c5158Smillert} 1942b39c5158Smillert 1943b39c5158Smillertsub _debug { 1944b39c5158Smillert my $self = shift; 1945b39c5158Smillert my $msg = shift or return; 1946b39c5158Smillert my $level = shift || 0; 1947b39c5158Smillert 1948b39c5158Smillert local $Carp::CarpLevel += $level; 1949b39c5158Smillert Carp::carp($msg); 1950b39c5158Smillert 1951b39c5158Smillert return 1; 1952b39c5158Smillert} 1953b39c5158Smillert 1954b39c5158Smillertsub _pp_child_error { 1955b39c5158Smillert my $self = shift; 1956b39c5158Smillert my $cmd = shift or return; 1957b39c5158Smillert my $ce = shift or return; 1958b39c5158Smillert my $pp_cmd = ref $cmd ? "@$cmd" : $cmd; 1959b39c5158Smillert 1960b39c5158Smillert 1961b39c5158Smillert my $str; 1962b39c5158Smillert if( $ce == -1 ) { 1963b39c5158Smillert ### Include $! in the error message, so that the user can 1964b39c5158Smillert ### see 'No such file or directory' versus 'Permission denied' 1965b39c5158Smillert ### versus 'Cannot fork' or whatever the cause was. 1966b39c5158Smillert $str = "Failed to execute '$pp_cmd': $!"; 1967b39c5158Smillert 1968b39c5158Smillert } elsif ( $ce & 127 ) { 1969b39c5158Smillert ### some signal 19706fb12b70Safresh1 $str = loc( "'%1' died with signal %2, %3 coredump", 1971b39c5158Smillert $pp_cmd, ($ce & 127), ($ce & 128) ? 'with' : 'without'); 1972b39c5158Smillert 1973b39c5158Smillert } else { 1974b39c5158Smillert ### Otherwise, the command run but gave error status. 1975b39c5158Smillert $str = "'$pp_cmd' exited with value " . ($ce >> 8); 1976b39c5158Smillert } 1977b39c5158Smillert 1978b39c5158Smillert $self->_debug( "# Child error '$ce' translated to: $str" ) if $DEBUG; 1979b39c5158Smillert 1980b39c5158Smillert return $str; 1981b39c5158Smillert} 1982b39c5158Smillert 1983b39c5158Smillert1; 1984b39c5158Smillert 19859f11ffb7Safresh1__END__ 19869f11ffb7Safresh1 1987b39c5158Smillert=head2 $q = QUOTE 1988b39c5158Smillert 1989b39c5158SmillertReturns the character used for quoting strings on this platform. This is 1990b39c5158Smillertusually a C<'> (single quote) on most systems, but some systems use different 1991b39c5158Smillertquotes. For example, C<Win32> uses C<"> (double quote). 1992b39c5158Smillert 1993b39c5158SmillertYou can use it as follows: 1994b39c5158Smillert 1995b39c5158Smillert use IPC::Cmd qw[run QUOTE]; 1996b39c5158Smillert my $cmd = q[echo ] . QUOTE . q[foo bar] . QUOTE; 1997b39c5158Smillert 1998b39c5158SmillertThis makes sure that C<foo bar> is treated as a string, rather than two 1999898184e3Ssthenseparate arguments to the C<echo> function. 2000b39c5158Smillert 2001b39c5158Smillert=head1 HOW IT WORKS 2002b39c5158Smillert 2003b39c5158SmillertC<run> will try to execute your command using the following logic: 2004b39c5158Smillert 2005b39c5158Smillert=over 4 2006b39c5158Smillert 2007b39c5158Smillert=item * 2008b39c5158Smillert 2009b39c5158SmillertIf you have C<IPC::Run> installed, and the variable C<$IPC::Cmd::USE_IPC_RUN> 2010898184e3Ssthenis set to true (See the L<"Global Variables"> section) use that to execute 2011898184e3Ssthenthe command. You will have the full output available in buffers, interactive commands 2012898184e3Ssthenare sure to work and you are guaranteed to have your verbosity 2013b39c5158Smillertsettings honored cleanly. 2014b39c5158Smillert 2015b39c5158Smillert=item * 2016b39c5158Smillert 2017b39c5158SmillertOtherwise, if the variable C<$IPC::Cmd::USE_IPC_OPEN3> is set to true 2018898184e3Ssthen(See the L<"Global Variables"> section), try to execute the command using 2019898184e3SsthenL<IPC::Open3>. Buffers will be available on all platforms, 2020b39c5158Smillertinteractive commands will still execute cleanly, and also your verbosity 2021b39c5158Smillertsettings will be adhered to nicely; 2022b39c5158Smillert 2023b39c5158Smillert=item * 2024b39c5158Smillert 2025898184e3SsthenOtherwise, if you have the C<verbose> argument set to true, we fall back 2026898184e3Ssthento a simple C<system()> call. We cannot capture any buffers, but 2027b39c5158Smillertinteractive commands will still work. 2028b39c5158Smillert 2029b39c5158Smillert=item * 2030b39c5158Smillert 2031b39c5158SmillertOtherwise we will try and temporarily redirect STDERR and STDOUT, do a 2032898184e3SsthenC<system()> call with your command and then re-open STDERR and STDOUT. 2033b39c5158SmillertThis is the method of last resort and will still allow you to execute 2034b39c5158Smillertyour commands cleanly. However, no buffers will be available. 2035b39c5158Smillert 2036b39c5158Smillert=back 2037b39c5158Smillert 2038b39c5158Smillert=head1 Global Variables 2039b39c5158Smillert 2040b39c5158SmillertThe behaviour of IPC::Cmd can be altered by changing the following 2041b39c5158Smillertglobal variables: 2042b39c5158Smillert 2043b39c5158Smillert=head2 $IPC::Cmd::VERBOSE 2044b39c5158Smillert 2045b39c5158SmillertThis controls whether IPC::Cmd will print any output from the 2046898184e3Ssthencommands to the screen or not. The default is 0. 2047b39c5158Smillert 2048b39c5158Smillert=head2 $IPC::Cmd::USE_IPC_RUN 2049b39c5158Smillert 2050b39c5158SmillertThis variable controls whether IPC::Cmd will try to use L<IPC::Run> 2051898184e3Ssthenwhen available and suitable. 2052b39c5158Smillert 2053b39c5158Smillert=head2 $IPC::Cmd::USE_IPC_OPEN3 2054b39c5158Smillert 2055b39c5158SmillertThis variable controls whether IPC::Cmd will try to use L<IPC::Open3> 2056b39c5158Smillertwhen available and suitable. Defaults to true. 2057b39c5158Smillert 2058b39c5158Smillert=head2 $IPC::Cmd::WARN 2059b39c5158Smillert 2060898184e3SsthenThis variable controls whether run-time warnings should be issued, like 2061b39c5158Smillertthe failure to load an C<IPC::*> module you explicitly requested. 2062b39c5158Smillert 2063b39c5158SmillertDefaults to true. Turn this off at your own risk. 2064b39c5158Smillert 2065898184e3Ssthen=head2 $IPC::Cmd::INSTANCES 2066898184e3Ssthen 2067898184e3SsthenThis variable controls whether C<can_run> will return all instances of 2068898184e3Ssthenthe binary it finds in the C<PATH> when called in a list context. 2069898184e3Ssthen 2070898184e3SsthenDefaults to false, set to true to enable the described behaviour. 2071898184e3Ssthen 2072898184e3Ssthen=head2 $IPC::Cmd::ALLOW_NULL_ARGS 2073898184e3Ssthen 2074898184e3SsthenThis variable controls whether C<run> will remove any empty/null arguments 2075898184e3Ssthenit finds in command arguments. 2076898184e3Ssthen 2077898184e3SsthenDefaults to false, so it will remove null arguments. Set to true to allow 2078898184e3Ssthenthem. 2079898184e3Ssthen 2080b39c5158Smillert=head1 Caveats 2081b39c5158Smillert 2082b39c5158Smillert=over 4 2083b39c5158Smillert 2084b39c5158Smillert=item Whitespace and IPC::Open3 / system() 2085b39c5158Smillert 2086b39c5158SmillertWhen using C<IPC::Open3> or C<system>, if you provide a string as the 2087b39c5158SmillertC<command> argument, it is assumed to be appropriately escaped. You can 2088b39c5158Smillertuse the C<QUOTE> constant to use as a portable quote character (see above). 2089898184e3SsthenHowever, if you provide an array reference, special rules apply: 2090b39c5158Smillert 2091898184e3SsthenIf your command contains B<special characters> (< > | &), it will 2092b39c5158Smillertbe internally stringified before executing the command, to avoid that these 2093b39c5158Smillertspecial characters are escaped and passed as arguments instead of retaining 2094b39c5158Smillerttheir special meaning. 2095b39c5158Smillert 2096b39c5158SmillertHowever, if the command contained arguments that contained whitespace, 209791f110e0Safresh1stringifying the command would lose the significance of the whitespace. 2098898184e3SsthenTherefore, C<IPC::Cmd> will quote any arguments containing whitespace in your 2099b39c5158Smillertcommand if the command is passed as an arrayref and contains special characters. 2100b39c5158Smillert 2101b39c5158Smillert=item Whitespace and IPC::Run 2102b39c5158Smillert 2103b39c5158SmillertWhen using C<IPC::Run>, if you provide a string as the C<command> argument, 2104b39c5158Smillertthe string will be split on whitespace to determine the individual elements 2105b39c5158Smillertof your command. Although this will usually just Do What You Mean, it may 2106b39c5158Smillertbreak if you have files or commands with whitespace in them. 2107b39c5158Smillert 2108b39c5158SmillertIf you do not wish this to happen, you should provide an array 2109b39c5158Smillertreference, where all parts of your command are already separated out. 2110898184e3SsthenNote however, if there are extra or spurious whitespaces in these parts, 2111b39c5158Smillertthe parser or underlying code may not interpret it correctly, and 2112b39c5158Smillertcause an error. 2113b39c5158Smillert 2114b39c5158SmillertExample: 2115b39c5158SmillertThe following code 2116b39c5158Smillert 2117b39c5158Smillert gzip -cdf foo.tar.gz | tar -xf - 2118b39c5158Smillert 2119b39c5158Smillertshould either be passed as 2120b39c5158Smillert 2121b39c5158Smillert "gzip -cdf foo.tar.gz | tar -xf -" 2122b39c5158Smillert 2123b39c5158Smillertor as 2124b39c5158Smillert 2125b39c5158Smillert ['gzip', '-cdf', 'foo.tar.gz', '|', 'tar', '-xf', '-'] 2126b39c5158Smillert 2127b39c5158SmillertBut take care not to pass it as, for example 2128b39c5158Smillert 2129b39c5158Smillert ['gzip -cdf foo.tar.gz', '|', 'tar -xf -'] 2130b39c5158Smillert 2131b39c5158SmillertSince this will lead to issues as described above. 2132b39c5158Smillert 2133b39c5158Smillert 2134b39c5158Smillert=item IO Redirect 2135b39c5158Smillert 2136b39c5158SmillertCurrently it is too complicated to parse your command for IO 2137898184e3Ssthenredirections. For capturing STDOUT or STDERR there is a work around 2138b39c5158Smillerthowever, since you can just inspect your buffers for the contents. 2139b39c5158Smillert 2140b39c5158Smillert=item Interleaving STDOUT/STDERR 2141b39c5158Smillert 2142b39c5158SmillertNeither IPC::Run nor IPC::Open3 can interleave STDOUT and STDERR. For short 2143898184e3Ssthenbursts of output from a program, e.g. this sample, 2144b39c5158Smillert 2145b39c5158Smillert for ( 1..4 ) { 2146b39c5158Smillert $_ % 2 ? print STDOUT $_ : print STDERR $_; 2147b39c5158Smillert } 2148b39c5158Smillert 2149b39c5158SmillertIPC::[Run|Open3] will first read all of STDOUT, then all of STDERR, meaning 2150898184e3Ssthenthe output looks like '13' on STDOUT and '24' on STDERR, instead of 2151b39c5158Smillert 2152898184e3Ssthen 1 2153898184e3Ssthen 2 2154898184e3Ssthen 3 2155898184e3Ssthen 4 2156b39c5158Smillert 2157b39c5158SmillertThis has been recorded in L<rt.cpan.org> as bug #37532: Unable to interleave 2158898184e3SsthenSTDOUT and STDERR. 2159b39c5158Smillert 2160b39c5158Smillert=back 2161b39c5158Smillert 2162b39c5158Smillert=head1 See Also 2163b39c5158Smillert 2164898184e3SsthenL<IPC::Run>, L<IPC::Open3> 2165b39c5158Smillert 2166b39c5158Smillert=head1 ACKNOWLEDGEMENTS 2167b39c5158Smillert 2168b39c5158SmillertThanks to James Mastros and Martijn van der Streek for their 2169898184e3Ssthenhelp in getting L<IPC::Open3> to behave nicely. 2170b39c5158Smillert 2171b39c5158SmillertThanks to Petya Kohts for the C<run_forked> code. 2172b39c5158Smillert 2173b39c5158Smillert=head1 BUG REPORTS 2174b39c5158Smillert 2175b39c5158SmillertPlease report bugs or other issues to E<lt>bug-ipc-cmd@rt.cpan.orgE<gt>. 2176b39c5158Smillert 2177b39c5158Smillert=head1 AUTHOR 2178b39c5158Smillert 2179898184e3SsthenOriginal author: Jos Boumans E<lt>kane@cpan.orgE<gt>. 2180898184e3SsthenCurrent maintainer: Chris Williams E<lt>bingos@cpan.orgE<gt>. 2181b39c5158Smillert 2182b39c5158Smillert=head1 COPYRIGHT 2183b39c5158Smillert 2184b39c5158SmillertThis library is free software; you may redistribute and/or modify it 2185b39c5158Smillertunder the same terms as Perl itself. 2186b39c5158Smillert 2187b39c5158Smillert=cut 2188