From e8c58a72c8b3d5bd62139eae49782e93ad513faf Mon Sep 17 00:00:00 2001 From: Vaclav Zeman Date: Thu, 6 Feb 2014 13:25:11 +0100 Subject: [PATCH 1/4] Fix Windows arguments passing. --- lib/IPC/System/Simple.pm | 46 +++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/IPC/System/Simple.pm b/lib/IPC/System/Simple.pm index 4d813be..92a1ddb 100644 --- a/lib/IPC/System/Simple.pm +++ b/lib/IPC/System/Simple.pm @@ -79,7 +79,7 @@ use constant UNDEFINED_POSIX_RE => qr{not (?:defined|a valid) POSIX macro|not im require Exporter; our @ISA = qw(Exporter); -our @EXPORT_OK = qw( +our @EXPORT_OK = qw( capture capturex run runx system systemx @@ -188,7 +188,7 @@ sub runx { if (WINDOWS) { our $EXITVAL = -1; - my $pid = _spawn_or_die($command, "$command @args"); + my $pid = _spawn_or_die($command, $command, @args); $pid->Wait(INFINITE); # Wait for process exit. $pid->GetExitCode($EXITVAL); @@ -232,7 +232,7 @@ sub capture { my @results = qx($command); _process_child_error($?,$command,$valid_returns); return @results; - } + } my $results = qx($command); _process_child_error($?,$command,$valid_returns); @@ -267,7 +267,7 @@ sub _win32_capture { open(my $saved_stdout, '>&', \*STDOUT) ## no critic or croak sprintf(FAIL_PLUMBING, "Can't dup STDOUT", $!); - # We now open up a pipe that will allow us to + # We now open up a pipe that will allow us to # communicate with the new process. pipe(my ($read_fh, $write_fh)) @@ -302,8 +302,8 @@ sub _win32_capture { # filehandles. my $err; - my $pid = eval { - _spawn_or_die($exe, qq{"$command" @args}); + my $pid = eval { + _spawn_or_die($exe, $command, @args); } or do { $err = $@; @@ -433,7 +433,7 @@ sub capturex { my $results = join("",<$pipe>); close($pipe); _process_child_error($?,$command,$valid_returns); - + return $results; } @@ -452,11 +452,23 @@ sub _spawn_or_die { if (not WINDOWS) { croak sprintf(FAIL_INTERNAL, "_spawn_or_die called when not under Win32"); } else { - my ($orig_exe, $cmdline) = @_; + my ($orig_exe, @args) = @_; my $pid; + # Quote the executable name/path. my $exe = $orig_exe; + # Prepare command line. + foreach my $arg (@args) + { + # Escape double quotation marks. Backslashes appear to be + # handled by the Win32::Process::Create() function. + $arg =~ s/(")/\\$1/g; + # Wrap each argument with double quotation marks. + $arg = '"' . $arg . '"'; + } + my $cmdline = join " ", @args; + # If our command doesn't have an extension, add one. $exe .= $Config{_exe} if ($exe !~ m{\.}); @@ -514,7 +526,7 @@ sub _check_taint { sub _process_child_error { my ($child_error, $command, $valid_returns) = @_; - + $EXITVAL = -1; my $coredump = WCOREDUMP($child_error); @@ -544,7 +556,7 @@ sub _process_child_error { croak sprintf FAIL_SIGNAL, $command, $signal_name, $signal_no, ($coredump ? " and dumped core" : ""); - } + } croak sprintf(FAIL_INTERNAL, qq{'$command' ran without exit value or signal}); @@ -565,7 +577,7 @@ sub _check_exit { if (not defined first { $_ == $exitval } @$valid_returns) { croak sprintf FAIL_BADEXIT, $command, $exitval; - } + } return $exitval; } @@ -633,13 +645,13 @@ IPC::System::Simple - Run commands simply, with detailed diagnostics =head1 DESCRIPTION -Calling Perl's in-built C function is easy, +Calling Perl's in-built C function is easy, determining if it was successful is I. Let's face it, C<$?> isn't the nicest variable in the world to play with, and even if you I check it, producing a well-formatted error string takes a lot of work. -C takes the hard work out of calling +C takes the hard work out of calling external commands. In fact, if you want to be really lazy, you can just write: @@ -696,14 +708,14 @@ or process diagnostics, then read on! # Capture output into $result and throw exception on failure - my $result = capture("some_command"); + my $result = capture("some_command"); # Check exit value from captured command print "some_command exited with status $EXITVAL\n"; # Captures into @lines, splitting on $/ - my @lines = capture("some_command"); + my @lines = capture("some_command"); # Run a command which must return 0..5, capture the output into # @lines, and avoid the shell. @@ -992,7 +1004,7 @@ hard work for you. If an odd exit status is provided, you're informed of what it is. If a signal kills your process, you are informed of both its name and number. If tainted data or environment prevents your command from -running, you are informed of exactly which datais +running, you are informed of exactly which datais =item Exceptions on failure @@ -1039,7 +1051,7 @@ Signals are not supported under Win32 systems, since they don't work at all like Unix signals. Win32 singals cause commands to exit with a given exit value, which this modules I capture. -Only 8-bit values are returned when C or C +Only 8-bit values are returned when C or C is called with a single value under Win32. Multi-argument calls to C and C, as well as the C and C always return the 32-bit Windows return values. From e698b0a4e6063d27647d9f77faed6cd4f5d9592c Mon Sep 17 00:00:00 2001 From: Vaclav Zeman Date: Thu, 6 Feb 2014 13:50:13 +0100 Subject: [PATCH 2/4] Escape backslashes as well. --- lib/IPC/System/Simple.pm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/IPC/System/Simple.pm b/lib/IPC/System/Simple.pm index 92a1ddb..32e5b77 100644 --- a/lib/IPC/System/Simple.pm +++ b/lib/IPC/System/Simple.pm @@ -461,9 +461,8 @@ sub _spawn_or_die { # Prepare command line. foreach my $arg (@args) { - # Escape double quotation marks. Backslashes appear to be - # handled by the Win32::Process::Create() function. - $arg =~ s/(")/\\$1/g; + # Escape double quotation marks and backslashes. + $arg =~ s/([\\"])/\\$1/g; # Wrap each argument with double quotation marks. $arg = '"' . $arg . '"'; } From aaddcb74ff3178bff5027d9f06a5fea72837dcaa Mon Sep 17 00:00:00 2001 From: Vaclav Zeman Date: Thu, 6 Feb 2014 13:57:06 +0100 Subject: [PATCH 3/4] Remove bad comment. --- lib/IPC/System/Simple.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/IPC/System/Simple.pm b/lib/IPC/System/Simple.pm index 32e5b77..88fe2a6 100644 --- a/lib/IPC/System/Simple.pm +++ b/lib/IPC/System/Simple.pm @@ -455,7 +455,6 @@ sub _spawn_or_die { my ($orig_exe, @args) = @_; my $pid; - # Quote the executable name/path. my $exe = $orig_exe; # Prepare command line. From c86480d73d57acc8bb6ba4ff78a700366293108d Mon Sep 17 00:00:00 2001 From: Vaclav Zeman Date: Thu, 6 Feb 2014 15:28:18 +0100 Subject: [PATCH 4/4] Fix quoting of backslashes and double quotes. --- lib/IPC/System/Simple.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/IPC/System/Simple.pm b/lib/IPC/System/Simple.pm index 88fe2a6..87ae23c 100644 --- a/lib/IPC/System/Simple.pm +++ b/lib/IPC/System/Simple.pm @@ -461,7 +461,7 @@ sub _spawn_or_die { foreach my $arg (@args) { # Escape double quotation marks and backslashes. - $arg =~ s/([\\"])/\\$1/g; + $arg =~ s,(\\*)",$1$1\\",g; # Wrap each argument with double quotation marks. $arg = '"' . $arg . '"'; }