For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > July 2004 > Finding if a file exists in $PATH









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Finding if a file exists in $PATH
Ashutosh

2004-07-22, 3:58 pm

Hi,

Is there a good way to find if an executable file exists in $PATH, before
trying to exec it from within a C program. My program basically execs xterm
with the parameters equivalent to:

xterm -e some_program

if some_program doesn't exist in $PATH, what ends up happening is that a new
xterm opens with the error message "xterm: Can't execvp some_program: No
such file or directory", and gives a command prompt. Can I check if
some_program really exists and is executable before passing it on to xterm.
One way could possibly be to fork(), and actually execvp some_program and
then kill it. Is there a better/another way?

Thanks,
Ashutosh


Chris Slominski

2004-07-22, 3:58 pm


"Ashutosh" <ashusharma1980@yahoo.co.uk> wrote in message
news:cYQLc.689$bA6.412478@newshog.newsread.com...
> Hi,
>
> Is there a good way to find if an executable file exists in $PATH, before
> trying to exec it from within a C program. My program basically execs

xterm
> with the parameters equivalent to:
>
> xterm -e some_program
>
> if some_program doesn't exist in $PATH, what ends up happening is that a

new
> xterm opens with the error message "xterm: Can't execvp some_program: No
> such file or directory", and gives a command prompt. Can I check if
> some_program really exists and is executable before passing it on to

xterm.
> One way could possibly be to fork(), and actually execvp some_program and
> then kill it. Is there a better/another way?
>
> Thanks,
> Ashutosh
>
>


You could issue the UNIX 'which' command from within your program.

Chris


Ashutosh

2004-07-22, 3:58 pm

"Ashutosh" <ashusharma1980@yahoo.co.uk> wrote in message
news:cYQLc.689$bA6.412478@newshog.newsread.com...
> Hi,
>
> Is there a good way to find if an executable file exists in $PATH, before
> trying to exec it from within a C program. My program basically execs

xterm
> with the parameters equivalent to:
>
> xterm -e some_program
>
> if some_program doesn't exist in $PATH, what ends up happening is that a

new
> xterm opens with the error message "xterm: Can't execvp some_program: No
> such file or directory", and gives a command prompt. Can I check if
> some_program really exists and is executable before passing it on to

xterm.
> One way could possibly be to fork(), and actually execvp some_program and
> then kill it. Is there a better/another way?
>
> Thanks,
> Ashutosh
>
>


One way could also be to getenv("PATH") and then parse it and then see if
some_program exists in any of these directories and is executable by the
effective current user. Could there be a less cumbersome way too?

Ashutosh


Lev Walkin

2004-07-22, 3:58 pm

Ashutosh wrote:
> "Ashutosh" <ashusharma1980@yahoo.co.uk> wrote in message
> news:cYQLc.689$bA6.412478@newshog.newsread.com...
>
>
> xterm
>
>
> new
>
>
> xterm.
>
>
>
> One way could also be to getenv("PATH") and then parse it and then see if
> some_program exists in any of these directories and is executable by the
> effective current user. Could there be a less cumbersome way too?


man which


which some_program >/dev/null && xterm -e some_program

--
Lev Walkin
vlm@lionet.info
Casper H.S. Dik

2004-07-22, 3:58 pm

"Ashutosh" <ashusharma1980@yahoo.co.uk> writes:

>Is there a good way to find if an executable file exists in $PATH, before
>trying to exec it from within a C program. My program basically execs xterm
>with the parameters equivalent to:


>xterm -e some_program


>if some_program doesn't exist in $PATH, what ends up happening is that a new
>xterm opens with the error message "xterm: Can't execvp some_program: No
>such file or directory", and gives a command prompt. Can I check if
>some_program really exists and is executable before passing it on to xterm.
>One way could possibly be to fork(), and actually execvp some_program and
>then kill it. Is there a better/another way?



Why not try this:


xterm -e sh -c "exec program"

I think we can safely assume that the exec of "sh" will succeed; sh
will then run "program" and xterm will not know the difference between
program not existing and programming being very fast indeed.

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Chuck Dillon

2004-07-22, 3:58 pm

Ashutosh wrote:
> Hi,
>
> Is there a good way to find if an executable file exists in $PATH, before
> trying to exec it from within a C program. My program basically execs xterm
> with the parameters equivalent to:
>
> xterm -e some_program
>
> if some_program doesn't exist in $PATH, what ends up happening is that a new
> xterm opens with the error message "xterm: Can't execvp some_program: No
> such file or directory", and gives a command prompt. Can I check if
> some_program really exists and is executable before passing it on to xterm.


Casper's suggestion is a good one as long as your program doesn't need
to be aware of the problem. If it does then you need a wrapper script
or launcher program to help you. You would have xterm call the wrapper
rather than some_program. The wrapper would capture the problem and
pass it back to you via some for of IPC you would devise.

> One way could possibly be to fork(), and actually execvp some_program and
> then kill it. Is there a better/another way?



Note, I haven't done the following other than experimenting in a shell,
so this is just a suggestion of something to experiment with in your
program.

You could try doing a fork() then use setrlimit() to set the datasize
very small (near 0) or the number of descriptors to less than 3 (not
enough for stdio) and then immediately exec().

In the small datasize case the exec should fail and errno should tell
you why. ENOMEM means it wanted to run a program but couldn't. ENOENT
means it couldn't find the program. You then exit indicating which is
the case.

In the small descriptors case the exec will succeed (at least on
Solaris) and the program will be killed. So if the exec fails
(indicating ENOENT) you exit with something distinguishable from the
killed case. A similar effect can be had by limiting the stacksize to
something unreasonable.

-- ced





--
Chuck Dillon
Senior Software Engineer
NimbleGen Systems Inc.
Ashutosh

2004-07-23, 3:57 am

"Casper H.S. Dik" <Casper.Dik@Sun.COM> wrote in message
news:40ffef44$0$34762$e4fe514c@news.xs4all.nl...
> "Ashutosh" <ashusharma1980@yahoo.co.uk> writes:
>
xterm[color=darkred]
>
>
new[color=darkred]
xterm.[color=darkred]
>
>
> Why not try this:
>
>
> xterm -e sh -c "exec program"
>
> I think we can safely assume that the exec of "sh" will succeed; sh
> will then run "program" and xterm will not know the difference between
> program not existing and programming being very fast indeed.
>
> Casper
> --
> Expressed in this posting are my opinions. They are in no way related
> to opinions held by my employer, Sun Microsystems.
> Statements on Sun products included here are not gospel and may
> be fiction rather than truth.


Thanks Casper. This seems perfect.


Ashutosh

2004-07-23, 3:57 am

"Chuck Dillon" <spam@nimblegen.com> wrote in message
news:cdp0ik$lth$1@grandcanyon.binc.net...
> Ashutosh wrote:
before[color=darkred]
xterm[color=darkred]
new[color=darkred]
xterm.[color=darkred]
>
> Casper's suggestion is a good one as long as your program doesn't need
> to be aware of the problem. If it does then you need a wrapper script
> or launcher program to help you. You would have xterm call the wrapper
> rather than some_program. The wrapper would capture the problem and
> pass it back to you via some for of IPC you would devise.
>
and[color=darkred]
>
>
> Note, I haven't done the following other than experimenting in a shell,
> so this is just a suggestion of something to experiment with in your
> program.
>
> You could try doing a fork() then use setrlimit() to set the datasize
> very small (near 0) or the number of descriptors to less than 3 (not
> enough for stdio) and then immediately exec().
>
> In the small datasize case the exec should fail and errno should tell
> you why. ENOMEM means it wanted to run a program but couldn't. ENOENT
> means it couldn't find the program. You then exit indicating which is
> the case.
>
> In the small descriptors case the exec will succeed (at least on
> Solaris) and the program will be killed. So if the exec fails
> (indicating ENOENT) you exit with something distinguishable from the
> killed case. A similar effect can be had by limiting the stacksize to
> something unreasonable.
>
> -- ced
> --
> Chuck Dillon
> Senior Software Engineer
> NimbleGen Systems Inc.


Thanks Chuck. I'll try to see if this solves the problem. One possible issue
might be the fact that doing a fork() might be very very taxing in my case,
as the entire address-space will be copied. I'm currently using vfork to
finally exec the xterm.

- Ashutosh


Ashutosh

2004-07-23, 8:57 am

"Chuck Dillon" <spam@nimblegen.com> wrote in message
news:cdp0ik$lth$1@grandcanyon.binc.net...
> Ashutosh wrote:
before[color=darkred]
xterm[color=darkred]
new[color=darkred]
xterm.[color=darkred]
>
> Casper's suggestion is a good one as long as your program doesn't need
> to be aware of the problem. If it does then you need a wrapper script
> or launcher program to help you. You would have xterm call the wrapper
> rather than some_program. The wrapper would capture the problem and
> pass it back to you via some for of IPC you would devise.
>
and[color=darkred]
>
>
> Note, I haven't done the following other than experimenting in a shell,
> so this is just a suggestion of something to experiment with in your
> program.
>
> You could try doing a fork() then use setrlimit() to set the datasize
> very small (near 0) or the number of descriptors to less than 3 (not
> enough for stdio) and then immediately exec().
>
> In the small datasize case the exec should fail and errno should tell
> you why. ENOMEM means it wanted to run a program but couldn't. ENOENT
> means it couldn't find the program. You then exit indicating which is
> the case.
>
> In the small descriptors case the exec will succeed (at least on
> Solaris) and the program will be killed. So if the exec fails
> (indicating ENOENT) you exit with something distinguishable from the
> killed case. A similar effect can be had by limiting the stacksize to
> something unreasonable.
>
> -- ced
>
>
>
>
>
> --
> Chuck Dillon
> Senior Software Engineer
> NimbleGen Systems Inc.


