1.0.12.37: RUN-PROGRAM now uses execvp(3) to search for executables
authorRichard M Kreuter <kreuter@users.sourceforge.net>
Wed, 19 Dec 2007 02:28:12 +0000 (02:28 +0000)
committerRichard M Kreuter <kreuter@users.sourceforge.net>
Wed, 19 Dec 2007 02:28:12 +0000 (02:28 +0000)
* RUN-PROGRAM now uses execvp(3) in the child, rather than a Lisp
  function in SBCL, to search for an executable to run.  This makes
  RUN-PROGRAM slightly closer to most other languages' process
  creation facilities.

* The function FIND-EXECUTABLE-IN-SEARCH-PATH has been removed.  A
  note is added to the manual pointing users who need the old,
  idiosyncratic search behavior to look for it it in the CVS history.

NEWS
doc/manual/beyond-ansi.texinfo
src/code/run-program.lisp
src/runtime/run-program.c
version.lisp-expr

diff --git a/NEWS b/NEWS
index 10f07f0..b8f07dc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,10 @@
 ;;;; -*- coding: utf-8; -*-
 changes in sbcl-1.0.13 relative to sbcl-1.0.12:
+  * minor incompatible change: RUN-PROGRAM now uses execvp(3) to find
+    an executable in the search path, and does so in the child
+    process's PATH.  The function FIND-EXECUTABLE-IN-SEARCH-PATH has
+    been removed; it can be found in the CVS history, for somebody who
+    needs that search behavior (see the manual).
   * minor incompatible change: compiler policy re. weakening type
     checks has changed: now type checks are weakened on if SAFETY < 2
     and SAFETY < SPEED.
index 2bb0ec6..dedf819 100644 (file)
@@ -249,16 +249,48 @@ between classes and proper names and between lists of the form
 @comment  node-name,  next,  previous,  up
 @section Support For Unix
 
+@menu
+* Command-line arguments::
+* Querying the process environment::
+* Running external programs::
+@end menu
+
+@node Command-line arguments
+@subsection Command-line arguments
+
 The UNIX command line can be read from the variable
-@code{sb-ext:*posix-argv*}. The UNIX environment can be queried with
-the @code{sb-ext:posix-getenv} function.
+@code{sb-ext:*posix-argv*}. 
+
+@node Querying the process environment
+@subsection Querying the process environment
+
+The UNIX environment can be queried with the
+@code{sb-ext:posix-getenv} function.
 
 @include fun-sb-ext-posix-getenv.texinfo
 
+@node Running external programs
+@subsection Running external programs
+
 External programs can be run with @code{sb-ext:run-program}.
+@footnote{In SBCL versions prior to 1.0.13, @code{sb-ext:run-program}
+searched for executables in a manner somewhat incompatible with other
+languages.  As of this version, SBCL uses the system library routine
+@code{execvp(3)}, and no longer contains the function,
+@code{find-executable-in-search-path}, which implemented the old
+search.  Users who need this function may find it
+in @file{run-program.lisp} versions 1.67 and earlier in SBCL's CVS
+repository here
+@url{http://sbcl.cvs.sourceforge.net/sbcl/sbcl/src/code/run-program.lisp?view=log}. However,
+we caution such users that this search routine finds executables that
+system library routines do not.}
 
 @include fun-sb-ext-run-program.texinfo
 
+When @code{sb-ext:run-program} is called with @code{wait} equal to
+NIL, an instance of class @var{sb-ext:process} is returned.  The
+following functions are available for use with processes:
+
 @include fun-sb-ext-process-p.texinfo
 
 @include fun-sb-ext-process-input.texinfo
index 1be271f..b1331de 100644 (file)
@@ -504,61 +504,19 @@ status slot."
               ,@body)
          (sb-sys:deallocate-system-memory ,sap ,size)))))
 
