The Common Lisp Cookbook - Interfacing with your OS


The ANSI Common Lisp standard doesn't mention this topic. (Keep in mind that it was written at a time where Lisp Machines were at their peak. On these boxes Lisp was your operating system!) So almost everything that can be said here depends on your OS and your implementation.

Accessing Environment variables

Here's a function that'll allow you to look at Unix/Linux environment variables on a lot of different CL implementations:
* (defun my-getenv (name &optional default)
    (let ((x (assoc name ext:*environment-list*
                    :test #'string=)))
      (if x (cdr x) default))
     #+Allegro (sys:getenv name)
     #+CLISP (ext:getenv name)
     #+ECL (si:getenv name)
     #+SBCL (sb-unix::posix-getenv name)
     #+LISPWORKS (lispworks:environment-variable name)
* (my-getenv "HOME")
* (my-getenv "HOM")
* (my-getenv "HOM" "huh?")
You should also note that some of these implementations also provide the ability to set these variables. These include ECL (SI:SETENV) and AllegroCL, LispWorks, and CLISP where you can use the functions from above together with SETF. This feature might be important if you want to start subprocesses from your Lisp environment.

Accessing the command line arguments

Accessing command line arguments is implementation-specific but it appears most implementations have a way of getting at them. SBCL has the special variable *posix-argv*
 $ sbcl my-command-line-arg 


* *posix-argv*

("sbcl" "my-command-line-arg")
More on using this to write standalone Lisp scripts can be found in the SBCL Manual

LispWorks has system:*line-arguments-list*

CL-USER> system:*line-arguments-list*
("/Users/cbrown/Projects/lisptty/tty-lispworks" "-init" "/Users/cbrown/Desktop/lisp/lispworks-init.lisp")
CMUCL has interesting extensions for manipulating the arguments

Here's a quick function to return the argument strings list across multiple implementations:

(defun my-command-line ()
   #+SBCL *posix-argv*  
   #+LISPWORKS system:*line-arguments-list*
   #+CMU extensions:*command-line-words*

Forking with CMUCL

Here's a function by Martin Cracauer that'll allow you to compile a couple of files in parallel with CMUCL. It demonstrates how to use the UNIX fork system call with this CL implementation.
(defparameter *sigchld* 0)

(defparameter *compile-files-debug* 2)

(defun sigchld-handler (p1 p2 p3)
  (when (> 0 *compile-files-debug*)
    (print (list "returned" p1 p2 p3))
  (decf *sigchld*))

(defun compile-files (files &key (load nil))
  (setq *sigchld* 0)
  (system:enable-interrupt unix:sigchld #'sigchld-handler)
  (do ((f files (cdr f)))
      ((not f))
    (format t "~&process ~d diving for ~a" (unix:unix-getpid)
	    `(compile-file ,(car f)))
    (let ((pid (unix:unix-fork)))
      (if (/= 0 pid)
	  ;; parent
	  (incf *sigchld*)
	;; child
	  (compile-file (car f) :verbose nil :print nil)
	  (unix:unix-exit 0)))))
  (do () ((= 0 *sigchld*))
    (sleep 1)
    (when (> 0 *compile-files-debug*)
      (format t "~&process ~d still waiting for ~d childs"
	      (unix:unix-getpid) *sigchld*)))
  (when (> 0 *compile-files-debug*)
    (format t "~&finished"))
  (when load
    (do ((f files (cdr f)))
	((not f))
      (load (compile-file-pathname (car f))))))

Copyright © 2002-2007 The Common Lisp Cookbook Project

$Header: /cvsroot/cl-cookbook/cl-cookbook/os.html,v 1.10 2007/01/28 10:14:10 skeptomai Exp $