Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

understanding eval in HPOJ

by GhodMode (Pilgrim)
on Apr 04, 2004 at 18:12 UTC ( #342498=perlquestion: print w/replies, xml ) Need Help??

GhodMode has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to understand the following snippet of code, which doesn't seem to be working for me.
eval '(exit $?0)' && eval 'exec env LANG=C $0 ${1+"$@"}' if $ENV{"LANG"} != "C";
What's happening in each eval? Here's what it looks like to me. Please correct me...
  1. It's just sticking a 0 on the end of the end of the exit status for the last child process and exiting. But there is no last child process.
  2. Set LANG=C then execute the current script again with an argument that is somehow made from a 1 and the code for the syntax error from the first eval
I'm very confused. This is a work-around for a bug with HP OfficeJet printer support on RedHat Linux. Since it's not working I was thinking of using this adaptation from another thread which helped me solve another, unrelated problem...
BEGIN { unless ( $ENV{LANG} eq "C" ) { $ENV{LANG} = "C"; exec 'env',$0,@ARGV; } }
I will be posting a question of this nature in their mailing list, too. But the Monks are much better :) Thank you,
-- GhodMode

Replies are listed 'Best First'.
Re: understanding eval in HPOJ
by broquaint (Abbot) on Apr 04, 2004 at 21:37 UTC
    What odd code - the first eval will always produce an error e.g
    $ perl -le 'eval q[exit $?0]; print $@' Number found where operator expected at (eval 1) line 1, near "$?0" (Missing operator before 0?) syntax error at (eval 1) line 1, near "$?0"
    So the second eval will never get used, and even if it did, that would also bail out (although, rather frighteningly, it's valid perl code; indirect object syntax is to blame :/) e.g
    $ perl -le 'eval q[exec env LANG=C $0 ${1+"$@"}]; print $@;' Can't call method "C" without a package or object reference at (eval 1 +) line 1.
    From here it looks like some seriously fruity mix of shell and perl that can never work. However your second concotion looks far more likely to succeed.


    update: tidied up second code example and added side note that it actually compiles (ick)

Re: understanding eval in HPOJ
by hossman (Prior) on Apr 04, 2004 at 20:23 UTC

    letting us know where you found that snippet (ie: URL) would be helpful

    (It really does look like bash to me too)

      The code is from the file hpoj (no extension), which is installed as part of the hpoj-0.90-14 RPM for RedHat Linux 9. It's 1339 lines long, but here are lines one through six: unchanged...

      #!/usr/bin/perl # LANG=C is a work around for bug 82652. # The easier work-around of setting LANG=C in perl script itself didn' +t # work. It's probably too late by then. eval '(exit $?0)' && eval 'exec env LANG=C $0 ${1+"$@"}' if $ENV{"LANG"} != "C";

      Really?! No one is familiar with exec and eval?

      eval "evaluates" perl code or an expression and exec terminates the currently running Perl script and executes it's arguments in the current shell, ie: without creating a new process ID.

      There is no eval command in Bash, but the exec command does work in a similar fashion, executing it's arguments without creating a new process.

      I think both execs are actually based on a similar function in the standard programming library for Unix-like operating systems.

      -- GhodMode

        First of all, it's not an issue of being familiar with eval or exec .. I know what those do, it's the some of the crazy syntax/variables it's trying to use in ways that make no sense.

        Second, bash most certainly has an "eval" see the "SHELL BUILTIN COMMANDS" section of "man bash"

        Third, reading RedHat bug#82652 indicates a couple of important things:

        • /etc/rc.d/init.d/hpoj is evidently a symlink to /usr/sbin/ptal-init
        • The lines you quoted seem to come from a patch attached to ALEXANDRE's comment#7
        • The same ALEXANDRE submitted another patch with comment#8 indicating that her first patch: "...isn't even correct perl."
        I would read the rest of that bug, and take a look at the most recent release of your software.

        There is certainly an eval command in bash. My One-liner japh is a bash script and it uses the eval builtin.

Re: understanding eval in HPOJ
by ambrus (Abbot) on Apr 04, 2004 at 19:56 UTC

    I think that this is bash code, not perl. But I must admit that I don't quite understand it either.

        I think the poster may have been referring to the fact that it uses environmental variables.

        Want to support the EFF and FSF by buying cool stuff? Click here.

        It reminds me to some code by which you can run the same script under bash and perl too. One variant of such code is:

        #!/bin/sh -- # -*- perl -*- -p eval 'exec perl -wS $0 ${1+"$@"}' if $running_under_some_shell;

        This has both eval end exec.

        The more sophisticated one is:

        #! /bin/sh eval '(exit $?0)' && eval 'PERL_BADLANG=x;PATH="$PATH:.";export PERL_B +ADLANG\ ;exec perl -T -x -S -- "$0" ${1+"$@"};#'if 0;eval 'setenv PERL_BADLANG + x\ ;setenv PATH "$PATH":.;exec perl -T -x -S -- "$0" $argv:q;#'.q #!perl -wi.bak +push@INC,'.';$0=~/(.*)/s;do(index($1,"/")<0?"./$1":$1);die$@if$@__END +__+if 0 ;#Don't touch/remove lines 1--7: +.Header

        (Which runs under csh too).

Re: understanding eval in HPOJ
by qq (Hermit) on Apr 04, 2004 at 21:46 UTC

    Does the script usually expect arguments? If its called again with that strange 1+err arg does it try and do anything with it?

    Your second code sample does look a lot more obvious, but I'll be watching this thread to see if anyone can explain $?0. It gives me syntax errors.

    Is there any way to google of such strings? (Perl syntax friendly search engines/tips anyone?)

    Sorry for another unhelpful reply...


Re: understanding eval in HPOJ
by Vautrin (Hermit) on Apr 04, 2004 at 20:30 UTC

    When I typed echo $LANG from my BASH prompt it spit out the letter C. The script probably needs to make sure the $LANG variable is set, and is checking for its existence (some scripts are run without any environmental variables for security). Not sure what the evals are doing without looking up the variables they're using, and a quick google for the purpose of $LANG didn't turn up anything.

    Want to support the EFF and FSF by buying cool stuff? Click here.
Re: understanding eval in HPOJ
by halley (Prior) on Apr 05, 2004 at 15:45 UTC
    This looks at first glance that it was intended as a polyglot incantation. That means it is meant for BOTH bash and for perl to read and act accordingly. These are very ugly and fickle, especially if something changes in the operating environment.

    There's a related example in perlrun, which may shed some light. The key features of these perl/shell polyglots are that they

    • come first in the script
    • use the suffix/modifier form of 'if' after a newline
    • use keywords that are common to both perl and the shell

    IF perl runs it, AND the internationalization $ENV{LANG} isn't set to the POSIX C setting, THEN the script will try to RESTART the script via the shell, with the appropriate environmental fix.

    IF on the otherhand, a shell runs it, THEN the if line is completely ignored since it doesn't get that far. The exit/exec pair see to that.

    The tortured use of confusing clauses like eval 'somestring' are just a side effect to ensure that it does the right thing in both cases, errors and warnings be damned.

    On Linux and many Un*x varieties, the kernel reads the shebang line and decides that the perl interpreter must be used if not otherwise specified. On DOS/Windows, and on some Un*x varieties, there is no such assumption that the shebang must be inspected. So these polyglots are sometimes used to ensure that the right interpreter is run. (CMD.EXE/PERL.EXE polyglots are even uglier.)

    (Sorry I'm not at a station where I can play with this further.)

    [ e d @ h a l l e y . c c ]

      I found a solution which I should've tried initially. I started by putting this in there after the variable was supposedly set:

      system( 'echo "LANG=|$LANG|" | /bin/mail "LANG environment variable" m +yuser' );

      Then I rebooted and found that it was not set like it should've been. It was set to "en_US.UTF-8", which I think it gets from the file /etc/sysconfig/i18n. I actually thought it might not even be getting past the goofy line because the first part is an exit.

      I commented the two goofy lines and put the BEGIN block that I mentioned in the earlier post in there and rebooted again. I was pleased to see that my email says LANG=|C| and I checked the process listing and found that my printer daemon is running.

      I don't fully understand what's happening in there, but thanks to halley's explanation, I get the idea. I think my solution will only work in my environment and is not as versatile as the original author intended. I'll read perlrun in a minute to see if I understand better.

      Thanks to all for the brain cells. I'll post the problem and my solution to hpoj-devel and post here if they give me a Perlish solution and/or explanation.

      -- GhodMode

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://342498]
Approved by broquaint
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2022-05-27 06:32 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (94 votes). Check out past polls.