Quoth (e-mail address removed) (Mr. Zeus):
You seem not to be using strictures; are you using warnings?
Every (yes, *every*) program you write, certainly every program you
post here, should start with
use strict;
use warnings;
$TtH = "\"c:/programme/apache
group/apache2/cgi-bin/tth.exe\"";
You would be better off using single quotes here:
my $TtH = '"c:/programme/.../tth.exe"';
I take it you provide a different value for $mode in the real program?
@args = ($TtH, "-L -t -r -w0 $mode", "<tth_in.dat", ">tth_out.dat",
"2>tth_err.dat");
system(@args)== 0
or die "system @args failed: $?";
Here the result:
system "c:/programme/apache group/apache2/cgi-bin/tth.exe" -L -t -r
-w0 <tth_in.dat >tth_out.dat 2>tth_err.dat failed: 256 at
C:\Programme\Apache Group\Apache2\cgi-bin\wikitth.pl line 3252.
The code is essential to finding this problem: the problem is with how
you have called system.
system LIST does not use the command shell, it invokes the program
directly. Three consequences of this are
1. Stdio redirections (<, >, >>, | &c.) will not work: they are
performed by the shell.
2. Every argument must be provided as a separate item in the list. qw//
is often useful for this, I find, as is the idiom
my @args = (
-L =>
-r =>
-w => 0,
$mode
);
3. Arguments and commands with spaces in them do not need quoting. Perl
will provide the arguments given directly to execvp(2); under Unix and
other OSen with C-compatible argument passing conventions, this will
pass them straight into the program with no interpolation at all; under
Win32 the C RTL will (theoretically) deal with quoting each argument
such that the receiving program parses the command line correctly.
So, your system command was equivalent to typing
"\"c:/.../tth.exe\"" "-L -t -r -w0 " "<tth_in.dat" ">tth_out.dat" ...
into cmd.exe. Unsurprisingly, this didn't work. You have two options:
1. If you are using perl 5.8, you could try pretending you're on Unix
and doing a fork/exec pair, redirecting STD{IN,OUT,ERR} after the fork
and passing exec a list of (unquoted) arguments. This may, if you're
lucky, work... it will also be portable to Unixen, if you care about
that. This *should* keep the benefits of system/exec LIST, namely that
you don't need to worry about shell metachars in your arguments.
2. Use system STRING instead; in this case you want to keep $Tth as it
is but call system like
system "$Tth -L -t -r -w0 $mode <tth_in.dat >tth_out.dat ...";
i.e. with one string correctly quoted as you would type it into cmd.exe.
This string will be passed to cmd /c, which will then do the
redirections for you and will also require the quotes around the exe
name. This has the potential problem that if (say) $mode contains any
shell metachars (and what cmd.exe's metechars are is rather hard to say;
certainly "\%><|, possibly ^, perhaps others; the only thing you really
know is safe is /\w/) you will have to deal with quoting them in a way
cmd.exe finds acceptable yourself. You may also find you need to use
back- instead of forward-slashes for paths: cmd.exe is about the only
part of windows that cares which you use (which is why it's best to use
/ in general, as perl prefers it), but I really don't know if it works
to invoke an exe with a forward-slashed path.
Ben