4.3. open() for Command Execution
The open
command can be used for command execution. By prefixing the filename with a pipe (|
), the rest of it is interpreted as a command invocation, which accepts standard input by printing to the filehandle, and is executed after the filehandle is closed. If the last character is a pipe, then the command is executed and its standard output is fed into the filehandle where it can be read using Perl's file input mechanisms.
Here are some examples:
#!/usr/bin/env perl use strict; use warnings; open my $in, "/sbin/ifconfig |"; my (@addrs); while (my $line = <$in>) { if ($line =~ /inet addr:((\d+\.)+\d)/) { push @addrs, $1; } } close($in); print "You have the following addresses: \n", join("\n",@addrs), "\n";
#!/usr/bin/env perl use strict; use warnings; # Send an E-mail to myself # Note: this is just an example - there are modules to do this on CPAN. open MAIL, "|/usr/sbin/sendmail shlomif\@shlomifish.org"; print MAIL "To: Shlomi Fish <shlomif\@shlomifish.org>\n"; print MAIL "From: Shlomi Fish <shlomif\@shlomifish.org>\n"; print MAIL "\n"; print MAIL "Hello there, moi!\n"; close(MAIL);
Pipe to @args
Recent versions of Perl also have a syntax that allows opening a process for input or output using its command line arguments. These are:
open my $print_to_process, "|-", $cmd, @args; print {$print_to_process} ...;
and:
open my $read_from_process, "-|", $cmd, @args; while (my $line = <$read_from_process>) { . . . }
Doing something like open my $print_to_process, "|-", "sendmail", $to_address;
is safer than doing: open my $print_to_process, "|-", "sendmail $to_address";
Because a malicious person may put some offending shell characters in $to_address
and end up with something like:
sendmail ; rm -fr $HOME