For Programmers: Free Programming Magazines  


Home > Archive > Tcl > May 2006 > Problem: 'file executable' not checking 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 Problem: 'file executable' not checking PATH?
Jack Daly

2006-05-24, 7:07 pm

I have a simple test script which tries to test for the existence of
an executable file before exec'ing it:

set prog "printargs"
if {![file executable $prog]} {
puts [file executable $prog]; # 0
puts [file executable ~/bin/printargs]; # 1
puts [file executable printargs]; # 0
puts [file executable ls]; # 0
puts [exec printargs]; # works!
}

The comments show the result of the 'file' command. 'printargs' is in
~/bin, with permissions '-rwxr-xr-x'. So, althougth the script can
execute 'printargs', and it knows that ~/bin/printargs is executable,
it *doesn't* know that 'printargs' is executable. I've checked the
path in the script, and it correctly shows that '~/bin' is in the
path.

Any ideas? How do I check if a file which is at an arbitrary location
in PATH exists and is executable?

I'm on Linux/RHEL4, tcl8.4.

Thanks -

Jack
Darren New

2006-05-24, 7:07 pm

Jack Daly wrote:
> ~/bin, with permissions '-rwxr-xr-x'. So, althougth the script can
> execute 'printargs', and it knows that ~/bin/printargs is executable,
> it *doesn't* know that 'printargs' is executable.


You are confusing the file "printargs" with the command "printargs". The
file "printargs" doesn't exist, so it can't be executable. The file
"~/bin/printargs" technically doesn't exist either - some piece of
software is replacing the "~" with an actual pathname based on your
login name and environment variables and such.

[file executable] tells you if a file is executable, not a command.

> Any ideas? How do I check if a file which is at an arbitrary location
> in PATH exists and is executable?


I believe you have to iterate throught $PATH one entry at a time, append
the file name you want to execute, and check. This assumes that the file
name is a relative file name.

--
Darren New / San Diego, CA, USA (PST)
My Bath Fu is strong, as I have
studied under the Showerin' Monks.
Ralf Fassel

2006-05-24, 7:07 pm

* Jack Daly <jd1033@yahoo.com>
| I have a simple test script which tries to test for the existence of
| an executable file before exec'ing it:

If people die if the test succeeds and the exec fails, you should
rethink that strategy. Just catch the exec and present the occasional
error:
% exec nono
couldn't execute "nono": no such file or directory
% set errorCode
POSIX ENOENT {no such file or directory}

| puts [file executable ~/bin/printargs]; # 1
| puts [file executable printargs]; # 0

The file command does not handle PATH. It handles the exact filename
(modulo tilde-substition) you pass, nothing less, nothing more.

Consider: of course there is a file named "passwd" *somewhere* on my
system, so should
file readable passwd
return true in every directory?

| Any ideas? How do I check if a file which is at an arbitrary
| location in PATH exists and is executable?
|
| I'm on Linux/RHEL4, tcl8.4.

On Unix, you can try
exec sh -c [list type $cmd]

I.e. let the shell handle the PATH search for you:

% catch {exec sh -c [list type nono]}
1
% catch {exec sh -c [list type true]}
0

HTH
R'
stephanearnold@yahoo.fr

2006-05-24, 7:07 pm

>Try auto_execok :

% puts [auto_execok cmd.exe] ;# prints 'c:\windows\system32\cmd.exe'

if {[llength [auto_execok mycmd]]} {
exec mycmd ...
} else {
# we don't have mycmd
}

Regards,
St=E9phane

Michael Schlenker

2006-05-24, 10:04 pm

Jack Daly wrote:
> On Wed, 24 May 2006 17:25:33 +0200, Ralf Fassel <ralfixx@gmx.de>
> wrote:
>
>
> Thanks. This seems to work:
>
> set driver "wibble"
> set status [catch {exec $driver -help}]
> if { ($status != 0) } {
> puts [ format "** Error executing '$driver' (%s) **" $::errorCode]
> exit 1
> }
>
>
> Hmmm. I would argue that 'file readable' is documented in such a way
> that you would expect the 'correct' behaviour. However, this is what
> Ousterhout's book says about 'executable':
>
> "returns 1 if name is executable by the current user, 0 otherwise".
>
> The concept of 'executable' is an operating system concept, not a tcl
> concept (if you exclude the case of tcl scripts themselves). Ergo, you
> have to use the OS to decide if 'name' is executable, and the OS may
> or may not use PATH to make that decision. That's got nothing to do
> with tcl.
>
> In addition, Ousterhout also says "the first argument to exec is the
> name of a program to execute". The OS is used to execute 'name' in
> this case, and the OS may search PATH to do so. It seems to me to be
> plain wrong that the result of 'file executable' is inconsistent with
> this.
>
> So, my humble conclusion is that tcl is wrong here.


One could argue that 'file executable should be moved to a platform
specific extension like tclx as it some platforms do not really have an
executable flag, especially if things like ACL's come into play.

One other thing about this is race conditions. Someone could change the
file between your call to file executable and exec.

So IMHO the only real use for file executable is to use it for a
display, to give executable files a different color, icon etc.

Michael


Gerald W. Lester

2006-05-24, 10:04 pm