-#-win32
-(sb-alien:define-alien-routine ("spawn" %spawn) sb-alien:int
-  (program sb-alien:c-string)
-  (argv (* sb-alien:c-string))
-  (envp (* sb-alien:c-string))
-  (pty-name sb-alien:c-string)
-  (stdin sb-alien:int)
-  (stdout sb-alien:int)
-  (stderr sb-alien:int))
-
-#+win32
-(sb-alien:define-alien-routine ("spawn" %spawn) sb-win32::handle
+(sb-alien:define-alien-routine spawn
+    #-win32 sb-alien:int
+    #+win32 sb-win32::handle
   (program sb-alien:c-string)
   (argv (* sb-alien:c-string))
   (stdin sb-alien:int)
   (stdout sb-alien:int)
   (stderr sb-alien:int)
+  (search sb-alien:int)
+  (envp (* sb-alien:c-string))
+  (pty-name sb-alien:c-string)
   (wait sb-alien:int))
 
-(defun spawn (program argv stdin stdout stderr envp pty-name wait)
-  #+win32 (declare (ignore envp pty-name))
-  #+win32 (%spawn program argv stdin stdout stderr (if wait 1 0))
-  #-win32 (declare (ignore wait))
-  #-win32 (%spawn program argv envp pty-name stdin stdout stderr))
-
-;;; FIXME: why are we duplicating standard library stuff and not using
-;;; execvp(3)?  We can extend our internal spawn() routine to take a
-;;; flag to say whether to search...
-;;; Is UNIX-FILENAME the name of a file that we can execute?
-(defun unix-filename-is-executable-p (unix-filename)
-  (let ((filename (coerce unix-filename 'string)))
-    (values (and (eq (sb-unix:unix-file-kind filename) :file)
-                 #-win32
-                 (sb-unix:unix-access filename sb-unix:x_ok)))))
-
-(defun find-executable-in-search-path (pathname &optional
-                                       (search-path (posix-getenv "PATH")))
-  #+sb-doc
-  "Find the first executable file matching PATHNAME in any of the
-colon-separated list of pathnames SEARCH-PATH"
-  (let ((program #-win32 pathname
-                 #+win32 (merge-pathnames pathname (make-pathname :type "exe"))))
-   (loop for end =  (position #-win32 #\: #+win32 #\; search-path
-                              :start (if end (1+ end) 0))
-         and start = 0 then (and end (1+ end))
-         while start
-         ;; <Krystof> the truename of a file naming a directory is the
-         ;; directory, at least until pfdietz comes along and says why
-         ;; that's noncompliant  -- CSR, c. 2003-08-10
-         for truename = (probe-file (subseq search-path start end))
-         for fullpath = (when truename
-                          (unix-namestring (merge-pathnames program truename)))
-         when (and fullpath (unix-filename-is-executable-p fullpath))
-         return fullpath)))
-
 ;;; FIXME: There shouldn't be two semiredundant versions of the
 ;;; documentation. Since this is a public extension function, the
 ;;; documentation should be in the doc string. So all information from
@@ -659,9 +617,8 @@ Users Manual for details about the PROCESS structure."#-win32"
       an alternative lossy representation of the new Unix environment,
       for compatibility with CMU CL""
    :SEARCH
-      Look for PROGRAM in each of the directories along the $PATH
+      Look for PROGRAM in each of the directories in the child's $PATH
       environment variable.  Otherwise an absolute pathname is required.
-      (See also FIND-EXECUTABLE-IN-SEARCH-PATH)
    :WAIT
       If non-NIL (default), wait until the created process finishes.  If
       NIL, continue running Lisp until the program finishes."#-win32"
@@ -739,20 +696,15 @@ Users Manual for details about the PROCESS structure."#-win32"
           #-win32 *handlers-installed*
           ;; Establish PROC at this level so that we can return it.
           proc
-          ;; It's friendly to allow the caller to pass any string
-          ;; designator, but internally we'd like SIMPLE-STRINGs.
           (simple-args (simplify-args args))
-          ;; See the comment above about execlp(3).
-          (pfile (if search
-                     (find-executable-in-search-path program)
-                     (unix-namestring program)))
+          (progname (native-namestring program))
           ;; Gag.
           (cookie (list 0)))
-      (unless pfile
-        (error "no such program: ~S" program))
-      (unless (unix-filename-is-executable-p pfile)
-        (error "not executable: ~S" program))
       (unwind-protect
+           ;; Note: despite the WITH-* names, these macros don't
+           ;; expand into UNWIND-PROTECT forms.  They're just
+           ;; syntactic sugar to make the rest of the routine slightly
+           ;; easier to read.
            (macrolet ((with-fd-and-stream-for (((fd stream) which &rest args)
                                                &body body)
                         `(multiple-value-bind (,fd ,stream)
@@ -803,9 +755,11 @@ Users Manual for details about the PROCESS structure."#-win32"
                          (with-environment-vec (environment-vec environment)
                            (let ((child
                                   (without-gcing
-                                    (spawn pfile args-vec
+                                    (spawn progname args-vec
                                            stdin stdout stderr
-                                           environment-vec pty-name wait))))
+                                           (if search 1 0)
+                                           environment-vec pty-name
+                                           (if wait 1 0)))))
                              (when (minusp child)
                                (error "couldn't fork child process: ~A"
                                       (strerror)))
index 08feaa1..303b280 100644 (file)
@@ -54,8 +54,9 @@ int set_noecho(int fd)
     return 1;
 }
 
-int spawn(char *program, char *argv[], char *envp[], char *pty_name,
-          int stdin, int stdout, int stderr)
+extern char **environ;
+int spawn(char *program, char *argv[], int stdin, int stdout, int stderr,
+          int search, char *envp[], char *pty_name, int wait)
 {
     int pid = fork();
     int fd;
@@ -112,16 +113,14 @@ int spawn(char *program, char *argv[], char *envp[], char *pty_name,
         close(fd);
 #endif
 
+    environ = envp;
     /* Exec the program. */
-    execve(program, argv, envp);
+    if (search)
+      execvp(program, argv);
+    else
+      execv(program, argv);
 
-    /* It didn't work, so try /bin/sh. */
-    argv[0] = program;
-    argv[-1] = "sh";
-    execve("/bin/sh", argv-1, envp);
-
-    /* The exec didn't work, flame out. */
-    exit(1);
+    exit (1);
 }
 #else  /* !LISP_FEATURE_WIN32 */
 
@@ -149,6 +148,9 @@ HANDLE spawn (
     int in,
     int out,
     int err,
+    int search,
+    char *envp,
+    char *ptyname,
     int wait
     )
 {
@@ -187,7 +189,10 @@ HANDLE spawn (
     }
 
     /* Spawn process given on the command line*/
-    hProcess = (HANDLE) spawnvp ( wait_mode, program, argv );
+    if (search)
+      hProcess = (HANDLE) spawnvp ( wait_mode, program, argv );
+    else
+      hProcess = (HANDLE) spawnv ( wait_mode, program, argv );
 
     /* Now that the process is launched, replace the original
      * in/out/err handles and close the backups. */
index 17bce5f..b5bb713 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.12.36"
+"1.0.12.37"