scheme shell
From: Olin Shivers <>
Newsgroups: comp.lang.scheme.scsh
Subject: directory search path for EXEC -- new design
Date: 11 Mar 2001 13:42:18 -0500
Organization: College of Computing, Georgia Tech
Message-ID: <>

A while back, a design problem surfaced with the exec-path system call in scsh. The call

(exec-path "ls" "-l" "/tmp")

causes scsh to search through an internal list of file directories for one containing file "ls". When it finds one, it execs this binary with the given arg vector. This is what happens when you say something like

(run (ls -l /tmp))

which expands into

(wait (fork (lambda () (exec-path "ls" "-l" "/tmp"))))

OK, from where does this list of directories to be searched come? It is the value of the global variable


which is initialised on startup to the contents of the $PATH env var:

    (set! exec-path-list
          (cond ((getenv "PATH") => split-colon-list)
                (else (if (not quietly?)
                          (warn "Starting up with no path ($PATH)."))

So it is typically something like

'("/bin" "/usr/bin" "/usr/local/bin")

Now... suppose you'd like to change that. Maybe you'd like to write a script that is insulated from $PATH, so nobody can mess with your search path. You put this as the first line in your script:

(set! exec-path-list '("/sbin" "/bin" "/usr/bin"))

Oops, in the current 0.5.2 release, you rapidly discover that exec-path-list is sitting inside another package, and you aren't allowed to set! it from the user package.

But even if you could, it would be wrong. Imagine a scsh server sitting on a host. People authenticate to the server and get a connection to a repl thread. You don't want my exec-path-list frobbing to interfere with your thread, right?

This is just a specific example of a general principle: global state bad.

The answer is to provide this bit of state as a fluid cell. Fluid cells are essentially cells whose contents are bound with dynamic scope, so threads can share them or not share them, as desired.

    (make-fluid init-value) => fluid				create
    (fluid fluid) => value					dereference
    (let-fluid fluid value thunk) => value(s) of thunk		bind
    (set-fluid! fluid value)  => undefined

I propose turning exec-path-list into a fluid. Your scripts (if they open the fluids package) can dereference it, rebind it, and side-effect it.

That means that any current code that references exec-path-list is going to break. But I don't expect there is any such code, since no one's been allowed to frob the variable.

Unfortunately, my archives of scsh posts are kind of a mess since I shifted my center of gravity from Cambridge to Atlanta, and dejanews is a mess, so I can't find the original reports & discussion. If anyone has these posts, could you send them to me? If anyone has a complete archive of comp.lang.scheme.scsh, I'd love to hear about that, too.

Any comments? I'm planning to put it into scsh, so now's a good time to speak up.