Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a quoted string to system() keeping quotes intact

Tags:

quotes

perl

exec

This problem applies to Perl v5.24.0 on Windows 10

Except for the simplest cases. It is always a problem passing command lines and parameter lists between programs. Taking into account the effects of whitespace and shell metacharacters, possibly so that the data remains intact over several levels of calls, can involve a mess of escapes and quotation marks

The panacea has always been to use the multiple-parameter form of system (which also tries to avoid calling the shell as an intermediary) so that each parameter is reliably separated without resorting to quotes

A call like this

system("dir \"C:\\Program Files\\\"")

is much easier on the eye written like this

system('dir', 'C:\Program Files\\')

However, I can see no way to pass values that include enclosing quotes

If I write a test program

show.pl

use Data::Dump;
dd \@ARGV;

and then call

system('show', 'xxx')

then the output I get is what I expect

["xxx"]

However, suppose I want to pass the string "xxx". If I try

system('show', '"xxx"')

then the quotes are stripped at some point along the way and the output is identical to the preceding example

How do I make a call to system such that the output is ["\"xxx\""]?

I have tried all manner of escaping, but the solution evades me

like image 904
Borodin Avatar asked Jul 06 '16 10:07

Borodin


1 Answers

The problem:

system($^X, '-E', 'say @ARGV', '"test"');

Output:

test

That's so broken![1]


Solution:

use Win32::ShellQuote qw( quote_system );

system(quote_system($^X, '-E', 'say @ARGV', '"test"'));

Output:

"test"

  1. Perl needs to build a command line even if the shell isn't used. Unlike unix where the system call to execute a program takes the path to a program and a list of arguments, the Windows system call to execute a program takes a command line, so a command line must be built even if the shell is avoided. It appears that Perl builds the command lines incorrectly.[2] This is why using the system BLOCK LIST syntax doesn't help.

  2. In fact, it's up to the application to parse the command line for arguments! Thankfully, there's a system call to do that, so a standard has formed.

like image 199
ikegami Avatar answered Nov 15 '22 19:11

ikegami