1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
6 ;;;; Purpose: Operating System utilities
7 ;;;; Programmer: Kevin M. Rosenberg
8 ;;;; Date Started: Jul 2003
10 ;;;; *************************************************************************
14 (defun command-output (control-string &rest args)
15 "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and
16 synchronously execute the result using a Bourne-compatible shell,
17 returns (VALUES string-output error-output exit-status)"
18 (let ((command (apply #'format nil control-string args)))
20 (let* ((process (sb-ext:run-program
23 :input nil :output :stream :error :stream))
24 (output (read-stream-to-string (sb-impl::process-output process)))
25 (error (read-stream-to-string (sb-impl::process-error process))))
26 (close (sb-impl::process-output process))
27 (close (sb-impl::process-error process))
31 (sb-impl::process-exit-code process)))
35 (let* ((process (ext:run-program
38 :input nil :output :stream :error :stream))
39 (output (read-stream-to-string (ext::process-output process)))
40 (error (read-stream-to-string (ext::process-error process))))
41 (close (ext::process-output process))
42 (close (ext::process-error process))
47 (ext::process-exit-code process)))
50 (multiple-value-bind (output error status)
51 (excl.osi:command-output command :whole t)
52 (values output error status))
55 ;; BUG: Lispworks combines output and error streams
56 (let ((output (make-string-output-stream)))
59 (system:call-system-showing-output
63 :output-stream output)))
64 (values (get-output-stream-string output) nil status))
68 ;; BUG: CLisp doesn't allow output to user-specified stream
72 (ext:run-shell-command command :output :terminal :wait t))
75 (let* ((process (ccl:run-program
78 :input nil :output :stream :error :stream
80 (output (read-stream-to-string (ccl::external-process-output-stream process)))
81 (error (read-stream-to-string (ccl::external-process-error-stream process))))
82 (close (ccl::external-process-output-stream process))
83 (close (ccl::external-process-error-stream process))
86 (nth-value 1 (ccl::external-process-status process))))
88 #-(or openmcl clisp lispworks allegro scl cmu sbcl)
89 (error "COMMAND-OUTPUT not implemented for this Lisp")
93 (defun run-shell-command (control-string &rest args)
94 "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and
95 synchronously execute the result using a Bourne-compatible shell,
96 returns (VALUES output-string pid)"
97 (let ((command (apply #'format nil control-string args)))
99 (sb-impl::process-exit-code
103 :input nil :output nil))
106 (ext:process-exit-code
110 :input nil :output nil))
114 (excl:run-shell-command command :input nil :output nil
118 (system:call-system-showing-output
120 :shell-type "/bin/sh"
125 #+clisp ;XXX not exactly *verbose-out*, I know
126 (ext:run-shell-command command :output :terminal :wait t)
130 (ccl:external-process-status
131 (ccl:run-program "/bin/sh" (list "-c" command)
132 :input nil :output nil
135 #-(or openmcl clisp lispworks allegro scl cmu sbcl)
136 (error "RUN-SHELL-PROGRAM not implemented for this Lisp")
140 (defun delete-directory-and-files (dir &key (if-does-not-exist :error) (quiet t) force)
141 #+allegro (excl:delete-directory-and-files dir :if-does-not-exist if-does-not-exist
142 :quiet quiet :force force)
143 #-(or allegro) (declare (ignore force))
145 ((probe-directory dir)
146 (let ((cmd (format nil "rm -rf ~A" (namestring dir))))
148 (format *trace-output* ";; ~A" cmd))
149 (command-output cmd)))
150 ((eq if-does-not-exist :error)
151 (error "Directory ~A does not exist [delete-directory-and-files]." dir))))
153 (defun file-size (file)
154 (when (probe-file file)
155 #+allegro (let ((stat (excl.osi:stat (namestring file))))
156 (excl.osi:stat-size stat))
157 #+sbcl (sb-posix:stat-size (sb-posix:stat file))
159 (with-open-file (in file :direction :input)
163 "Return the PID of the lisp process."
164 #+allegro (excl::getpid)
165 #+(and lispworks win32) (win32:get-current-process-id)
166 #+(and lispworks (not win32)) (system::getpid)
167 #+sbcl (sb-posix:getpid)
168 #+cmu (unix:unix-getpid)
169 #+openmcl (ccl::getpid)
170 #+(and clisp unix) (system::process-id)
171 #+(and clisp win32) (cond ((find-package :win32)
172 (funcall (find-symbol "GetCurrentProcessId"
175 (system::getenv "PID")))