``, system, eval and exec all do different things, so it's useless to compare their performance.
- Do you want the caller to wait for script.cgi to finish and resume execution after script.cgi is done? (yes: ``, exec)
- Do you want the caller to resume execution immediately after script.cgi is launched, letting it run in parallel? (yes: fork+exec)
- Do you want to capture the script.cgi's output? If you don't, it will go to STDOUT. (yes: `` and fork+exec+pipes)
Don't use eval. You'd have to change script.cgi to play nice, but it's easier and better to write script.cgi as a proper module instead.
| [reply] |
If the plan is to use the output of another script as data in the current (CGI) script (e.g. as content to be included on a web page), the three possible ways to do that are:
# one way:
my $content = `other_script`;
die "No output from other_script" unless ( $content );
# another way:
open( SCR, "other_script |" ) or die "other_script failed: $!";
print while (<SCR>);
close SCR;
# the only other way:
my $tmpfile = function_returning_uniq_name();
my $status = system( "other_script > $tmpfile" );
die "other_script failed" if ( $status or -s $tmpfile == 0 );
open( TMP, $tmpfile ) or die "WTF?? can't open $tmpfile: $!";
print <TMP>;
close TMP:
unlink $tmpfile;
In terms of security, I think the three methods are equivalent (I hope others will correct me if I'm wrong):
If the name of "other_script" and any command line args that are needed are constants that you define in the source code (not derived from input CGI parameters), then there isn't much to worry about.
If the command line needs to be constructed on the basis of CGI params, then you need to be very careful about how you do this, no matter which method you use. Ideally, CGI params would only be used (via regex matches or value comparisons) to decide which script-internal, pre-defined constants -- or which server-internal, verifiable file/directory names -- should be included in the command line. If the app is supposed to allow CGI param strings to be included on the command line, apply the tightest possible untainting.
Regarding the 2nd, 3rd and 4th "alternatives" suggested in the OP, they won't work at all:
- The system call returns the exit status of the command line, not the stdout content.
- eval("script.cgi") returns the string "script.cgi"
- exec("script.cgi") does not return to the calling script -- the named command takes the place of the calling routine in the system's process table.
BTW, based on your proposed examples, you may need to take note: running a sub-process in a CGI script does not mean that the sub-process is "automatically" a CGI script itself -- it does not get the parameter values that the calling CGI script received, unless these are somehow (carefully) included in the command line or %ENV. You can run any command, more or less the way you would from an interactive shell on the server -- that's why you have to be careful. | [reply] [d/l] [select] |
This is exactly what i was looking for. Thank you very much =)
| [reply] |
perldoc -f system
system LIST
system PROGRAM LIST
Does exactly the same thing as "exec LIST", except that
+ a fork
is done first, and the parent process waits for the chi
+ld pro-
cess to complete. Note that argument processing varies
+ depend-
ing on the number of arguments. If there is more than
+one
argument in LIST, or if LIST is an array with more than
+ one
value, starts the program given by the first element of
+ the
list with arguments given by the rest of the list. If
+there is
only one scalar argument, the argument is checked for s
+hell
metacharacters, and if there are any, the entire argume
+nt is
passed to the system’s command shell for parsing (this
+is
"/bin/sh -c" on Unix platforms, but varies on other pla
+tforms).
If there are no shell metacharacters in the argument, i
+t is
split into words and passed directly to "execvp", which
+ is more
efficient.
Beginning with v5.6.0, Perl will attempt to flush all f
+iles
opened for output before any operation that may do a fo
+rk, but
this may not be supported on some platforms (see perlpo
+rt). To
be safe, you may need to set $│ ($AUTOFLUSH in En
+glish) or call
the "autoflush()" method of "IO::Handle" on any open ha
+ndles.
The return value is the exit status of the program as r
+eturned
by the "wait" call. To get the actual exit value shift
+ right
by eight (see below). See also "exec". This is not wh
+at you
want to use to capture the output from a command, for t
+hat you
should use merely backticks or "qx//", as described in
"‘STRING‘" in perlop. Return value of -1 indicates a f
+ailure
to start the program (inspect $! for the reason).
Like "exec", "system" allows you to lie to a program ab
+out its
name if you use the "system PROGRAM LIST" syntax. Agai
+n, see
"exec".
Because "system" and backticks block "SIGINT" and "SIGQ
+UIT",
killing the program they’re running doesn’t actually in
+terrupt
your program.
@args = ("command", "arg1", "arg2");
system(@args) == 0
or die "system @args failed: $?"
You can check all the failure possibilities by inspecti
+ng $?
like this:
$exit_value = $? >> 8;
$signal_num = $? & 127;
$dumped_core = $? & 128;
or more portably by using the W*() calls of the POSIX e
+xten-
sion; see perlport for more information.
When the arguments get executed via the system shell, r
+esults
and return codes will be subject to its quirks and capa
+bilities. See "‘STRING‘" in perlop and "exec" for details.
| [reply] [d/l] [select] |