From: Olin Shivers <shivers@tokyo.cc.gatech.edu>
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: <k1wv9wqh9x.fsf@tokyo.cc.gatech.edu>
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
exec-path-list
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.
-Olin
Up |