From: Richard M K. <kr...@pr...> - 2007-12-03 17:49:09
|
Johann H=?UTF-8?Q?=C3=B6chtl?= writes: > > This is SBCL 1.0.9 on Windows > > I think this might be a bug (At least when with-output-to-string > should catch the output of what is write n to stdout into a stream) > > (with-output-to-string (o) > (or (sb-ext:run-program "tar" (list "-tzf C:\\p.tar.gz" nil) > :output o :search t :wait t) > (error "Failed") > ) > (princ o) > (terpri)) > > #<STRING-OUTPUT-STREAM {B1AF721}> > "" > > This should print the contents of the archive, but I guess nothing is > written to the buffer. > > Tried on the comand line with different programs (mem.exe) as well, > stream is always empty. While I don't have a Windows host to debug this, I'd hazard a guess that might help you get started, if you're inclined to: this is probably a problem with RUN-PROGRAM, rather than with WITH-OUTPUT-TO-STRING. In order to have the child process's output go to a Lisp stream other than an FD-STREAM, RUN-PROGRAM creates a pipe, arranges for the child's standard output to be the write end of the pipe, and copies all the data from the read end of the pipe into the Lisp stream by entering loop that calls select on the read end of pipe to ensure that the child doesn't block. Every detail of this story (piping, setting up a child's file descriptors, using select on file descriptors) uses different code on Windows than on Unix, and so could be faulty in ways that can only be detected tehre. (Under Unix, if I found this didn't work and needed a workaround, I might try to change the RUN-PROGRAM to call the system shell, redirecting the process's output to a file, and then read the file contents in. The following quick hack happens to work on Unix, but it will require changing for Windows: (defun run-program-for-output (program &rest args) (multiple-value-bind (fd output-filename) ;; There's no sb-posix:mkstemp on Windows, so find some other ;; way to make a fresh file (sb-posix::mkstemp ;sigh, mkstemp isn't exported. I'll fix this. "/tmp/run-program.XXXXXX") (sb-posix:close fd) ;; This uses the output redirection facility of the Unix shell. (run-program "/bin/sh" (list "-c" (format nil "~A ~{~A~^ ~} > ~A" program args output-filename)) :wait t) (let ((output-pathname (parse-native-namestring output-filename))) (prog1 (with-open-file (*standard-input* output-pathname) (with-output-to-string (*standard-output*) (loop for line = (read-line nil nil) while line do (write-line line)))) (delete-file output-pathname))))) I don't know whether Windows's shells can be used this way from other programs, but you could try that, if you need to proceed with whatever you're doing.) Hope that helps, RmK |