Jack Daly wrote:
>...
>
> Hmmm. I would argue that 'file readable' is documented in such a way
> that you would expect the 'correct' behaviour. However, this is what
> Ousterhout's book says about 'executable':
>
> "returns 1 if name is executable by the current user, 0 otherwise".
>
> The concept of 'executable' is an operating system concept, not a tcl
> concept (if you exclude the case of tcl scripts themselves). Ergo, you
> have to use the OS to decide if 'name' is executable, and the OS may
> or may not use PATH to make that decision. That's got nothing to do
> with tcl.
>
> In addition, Ousterhout also says "the first argument to exec is the
> name of a program to execute". The OS is used to execute 'name' in
> this case, and the OS may search PATH to do so. It seems to me to be
> plain wrong that the result of 'file executable' is inconsistent with
> this.
>
> So, my humble conclusion is that tcl is wrong here.


I beg to differ, first off John's book is not the official documentation,

From the top of the file man/help page:

This command provides several operations on a file's name or attributes.
Name is the name of a file; if it starts with a tilde, then tilde
substitution is done before executing the command

IMHO, this clearly states that that "name" is the name of a file. Part of a
file's name is the path, is the path is missing then it is relative to the
current working directory (on *nix, OX/X and Windows). Thus I believe the
current behavior is properly documented.

You may of course put in a bug report, I have major doubts if the behavior
will change.

BTW, John's book is way out date you may want to switch to something more
modern.

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
Donald Arseneau

2006-05-24, 10:04 pm

Jack Daly <jd1033@yahoo.com> writes:

> Ousterhout's book says about 'executable':
>
> "returns 1 if name is executable by the current user, 0 otherwise".
>
> The concept of 'executable' is an operating system concept, not a tcl


Fine. But you are talking about the *file* command, and the argument
is a *file name*. Your problem is finding that file, not determining
if it is executable.

> In addition, Ousterhout also says "the first argument to exec is the
> name of a program to execute".


The exec command has nothing to do with the file command. Yes, the
first argument to exec is the name of a program, but the argument
following "file executable" is a file name, not a program.

What appears to be poorly documented is whether a particular
file subcommand throws an error when the file does not exist.
Some of the subcommands are documented to return errors,
(like file mtime) but most don't mention the possibility.
For example [file attributes f] returns an error for a
non-existent file, but [file executable f] does not.



--
Donald Arseneau asnd@triumf.ca
Fredderic

2006-05-25, 8:14 am

On Wed, 24 May 2006 17:57:58 +0100,
Jack Daly <jd1033@yahoo.com> wrote:

> Hmmm. I would argue that 'file readable' is documented in such a way
> that you would expect the 'correct' behaviour.


The 'correct' behaviour, is that it checks whether a file is readable.
If you mean [file executable], then it means the exact same. Is the
specified file executable (right now)? That's not the same as "is the
command I *really* want executable?" For that, we need to figure out
WHERE that command is; if it's internal to the shell, then we're
stuffed. If it's a file, we still need to figure out WHERE that file
is.

In Linux (and most Unix's), the current directory isn't automatically
considered part of the search path by default. I can, if I need to,
still execute a file in the current directory (or in fact, any
directory on the system) by specifying the path (./somefile will do,
for example). Not only that, but the shell will skip non-executable
files as it searches the path looking for one to execute. So if there
were two files with that name, one early in the path that wasn't
executable, and one later in the path that was (and happens to be the
one that [exec] would end up running), exactly what would you want the
[file executable] command to return?

What you're asking for, seems to be something along the lines of this:

proc findExecutable {name} {
foreach dir [split $::env(PATH) :] {
if { [file executable $dir/$name] } {
return $dir/$name
}
}
}


Fredderic
Ramon Ribó

2006-05-25, 8:14 am


Try command:

set file [auto_execok printargs]

Ramon Ribó

En Wed, 24 May 2006 17:06:13 +0200, Darren New <dnew@san.rr.com> escribió:

> Jack Daly wrote:
>
> You are confusing the file "printargs" with the command "printargs". The
> file "printargs" doesn't exist, so it can't be executable. The file
> "~/bin/printargs" technically doesn't exist either - some piece of
> software is replacing the "~" with an actual pathname based on your
> login name and environment variables and such.
>
> [file executable] tells you if a file is executable, not a command.
>
>
> I believe you have to iterate throught $PATH one entry at a time, append
> the file name you want to execute, and check. This assumes that the file
> name is a relative file name.
>




--
Compass Ing. y Sistemas Dr. Ramon Ribo
http://www.compassis.com ramsan@compassis.com
c/ Tuset, 8 7-2 tel. +34 93 218 19 89
08006 Barcelona, Spain fax. +34 93 396 97 46
Ralf Fassel

2006-05-25, 8:14 am

* Jack Daly <jd1033@yahoo.com>
| The concept of 'executable' is an operating system concept, not a
| tcl concept (if you exclude the case of tcl scripts
| themselves). Ergo, you have to use the OS to decide if 'name' is
| executable, and the OS may or may not use PATH to make that
| decision.

No OS I know of (Unix, Windows) takes PATH into account when
determining whether a file is executable. The stat() family of system
calls on Unix simply take the file name you give it and return the
info for it. This is exactly what TCL does.

Asking the OS to _execute_ a file as a program is a completely
different matter. Eg on Unix, you have two kinds of exec() system
calls, one kind which searches PATH and the other doesn't. So if you
use e.g. execv() for some filename, you may get an error, and if you
use execvp() for the exact same file name, you don't get an error.
Is the OS wrong or right when execv() returns an error?

| That's got nothing to do with tcl.

I agree :-)

R'
Sponsored Links







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

Copyright 2008 codecomments.com