Like Andrzej, I'd say avoid using the shell. But there's a simpler way to accomplish that:
open(FH, "|-", "mailx", "-s", $subject, $to) or die "Can't mailx: $!";
print FH $message;
close(FH);
If you give the command and its arguments to open with the "|-" mode, open
and close
will handle the exec
ing and waitpid
ing for you.
From perldoc -f open
:
The following blocks are more or less equivalent:
open(FOO, "|tr '[a-z]' '[A-Z]'");
open(FOO, "|-", "tr '[a-z]' '[A-Z]'");
open(FOO, "|-") || exec 'tr', '[a-z]', '[A-Z]';
open(FOO, "|-", "tr", '[a-z]', '[A-Z]');
open(FOO, "cat -n '$file'|");
open(FOO, "-|", "cat -n '$file'");
open(FOO, "-|") || exec "cat", "-n", $file;
open(FOO, "-|", "cat", "-n", $file);
The last two examples in each block show the pipe as "list form",
which is not yet supported on all platforms. A good rule of thumb
is that if your platform has a real "fork()" (in other words, if
your platform is Unix, including Linux and MacOS X), you can use
the list form. You would want to use the list form of the pipe so
you can pass literal arguments to the command without risk of the
shell interpreting any shell metacharacters in them. However, this
also bars you from opening pipes to commands that intentionally
contain shell metacharacters, such as:
open(FOO, "|cat -n | expand -4 | lpr")
// die "Can't open pipeline to lpr: $!";
See "Safe Pipe Opens" in perlipc for more examples of this.
...
Closing any piped filehandle causes the parent process to wait for
the child to finish, then returns the status value in $? and
"${^CHILD_ERROR_NATIVE}".