All Manuals > LispWorks® User Guide and Reference Manual > 47 The SYSTEM Package

open-pipe Function

Summary

Runs an executable or shell command in a subshell.

Package

system

Signature

open-pipe command &key direction element-type interrupt-off shell-type use-pty save-exit-status external-format => stream

Arguments
command
A string, a list of strings, a simple-vector of strings, or nil.
direction
:input, :output, :io or :none.
element-type
A type specifier.
interrupt-off
A boolean. Not implemented on Microsoft Windows.
shell-type
A shell type.
use-pty
A boolean.
save-exit-status
A boolean.
external-format
An external file format designator. Defaults to :default. New in LispWorks 8.0.
Values
stream
A pipe stream.
Description

The function open-pipe runs an executable or shell command with its input and/or output connected to a stream.

On non-Windows platforms the behavior of open-pipe is analogous to that of popen in the POSIX C library. It creates a pipe to/from a subprocess and returns a stream. The stream can be read from or written to as appropriate.

On Microsoft Windows open-pipe calls CreateProcess and CreatePipe and returns a bidirectional stream.

command is interpreted as by call-system-showing-output.

direction is a keyword for the stream direction. The default value is :input. Bidirectional (I/O) pipes may be created by passing :io. See the example below. direction can also be :none, which means no input and no output like call-system, but is useful when you want to use pipe-exit-status and pipe-kill-process. On Windows it is not possible to open a unidirectional pipe, so :input and :output both have the same effect as :io.

When save-exit-status is non-nil, the status of the child process that open-pipe creates is tracked, so pipe-exit-status and pipe-kill-process can be used reliably. The default value of save-exit-status is nil.

external-format specifies the external format to use if it is not :default. See 26.6 External Formats to translate Lisp characters from/to external encodings for a description of external formats.

On non-Windows platforms, if external-format is :default and element-type is also :default (the defaults), then LispWorks tries to determine the external format to use using the POSIX environment variables LC_ALL, LC_CTYPE and LANG (in that order). If external-format is :default and element-type is not :default or it fails to find a known external format, open-pipe creates a stream that does not use an external format.

On Windows if external-format is :default it does not use external format.

Note that external-format is new in LispWorks 8.0. In previous versions, open-pipe never used an external format.

element-type specifies the type of the stream as with open. It defaults to :default, which causes open-pipe to choose the appropriate element-type for external-format, as determined by ef:external-format-type. If there is no external format, it chooses base-char.

interrupt-off, if t, ensures that Ctrl+C (SIGINT) to the LispWorks image is ignored by the subprocess. This argument is not implemented on Microsoft Windows.

shell-type specifies the type of shell to run. On Unix-like systems the default value is "/bin/sh". On Microsoft Windows the default value is "cmd".

use-pty is useful on Unix-like systems if the sub-process behaves differently when running interactively and non-interactively. When use-pty is non-nil, the input and output of the sub-process are opened using PTY (Pseudo-pty). That means that the sub-process sees its input and output as if they come from an interactive terminal. The PTY also processes special characters such as Ctrl-C the same way that an ordinary TTY does.

use-pty is probably not useful on Microsoft Windows as there is no concept corresponding to the Unix behavior. If use-pty is non-nil then it uses the CREATE_NEW_PROCESS_GROUP flag when creating the child, but it is not obvious when this might be useful.

stream supports mixed character and binary I/O in the same way as file streams constructed by open.

Notes: Compatibility Note

When open-pipe is called on non-Windows platforms and neither of external-format or element-type are supplied, then it may choose an external format based on environment variables hence and behave differently from previous versions, and also between different environments. If the data that is passed in the pipe conforms to the external format specified by the environment variables, for example it is the output of standard Unix utilities, that is the useful behavior. Otherwise, you should supply the required external-format or element-type to control it. If you use sys:open-pipe in previous versions of LispWorks without supplying element-type and you want it to continue to not process the data using an external-format, then supply element-type with base-char if you want code to work on all versions of LispWorks.

Examples

Example on Unix:

CL-USER 1 > (setf *ls* (sys:open-pipe "ls"))
Warning: Setting unbound variable *LS*
#<SYSTEM::PIPE-STREAM "ls">
 
CL-USER 2 > (loop while 
                  (print (read-line *ls* nil nil)))
 
"hello" 
"othello" 
NIL 
NIL
 
CL-USER 3 > (close *ls*)
T

The following example shows you how to use bidirectional pipes.

CL-USER 1 >  (with-open-stream
                   (s (sys:open-pipe "/bin/csh"
                                     :direction :io))
                 (write-line "whereis ls" s) 
                 (force-output s)
                 (read-line s))
"ls: /sbin/ls /usr/bin/ls /usr/share/man/man1.Z/ls.1"
NIL

Example on Microsoft Windows:

CL-USER 40 > (setf *ls* (sys:open-pipe "dir"))
#<WIN32::TWO-WAY-PIPE-STREAM 205F03F4>
 
CL-USER 41 > (loop while 
                   (print (read-line *ls* nil nil)))
 
" Volume in drive Z is lispsrc" 
" Volume Serial Number is 82E3-1342" 
"" 
" Directory of Z:\\v42\\delivery-tests" 
"" 
"20/02/02  11:57a        <DIR>          ." 
"20/02/02  11:57a        <DIR>          .." 
"14/02/02  07:04p             6,815,772 othello.exe" 
"14/02/02  07:07p             6,553,628 hello.exe" 
"               4 File(s)     13,369,400 bytes" 
"                          3,974,103,040 bytes free" 
NIL 
NIL
 
CL-USER 42 > (close *ls*)
T

This last example illustrates the use of save-exit-status. This form runs LispWorks as a subprocess such that it quits immediately with exit status 1623:

(setq *sub*
      (sys:open-pipe 
       (list (lisp-image-name)
             "-eval"
             "(quit :status 1623)") 
       :save-exit-status t))

This form then returns 1623:

(sys:pipe-exit-status *sub*)
See also

call-system
call-system-showing-output
pipe-exit-status
pipe-kill-process
pipe-close-connection


LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:31:02