On Saturday, Mar 29, 2003, at 03:23 Asia/Tokyo, Rich Morin wrote:
Let's say that I want to use a command (e.g., md5) on a file.  No
problem; just use:

system("md5 $file");

Except that the file name could contain all manner of white space
characters, shell wildcard characters, etc.  Is there a module that
deals with this sort of thing (e.g., wrapping each argument in the
appropriate kinds of quoting)?

This is definitely one of the areas where TMTOWTDI blesses you and curses you the most. There are just too many ways to do this kind of things to come up with idioms. But there are rules of thumb;


* Let perl or module do it

Instead of system("md5"...) (Well, I think it is more like open MD5, "md5 ... |" if you want to reuse the result in perl), you can use Digest::MD5. Perl itself is versatile enough to do away with the need of such commands as grep, sed, and awk. And with so many modules that does shell commands, it is usually much easier to find the module and use it than resort to system() or open().

* When you have to, use taint mode and untaint with care

There are still some cases where external commands are (better| the only choice). But just because you decided to use them don't blindly system() or open(). Use taint mode. With taint mode on (via -T switch), system("md5 $file") simply dies if $file is set by external data. You have to untaint it to use it. i.e.

my $file = shift; # tainted
$file =~ m/([\w\.\-\+]+)/o; # $1 is not tainted
system("md5", $1); # okay;

See "perldoc perlsec" for details.

* when you system(), do not let shell stand in a way

system("md5 $file") and system("md5", $file) looks the same but they are treated completely differently by camel, The first one is fed to the shell (/bin/sh for most cases) but the second one is directly invoked by perl so wild cards are not expanded, resulting much safer codes. Not only is it safer but also faster. So when you want to do the following,

my $cmd = "command arg1 arg2";

Do

my (@cmd) = split /\s+/ => $cmd;
system(@cmd);

instead of "system($cmd)".

Of course there are still in need of shell, such as cases like below when you have to use redirections therein.

$cmd = "command arg1 > out.txt 2> error.txt";

But these cases are much rarer and can usually cope with different techniques. See
"perldoc perlfaq" and "Perl Cookbook".


Dan the Man with Too Many Ways to Do It



Reply via email to