Скачивание и установка
Автоматически
(ql:quickload "external-program")
Вручную
git clone --depth 1 https://github.com/sellout/external-program.git
(require :asdf)
(require :external-program)
API
(RUN program args &KEY input if-input-does-not-exist output if-output-exists error if-error-exists environment replace-environment-p) => result-code
Запускает заданную программу как внешний процесс, блокирует текущий лисп поток, и возвращает код завершения процесса.
INPUT, OUTPUT и ERROR ведут себя аналогичным образом, принимая одно из следующих значений:
| NIL | указывает для использования нулевой поток (например, /dev/null) |
| T | указывает, что внешний процесс должен использовать текущие для лиспа источники ввода/вывода |
| поток | |
| обозначение пути для перенаправления из/в файл | |
| :OUTPUT | (доступно только для ERROR) перенаправляет вывод ошибок в стандартный вывод |
ENVIRONMENT содержит alist с переменными и значениями.
REPLACE-ENVIRONMENT-P отображает, должен ли аргумент переданный как ENVIRONMENT заменить или расширить текущее окружение. По умолчанию NIL (расширить окружение).
(START program args &KEY input if-input-does-not-exist output if-output-exists error if-error-exists environment replace-environment-p status-hook) => process
START работает почти также, как и RUN, за исключением того, что процесс запускается в фоне, и функция немедленно возвращает объект класса PROCESS, который может использован для получения потоков ввода/вывода и статуса процесса.
Параметры отличаются следующим:
дополнительное значение для input, output и error:
| :STREAM | создает новый поток для символьного ввода или вывода (доступный через EXTERNAL-PROCESS-*-STREAM) |
STATUS-HOOK функция, которая вызывается системой при изменении статуса процесса. Функция получает процесс в качестве аргумента.
(PROCESS-P object)
Возвращает T, если объект является процессом, иначе NIL.
(SIGNAL-PROCESS process signal)
Посылает указанный unix сигнал данному внешнему процессу. Сигнализирует об ошибке в случае неудачи. Сигнал может быть целым или одним из keyword'ов из EXTERNAL-PROGRAM::*SIGNAL-MAPPING*.
alist EXTERNAL-PROGRAM::*SIGNAL-MAPPING*:
| :HANGUP | 1 |
| :INTERRUPT | 2 |
| :QUIT | 3 |
| :ILLEGAL-INSTRUCTION | 4 |
| :BREAKPOINT-TRAP | 5 |
| :ABORT | 6 |
| :EMULATION-TRAP | 7 |
| :ARITHMETIC-EXCEPTION | 8 |
| :KILLED | 9 |
| :BUS-ERROR | 10 |
| :SEGMENTATION-FAULT | 11 |
| :BAD-SYSTEM-CALL | 12 |
| :BROKEN-PIPE | 13 |
| :ALARM-CLOCK | 14 |
(PROCESS-ID process)
Возвращает идентификатор процесса назначенные ему операционной системой. Обычно это положительное 16-битное число.
(PROCESS-INPUT-STREAM process)
Возвращает поток, созданный, если аргумент input в START был указан как :STREAM.
(PROCESS-OUTPUT-STREAM process)
Возвращает поток, созданный, если аргумент output в START был указан как :STREAM.
(PROCESS-ERROR-STREAM process)
Возвращает поток, созданный, если аргумент error в START был указан как :STREAM.
(PROCESS-STATUS process)
Возвращает несколько значений, keyword указывающий статус внешнего процесса (один из :RUNNING, :STOPPED, :SIGNALED или :EXITED) и код завершения или сигнал прекращения процесса, если первое значение не :RUNNING
Пример
Запуск программы maxima и создание потоков для управления вводом/выводом внешнего процесса:
(defvar *p* (external-program:start "maxima" nil :input :stream :output :stream :error :stream))
Запись в stdin внешнего процесса:
(let ((*standard-output* (external-program:process-input-stream *p*)))
(write-line "2+2\n")
(finish-output))
Чтение из stdout внешнего процесса:
;; Вспомогательная функция
(defun read-all (&optional (input-stream *standard-input*))
"Read all data from stream"
(do ((output (make-array 0
:element-type 'character
:fill-pointer 0
:adjustable t)))
((not (listen input-stream)) output)
(vector-push-extend (read-char input-stream) output)))
;; Форма выполняющая чтение
(let ((*standard-input* (external-program:process-output-stream *p*)))
read-all)
Завершение процесса:
(external-program:signal-process *p* :QUIT)