Re: Handling weird return values with or die
by azatoth (Curate) on Jul 05, 2001 at 16:29 UTC
|
| [reply] |
|
Thanks; your solution worked great! I hadn't been familiar with $? until now.
| [reply] [d/l] |
Re: Handling weird return values with or die
by jeroenes (Priest) on Jul 05, 2001 at 16:31 UTC
|
But with system that is different. See the doc. Check for
a number of -1 to die on start failure:
system("blah foo beer!") <> -1 or die "error: $?";
To die on the exit call, maybe you'd better use some
elaborate sceme:
system( @args ) == 0 or syscall_error( $?, "system @args" );
sub syscall_error(
my $error = shift;
my $name = shift;
die "$name failed: $!" if $error == -1;
die "$name returned error: ", $error >> 8,
", signal: ", $error & 127,
" and dumped_core: ", $error & 128;
}
The last sub pulled from the literal info in system.
Hope this helps, Jeroen
"We are not alone"(FZ) Updated | [reply] [d/l] [select] |
Re: Handling weird return values with or die
by japhy (Canon) on Jul 05, 2001 at 16:37 UTC
|
The problem is not with or. The problem is with system(). Unlike functions like open(), unlink(), and chmod(), this does not return a true value on success -- rather, it turns 0 (the shell's version of true) on success, and non-zero on failure. This is documented.
Many people write system(...) == 0 or die to get around this. You can use my Perl 6 module for "fixing" the senses of true and false, found at japhygesis. I'll probably put it on CPAN soon.
japhy --
Perl and Regex Hacker | [reply] |
Re: Handling weird return values with or die
by Zaxo (Archbishop) on Jul 05, 2001 at 16:36 UTC
|
Perl functions generally return true on success, but system() returns the system exit status, which is inverted. Your workaround is correct. Another clean but unintuitive way is:
system("zip -rq $target $project_root") and die "couldn't exec zip: $!";
After Compline, Zaxo
| [reply] [d/l] [select] |
Re: Handling weird return values with or die
by mvaline (Friar) on Jul 05, 2001 at 16:48 UTC
|
I obviously didn't read the entry for system in the Camel Book well enough, its code sample is:
@args = ("command", "arg1", "arg2");
system(@args) == 0
or die "system @args failed: $?"
Thanks, though... I've got it working now.
Just out of curiosity, is there some interesting piece of lore that explains why perl functions and shell functions have opposing standards for return values? The return values for other perl functions such as open, unlink, etc. as cited above seem to be the more intuitive, but I guess confusion only comes from having multiple standards. | [reply] [d/l] |
|
Perl functions as it does to be a good fit to intuition and natural language.</p?
A shell process's return value is the only way (aside from whatever it may have written to stderr) that status can be checked. Since there are many interesting ways for a process to fail, the ability to return different error codes is useful. Hence 0 == success, 0 != error_code.
It takes some getting used to.
After Compline, Zaxo
| [reply] |
|
I see; since boolean true would refer to any value above 0 and false only refers to to 0, and the fact that multiple error codes are much more useful than multiple success codes :-), zero has to be the success code. Thanks!
| [reply] |
|
It is not a matter of opposing standards. There are two
different things. First, there are the function calls,
whose behaviour is strictly defined (or else they would
be unusuable). At the C level, failure is often indicated
by a return value of -1, or NULL,
and the reason of failure is passed in a global variable,
errno. Not very intuitive (IMO), and Perl,
being the thin layer it is above Unix/C, only makes it
slightly more convenient. It returns 0 on
failure. The reason of failure is still passed in a global
variable, $! (which explains that variable).
The return values of spawned process have nothing to do with
the shell. It's the other way around. Processes typically
return 0 indicating success, and anything else
for failure. There's no global variable to set, all they can
do is return a single integer. "0 on success"
is a mere convention. It's just because this
convention is followed so often, typical shell Boolean logic
is "reversed"; 0 is true, other integers are
false.
-- Abigail
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
I'd say the truthness values come from C.
As C language does not have a bool type, thruthness is
expressed with anything different from 0, and 0 is false.
The shell, (and certainly most programs in most OS's) return 0 when everything went OK, and an error code when not...
Notice there'll be a my $rc = 0 is true;, which
basically says the result of your sub is a 'zero' and that
it's true (not an error, for example...). Only available
in Perl6 properties (I wish it arrives soon :-)
laters, david
sub foo { return join '~', @_ }
| [reply] |
Re: Handling weird return values with or die
by bikeNomad (Priest) on Jul 05, 2001 at 20:00 UTC
|
use Archive::Zip;
use Archive::Zip::Tree;
use File::Temp;
use File::Basename;
my $zip = Archive::Zip->new();
$zip->read($target) and die "can't read $target\n"
if -f $target;
$zip->addTree($project_root, $project_root);
if (-f $target) # existing file?
{
my ($tmpfh, $tmpname) = File::Temp::tempfile( DIR => dirname($target
+));
$zip->writeToFileHandle( $tmpfh ) and die "Can't write to $tmpname\n
+";
$tmpfh->close();
unlink($target) or die "can't remove $target: $!\n";
rename($tmpname, $target) or die "can't rename $target: $!\n";
}
else
{
$zip->writeToFileNamed($target) and die "can't write to $target\n"
+;
}
Hmm... maybe I should add the write back to same file ability to Archive::Zip. | [reply] [d/l] |
|
| [reply] |
Re: Handling weird return values with or die
by Abigail (Deacon) on Jul 05, 2001 at 19:46 UTC
|
As you are saying, normally executing programs return
0
to signify a normal exit. The Perl expression
EXPR1 or EXPR2 evaluates EXPR2
only if EXPR1 is false. 0 is
false....
So, what you see happening is exactly what should be happening.
I guess you are using or die on system *calls*
(like open or unlink), but
system is not a system call.
-- Abigail | [reply] [d/l] [select] |
Re: Handling weird return values with or die
by sierrathedog04 (Hermit) on Jul 06, 2001 at 00:10 UTC
|
not system("zip -rq $target $project_root") or die "couldn't exec zip: $!";
reduces to die "couldn't exec zip: $!" if system ("zip -rq $target $project_root");
Might as well reduce the two keywords "not" and "or" to just one "if".
| [reply] [d/l] [select] |
|
Except that breaks the principle of "put the most important thing first." if(system("whatever")) { die "whatever else" } doesn't, however...
=cut
--Brent Dax
@HPAJ=split("", "rekcaH lreP rentonA tsuJ");
print reverse @HPAJ; #sucky but who cares?
| [reply] [d/l] [select] |