But if you wanted to send an e-mail with "; touch /root/evilfile" as a subject, you will end up creating a file instead. Also, arguments containing spaces simply break, because, given @ARGV=("login@host", "-s", "some topic") you run /bin/mail login@host -s some topic - without quotes or (preferrably) stating array of command line arguments (multi-argument form of open/system/exec).
Examples of bad behaviour which can be solved using open(my $ch, "|-", "/bin/mail", @ARGV):
$ cat if-mail.pl
#!/usr/bin/perl
exit 0 unless (my @lines = <STDIN>);
open(my $mail, "|-", join " ", "/usr/bin/mail", @ARGV) or die $!;
print $mail @lines;
$ LC_ALL=C ./if-mail.pl root@localhost -s "do not run echo; touch ~/zz
+z && ls ~/zzz - it does not make sense"
TEST
^D
ls: cannot access -: No such file or directory
ls: cannot access it: No such file or directory
ls: cannot access does: No such file or directory
ls: cannot access not: No such file or directory
ls: cannot access make: No such file or directory
ls: cannot access sense: No such file or directory
/home/aitap/zzz
$ ./if-mail.pl root@localhost -s "try running echo *"
TEST
^D
Trying to read the mail, I get:
$ mail
From: Krylov Ivan <aitap@tarkus>
To: echo@tarkus, not@tarkus, root@localhost, run@tarkus
Subject: do
Message-ID: <E1VnDEf-0008HF-UG@Tarkus>
Date: Пнд, 02 Дек 2013 00:0
+3:21 +0400
----------------------------------------------------------------
TEST
----------------------------------------------------------------
From: Mail Delivery System <Mailer-Daemon@tarkus>
To: aitap@tarkus
Subject: Mail delivery failed: returning message to sender
Message-ID: <E1VnDEg-0008HS-5L@Tarkus>
Date: Пнд, 02 Дек 2013 00:0
+3:22 +0400
----------------------------------------------------------------
This message was created automatically by mail delivery software.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) faile
+d:
echo@tarkus
Unrouteable address
not@tarkus
Unrouteable address
run@tarkus
Unrouteable address
------ This is a copy of the message, including all the headers. -----
+-
<...>
From: Krylov Ivan <aitap@tarkus>
To: echo@tarkus, if-mail.pl@tarkus, root@localhost, running@t
+arkus
Subject: try
Message-ID: <E1VnDFD-0008Is-Co@Tarkus>
Date: Пнд, 02 Дек 2013 00:0
+3:55 +0400
----------------------------------------------------------------
TEST
----------------------------------------------------------------
From: Mail Delivery System <Mailer-Daemon@tarkus>
To: aitap@tarkus
Subject: Mail delivery failed: returning message to sender
Message-ID: <E1VnDFD-0008Iy-K2@Tarkus>
Date: Пнд, 02 Дек 2013 00:0
+3:55 +0400
----------------------------------------------------------------
This message was created automatically by mail delivery software.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) faile
+d:
echo@tarkus
Unrouteable address
if-mail.pl@tarkus
Unrouteable address
running@tarkus
Unrouteable address
------ This is a copy of the message, including all the headers. -----
+-
<...>
(notice if-mail.pl@tarkus in the list of addressees: it's from the expansion of "*" from the subject)
Also, I think in your proposal the data on STDIN would be lost, but I have not tested it either.
I was thinking about the simpliest way of passing the STDIN by just jeaving it to the process being executed, but yes, using eof on STDIN before the exec does indeed lose the first line of input (even on pipes). I have not figured a way around this, neither $|++ nor setbuf helped.
| [reply] [d/l] [select] |