On Wed Nov 06 11:36:29 2019, Chris.Denley@experian.com wrote:
Show quoted text> I didn't even try quote_cmd as the documentation says it "quotes as a
> string" rather than "quotes as a list" like quote_system_string, and I
> need to pass it a list of arguments. But it does seem to take a list
> and work exactly as needed, resolving my issue. I assume passing
> "2>&1" in that list would result in that string being quoted and
> passed as an argument, which is why I was appending to the result.
All of the functions take lists of arguments to be quoted, but some of them return lists as well. quote_system_string and quote_cmd both take lists and return a single string.
If you have suggestions on how the documentation could be improved, they would be welcome.
Show quoted text>
> I initially wanted to use IPC::Run to capture the output from commands
> passed as a list, but it is not thread-safe on Windows. Otherwise it
> would've been perfect. Perhaps you're thinking of Win32::Process or
> something? Cross-platform would be ideal, but obviously in using
> Win32::ShellQuote we already have the quoting of arguments handled
> conditionally based on OS. I'm trying to keep that to a minimum
> though.
>
> -----Original Message-----
> From: Graham Knop via RT <bug-Win32-ShellQuote@rt.cpan.org>
> Sent: Tuesday, November 5, 2019 4:41 PM
> To: Denley, Chris <Chris.Denley@experian.com>
> Subject: [rt.cpan.org #130905] ^ quote_system_string 2>&1
>
> <URL:
https://rt.cpan.org/Ticket/Display.html?id=130905 >
>
> On Tue Nov 05 14:18:39 2019, Chris.Denley@experian.com wrote:
> > Not sure if this is actually a bug in this module, a bug in Windows,
> > or maybe just some known limitation. As a test for my own
> > application,
> > I was passing random strings as arguments to verify they were escaped
> > properly when passed as arguments. I found some strings which would
> > have ^ dropped from it, but only if the command pipes STDERR to
> > STDOUT. "quote_system_string" seems to be the correct subroutine to
> > use for quoting arguments to be used with backticks, and backticks
> > seems to be the only thread-safe way of capturing output on Windows.
> >
> > Strawberry Perl 5.24.1.1
> > Windows Server 2008 R2 Enterprise SP1 (64-bit)
> >
> > Strawberry Perl 5.30.0.1
> > Windows 10 Enterprise (1709, 64-bit)
> >
> > use strict;
> > use Win32::ShellQuote 'quote_system_string';
> >
> > if(@ARGV) {
> > my $arg = pop(@ARGV);
> > binmode(STDOUT);
> > print $arg;
> > exit(0);
> > }
> >
> > my @args = ('^','^foo|^bar','foo"!^d bar','xeX]m"!^d 7MV"G{WV|X');
> > foreach my $arg(@args) {
> > my @cmdarr = ($^X,$0,$arg);
> > my $cmd = quote_system_string(@cmdarr);
> > foreach my $acmd($cmd,"$cmd 2>&1") {
> > print "\n$acmd\n$arg\n";
> > my $output = `$acmd`;
> > if($output eq $arg) {
> > print "$output: argument preserved\n";
> > }
> > else {
> > print "$output: argument mismatch\n";
> > }
> > }
> > }
>
> I don't have a Windows machine easily available to test on at the
> moment, but I'm fairly certain this is just a documentation issue.
>
> Backticks or system use heuristics to decide if the command used
> should be run directly or using cmd.exe. quote_system_string
> reimplements these heuristics, and quotes accordingly. But this only
> works if its output is passed directly to system or the backticks.
> '2>&1' is a shell construct, so adding it forces the command to be run
> using cmd.exe. quote_system_string doesn't know about this, so it
> can't make the correct decision on how to quote its output. The
> correct function to use in this case is quote_cmd, since you are
> forcing cmd.exe to be used.
>
> Backticks are not the only thread safe way to run other programs on
> Win32.
IPC::Open3 should be viable.
my $pid = open3 *STDIN, my $fh, undef, quote_system_list('program', @args);
my $output = do { local $/; <$fh> };
close $fh;