Perl command call check

Discussion in 'Perl Misc' started by neilsolent, Apr 29, 2009.

  1. neilsolent

    neilsolent Guest

    Before calling a command with system() or with backticks, is there a
    neat way to check that the executable exists in the path (i.e. like
    the UNIX "which" command) ?

    Seems a bit untidy to attempt to run the command blindly and then use
    the return code / output to first check whether the command was even
    found.

    thanks,
    Neil
    neilsolent, Apr 29, 2009
    #1
    1. Advertising

  2. neilsolent <> wrote:
    > Before calling a command with system() or with backticks, is there a
    > neat way to check that the executable exists in the path (i.e. like
    > the UNIX "which" command) ?



    It is a Really Good Idea to use a full pathspec for external
    commands rather than relying on PATH.

    If PATH=/opt/badbin:/bin and there is an "ls" in badbin/ then
    system 'ls *'
    will run badbin/ls whereas
    system '/bin/ls *'
    will run /bin/ls.


    > Seems a bit untidy to attempt to run the command blindly and then use
    > the return code / output to first check whether the command was even
    > found.


    If you adopt the security measure suggested above then:

    die "/bin/ls could not be executed" unless -x '/bin/ls';

    :)


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad J McClellan, Apr 30, 2009
    #2
    1. Advertising

  3. neilsolent

    neilsolent Guest

    On 30 Apr, 00:45, Tad J McClellan <> wrote:
    > neilsolent <> wrote:
    > > Before calling a command with system() or with backticks, is there a
    > > neat way to check that the executable exists in the path (i.e. like
    > > the UNIX "which" command) ?

    >
    > It is a Really Good Idea to use a full pathspec for external
    > commands rather than relying on PATH.
    >


    Thanks for you post.
    I disagree - at least this depends on the context.
    If I fix paths to executables - I seriously reduce the portability.
    If I end up calling a bad version of a command - then the system was
    in a bad state to start with!
    I think it is a fair enough assumption that the PATH is setup
    correctly and won't cause bad things to happen. If not - much more is
    likely to break than just this script.
    neilsolent, Apr 30, 2009
    #3
  4. neilsolent

    neilsolent Guest

    > > Before calling a command with system() or with backticks, is there a
    > > neat way to check that the executable exists in the path (i.e. like
    > > the UNIX "which" command) ?

    >
    > File::Which. Note that this won't find shell builtins, even though you
    > can invoke them with system.
    >
    > It is worth mentioning that there is a race condition between this check
    > and the actual invocation, and that trying something and letting it fail
    > is usually a better strategy than trying to second-guess the answer;
    > however, I'm pretty sure that all implementations of system that search
    > the PATH have the same race condition internally, so it doesn't matter
    > much in this case.
    >


    Thanks for that.
    Hmm race condition - don't like the sound of that! I think you are
    right - I will just submit the commands and work out what happened
    after.
    neilsolent, Apr 30, 2009
    #4
  5. neilsolent

    Tim McDaniel Guest

    In article <>,
    Tad J McClellan <> wrote:
    >neilsolent <> wrote:
    >> Before calling a command with system() or with backticks, is there
    >> a neat way to check that the executable exists in the path
    >> (i.e. like the UNIX "which" command) ?

    >
    >It is a Really Good Idea to use a full pathspec for external
    >commands rather than relying on PATH.
    >
    >If PATH=/opt/badbin:/bin and there is an "ls" in badbin/ then
    > system 'ls *'
    >will run badbin/ls whereas
    > system '/bin/ls *'
    >will run /bin/ls.


    As another reply said, hard-coding paths is also a bad idea. On one
    system I use, perl is in /usr/bin. On another, it is in /bin and
    /usr/bin. On another, it is in /usr/local/bin -- and that's the one
    system I have no control over, so I can't symlink on it. And I copy
    my utility scripts to all systems that I use.

    If someone sets up a path with their own version of a command that's
    usually gotten from the system,

    - there's often a good reason. I've written wrappers and put them in
    ~/bin to paper over differences in locations as above. I use my own
    version of hostname that compensates somewhat for different syntaxes
    and behaviors on different OSes.

    - if their own version makes another program misbehave, it's their own
    damned fault and they got what they deserved.

    --
    Tim McDaniel,
    Tim McDaniel, Apr 30, 2009
    #5
  6. On Apr 30, 1:12 am, neilsolent <> wrote:
    > I will just submit the commands and work out what happened
    > after.


    Well with system() or backticks, how do know if it's telling you that
    the command doesn't exist vs. exit failure?

    ~ >uname
    Linux
    ~ >perl -e'print(system("bass > /dev/null 2>&1")>>8)'
    127
    ~ >grep '\<127\>' /usr/include/asm-generic/errno.h
    #define EKEYEXPIRED 127 /* Key has expired */

    Hum, not sure what that means, let’s try something familiar:

    ~ >perl -e'print(system("ls nope > /dev/null 2>&1")>>8)'
    2
    ~ >grep '\<2\>' /usr/include/asm-generic/errno-base.h '
    #define ENOENT 2 /* No such file or directory */

    Ah ok. Let’s see what the exit value of an inaccessible command is on
    Solaris?

    ~ >uname
    SunOS
    ~ >perl -e'print(system("bass > /dev/null 2>&1")>>8)'
    sh: bass: not found
    1

    I'd stick with the Which module.

    -Skye
    Skye Shaw!@#$, May 1, 2009
    #6
  7. neilsolent

    neilsolent Guest

    > > I will just submit the commands and work out what happened
    > > after.

    >
    > Well with system() or backticks, how do know if it's telling you that
    > the command doesn't exist vs. exit failure?


    I find $? (within the Perl process) gets set to -1, and $! is set to
    something like "file not found".
    Does your platform do something different ?
    neilsolent, May 6, 2009
    #7
  8. neilsolent <> wrote in news:d5509dd5-9abf-416c-
    :

    >> > I will just submit the commands and work out what happened
    >> > after.

    >>
    >> Well with system() or backticks, how do know if it's telling you that
    >> the command doesn't exist vs. exit failure?

    >
    > I find $? (within the Perl process) gets set to -1, and $! is set to
    > something like "file not found".
    > Does your platform do something different ?


    The documentation for the system function explains:

    You can check all the failure possibilities by inspecting $?
    like this:

    if ($? == -1) {
    print "failed to execute: $!\n";
    }
    elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
    ($? & 127), ($? & 128) ? 'with' : 'without';
    }
    else {
    printf "child exited with value %d\n", $? >> 8;
    }

    Alternatively you might inspect the value of
    "${^CHILD_ERROR_NATIVE}" with the W*() calls of the POSIX
    extension.

    Read the rest of the documentation for potential pitfalls when the shell
    is involved.

    Sinan
    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://www.rehabitation.com/clpmisc/
    A. Sinan Unur, May 6, 2009
    #8
  9. neilsolent

    neilsolent Guest


    > The documentation for the system function explains:
    >


    Read the manual eh ? Good idea :)

    Thanks for the post - think that has cleared this thread up
    I already discovered the common -1 code for $?, but it is useful to
    see the official explanation.
    neilsolent, May 7, 2009
    #9
  10. neilsolent <> wrote in news:f89fa97f-b215-4777-
    :

    >
    >> The documentation for the system function explains:
    >>

    >
    > Read the manual eh ? Good idea :)


    Always ;-)

    Sinan

    --
    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://www.rehabitation.com/clpmisc/
    A. Sinan Unur, May 7, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jim
    Replies:
    2
    Views:
    451
  2. prakash
    Replies:
    2
    Views:
    581
    prakash
    Apr 11, 2005
  3. Replies:
    2
    Views:
    159
    Tad McClellan
    Mar 26, 2005
  4. Replies:
    0
    Views:
    141
  5. luca
    Replies:
    3
    Views:
    358
    Robin
    Nov 21, 2010
Loading...

Share This Page