Thanks Chuck. I'll try to see if this solves the problem. One possible issue
might be the fact that doing a fork() might be very very taxing in my case,
as the entire address-space will be copied. I'm currently using vfork to
finally exec the xterm.

- Ashutosh


Chuck Dillon

2004-07-23, 3:57 pm

Ashutosh wrote:

>
>
>
> Thanks Chuck. I'll try to see if this solves the problem. One possible issue
> might be the fact that doing a fork() might be very very taxing in my case,
> as the entire address-space will be copied. I'm currently using vfork to
> finally exec the xterm.
>


On a modern *NIX memory is copied only when modified by the child. So
{ fork(); exec("foo"...); } has relatively little overhead in terms
of memory consumption.

-- ced



--
Chuck Dillon
Senior Software Engineer
NimbleGen Systems Inc.
Ashutosh

2004-07-23, 3:57 pm

"Chuck Dillon" <spam@nimblegen.com> wrote in message
news:cdr5hf$7tp$1@grandcanyon.binc.net...
> Ashutosh wrote:
>
issue[color=darkred]
case,[color=darkred]
>
> On a modern *NIX memory is copied only when modified by the child. So
> { fork(); exec("foo"...); } has relatively little overhead in terms
> of memory consumption.
>
> -- ced
>
>
>
> --
> Chuck Dillon
> Senior Software Engineer
> NimbleGen Systems Inc.


I'll try this then. Meanwhile, I've written the code to getenv("PATH") and
then search for it. I had tried doing a 'xterm -e sh -c "some_program"' ,
but it seemes to have a problem that the arguments given to some_program are
interpreted by the shell so this has the same insecurities as using the
'system' function. (e.g. a ';rm -rf /' in the arguments).

Ashutosh


Lev Walkin

2004-07-24, 3:56 am

Chuck Dillon wrote:
> Ashutosh wrote:
>
>
> On a modern *NIX memory is copied only when modified by the child. So
> { fork(); exec("foo"...); } has relatively little overhead in terms of
> memory consumption.


On a modern *NIX vfork() simply invokes fork(), and the old vfork() semantics
is explicitly not supported.

--
Lev Walkin
vlm@lionet.info
Michael Kerrisk

2004-07-28, 9:05 pm

On Fri, 23 Jul 2004 20:58:56 -0700, Lev Walkin <vlm@lionet.info>
wrote:

>Chuck Dillon wrote:
>
>On a modern *NIX vfork() simply invokes fork(), and the old vfork() semantics
>is explicitly not supported.


Hmm... Define "modern *NIX". As far as I know, vfork() is not
implemented as fork() on:

FreeBSD 5.1
Solaris 8
HP-UX 11
Linux 2.6

but is implemented as fork() on Tru64 5.1.

Cheers,

Michael
Lev Walkin

2004-07-28, 9:05 pm

Michael Kerrisk wrote:
> On Fri, 23 Jul 2004 20:58:56 -0700, Lev Walkin <vlm@lionet.info>
> wrote:
>
>
>
>
> Hmm... Define "modern *NIX". As far as I know, vfork() is not
> implemented as fork() on:
>
> FreeBSD 5.1
> Solaris 8
> HP-UX 11
> Linux 2.6
>
> but is implemented as fork() on Tru64 5.1.


Yes, indeed. Even FreeBSD 4.x has it.

Yet,

=== cut from FreeBSD manual page ===
This system call will be eliminated when proper system sharing mechanisms
are implemented. Users should not depend on the memory sharing semantics
of vfork() as it will, in that case, be made synonymous to fork(2).
=== cut ===

As I understand, it is there just to support legacy code. New code
is strongly discouraged from using vfork().

--
Lev Walkin
vlm@lionet.info
Michael Kerrisk

2004-07-28, 9:05 pm

On Mon, 26 Jul 2004 05:59:19 -0700, Lev Walkin <vlm@lionet.info>
wrote:

>Michael Kerrisk wrote:
>
>Yes, indeed. Even FreeBSD 4.x has it.
>
>Yet,
>
>=== cut from FreeBSD manual page ===
> This system call will be eliminated when proper system sharing mechanisms
> are implemented. Users should not depend on the memory sharing semantics
> of vfork() as it will, in that case, be made synonymous to fork(2).
>=== cut ===


The BSD vfork() man page has been saying that for more than 20
years...

>As I understand, it is there just to support legacy code.


Well -- to give the fastest possible fork().

>New code
>is strongly discouraged from using vfork().


Yes, the semantics are dangerous; but neverthless it is still used
occasionally.

Cheers,

Michael
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com