On 27 March 2012 19:41, Ville Voutilainen ville.voutilainen@gmail.com wrote:
On 27 March 2012 16:42, Pascal J. Bourguignon pjb@informatimago.com wrote:
I like the following API, which is implemented in clisp. (getenv) --> the current environment as an a-list. (("LC_CTYPE" . "C") ("TERM" . "/bin/bash") …) (getenv "TERM") --> the string value, or NIL if the variable is not present in the environment. "/bin/bash" (setf (getenv "LC_CTYPE") "en_US.UTF-8") changes the environment for the current process and its future children. (setf (getenv "LC_CTYPE") nil)
I dcn't think we can get that far. Java doesn't seem to support environment modifications that way, see http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#getenv%28... and in particular "Returns an unmodifiable string map view of the current system environment." Note the "unmodifiable".
We could allow setting the environment for run-program. Here's what I'd do:
- fix the documentation of run-program to mention the environment merging
- add a new function that can completely replace the default
environment for the program to run, use an alist or a hash. Also add a function that can return the full environment, for cases where you don't want to rebuild everything.
Comments? Opinions?
Here's a tentative patch. I opted for a new keyword argument, since the new function approach would've led to duplication or to a macro that has the new argument anyway. Untested so far, so this is for general review. Also lacking the docstring changes.
Index: src/org/armedbear/lisp/run-program.lisp =================================================================== --- src/org/armedbear/lisp/run-program.lisp (revision 13893) +++ src/org/armedbear/lisp/run-program.lisp (working copy) @@ -40,11 +40,13 @@ ;;; This implementation uses the JVM facilities for running external ;;; processes. ;;; http://download.oracle.com/javase/6/docs/api/java/lang/ProcessBuilder.html. -(defun run-program (program args &key environment (wait t)) +(defun run-program (program args &key environment (wait t) clear-env) ;;For documentation, see below. (let ((pb (%make-process-builder program args))) (when environment (let ((env-map (%process-builder-environment pb))) + (when clear-env + (%process-builder-env-clear env-map)) (dolist (entry environment) (%process-builder-env-put env-map (princ-to-string (car entry)) @@ -131,6 +133,9 @@ (defun %process-builder-env-put (env-map key value) (java:jcall "put" env-map key value))
+(defun %process-builder-env-clear (env-map) + (java:jcall "clear" env-map)) + (defun %process-builder-start (pb) (java:jcall "start" pb))
Index: src/org/armedbear/lisp/Extensions.java =================================================================== --- src/org/armedbear/lisp/Extensions.java (revision 13893) +++ src/org/armedbear/lisp/Extensions.java (working copy) @@ -37,6 +37,7 @@
import java.io.File; import java.io.IOException; +import java.util.*;
public final class Extensions { @@ -317,4 +318,28 @@ return NIL; } } + + // ### getenv variable => string + private static final Primitive GETENV_ALL = new getenv_all(); + private static class getenv_all extends Primitive + { + getenv_all() + { + super("getenv-all", PACKAGE_EXT, true, "variable", + "Returns all environment variables as an alist containing (name . value)"); + } + @Override + public LispObject execute() + { + Cons result = new Cons(NIL); + Map<String, String> env = System.getenv(); + for (Map.Entry<String, String> entry : env.entrySet()) { + Cons entryPair = new Cons(new SimpleString(entry.getKey()), + new SimpleString(entry.getValue())); + result = new Cons(entryPair, result); + } + return result; + } + } + }