0

We have some applications in various subdirectories that we limit access to by unix group, and we want them to be execute only. So, for example, if we want members of the "chem" group to have execute-only access to a.out, we have:

$ ll -d /tmp/dir1
drwx--x--- 2 root chem 18 Oct 20 07:50 /tmp/dir1/
$ ll /tmp/dir1/a.out 
-rwx--x--- 1 root chem 8728 Oct 20 07:50 /tmp/dir1/a.out

Now from the bash shell I (a member of the "chem" group) can add this directory to my path and execute a.out:

$ export PATH=/tmp/dir1:$PATH
$ a.out
 This is a test. . .

From tcsh, however, I can't:

$ set path = ( /tmp/dir1 $path )
$ a.out
a.out: Command not found.

I have to add group read permission to the parent directory for a tcsh user to be able to run a.out (bash works in both cases):

$ ll -d /tmp/dir1
drwxr-x--- 2 root chem 18 Oct 20 07:50 /tmp/dir1/

After the chmod I log out and back in (under tcsh), then:

$ set path = ( /tmp/dir1 $path )
$ a.out
 This is a test. . .

We expected that read permission on the parent directory would not be needed. I've looked all over for documentation that would explain the apparent in difference in behavior between bash and tcsh in this case, but no luck. Can anyone explain this? By the way, I did these tests under SLES 12 and CentOS 7, and the behavior was the same in both cases.

1 Answer 1

4

bash searches every directory in $PATH (from first to last) every time you run a command, trying to run the command out of that directory. It either succeeds or fails. So if /tmp/dir1 is in your $PATH, and a.out is in that directory, you can try to run a.out - bash will try to run /tmp/dir1/a.out, and that succeeds because you have execute permission.

csh is different. When you change (or set) the $path, csh builds a hash table of everything it finds in every directory in the path, and it remembers what order those directories appear in the path. By default, when you run a command (without using a full pathname), csh looks in its hash tables to see if it remembers that command being on the path somewhere (and if more than one directory in your path has it, it picks the first one it finds in the order listed in $path. If it doesn't find it in the hash table, then it assumes no such command exists, and you get an error. This was useful long ago, when the amount of time it took to walk down all the directories in the search path and look for the command was actually significant. It's not so significant anymore, but csh has always behaved this way, and it still does today.

In order for csh to build its hash table, it needs read permission on all of the directories in $path. Because it needs to be able to know exactly what executables live in which directories in the $path. Because you've denied read permission for /tmp/dir1, csh can't build the hash table for it, and it treats it as if there are no commands in that directory at all. That's why csh can't find your a.out file in a directory in the $path that it doesn't have read permission for.

In order for csh to be able to find commands in directories on the $path that it has no read permission on, you have to turn off the hashing function. You do that by running the builtin command unhash. Once you run that, the hash table function is turned off, and csh will fall back to just trying every directory in the search path to see if it can run the command out of it, just like bash does.

Another side effect of this hashing behavior is that, if you add executables to directories that are on the csh search path, csh won't know about it. So suppose you put emacs in /usr/local/bin (which is on your search path). Then you try to run emacs, and ... Command not found. To resolve this (without turning off hashing), you run rehash which tells csh to go and build a fresh set of hash tables, upon which it will pick up anything new that's been added.

2
  • Wow, what a great explanation, thanks!
    – Peter
    Commented Oct 20, 2020 at 21:59
  • Great answer - and all the more reason to dislike (t)csh ;)
    – tink
    Commented Oct 20, 2020 at 21:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .