diff options
| author | Josselin Poiret <dev@jpoiret.xyz> | 2022-01-15 14:50:00 +0100 |
|---|---|---|
| committer | Mathieu Othacehe <othacehe@gnu.org> | 2022-02-02 16:46:43 +0100 |
| commit | 0b9fbbb4dd24f227c9a708561ba291f6169ad2e6 (patch) | |
| tree | 3cb7d304cf0653e8d7fbb72f4aa68ec65ab2e04f /gnu | |
| parent | c57ec6ed1ee5f2367833c3e11ae7074f114dbf02 (diff) | |
installer: Capture external commands output.
* gnu/installer/utils.scm (run-external-command-with-handler,
run-external-command-with-line-hooks): New variables.
(run-command): Use run-external-command-with-line-hooks.
Signed-off-by: Mathieu Othacehe <othacehe@gnu.org>
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/installer/utils.scm | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/gnu/installer/utils.scm b/gnu/installer/utils.scm index 1bff1e12290..66c41ac2a1a 100644 --- a/gnu/installer/utils.scm +++ b/gnu/installer/utils.scm | |||
| @@ -25,7 +25,9 @@ | |||
| 25 | #:use-module (srfi srfi-1) | 25 | #:use-module (srfi srfi-1) |
| 26 | #:use-module (srfi srfi-19) | 26 | #:use-module (srfi srfi-19) |
| 27 | #:use-module (srfi srfi-34) | 27 | #:use-module (srfi srfi-34) |
| 28 | #:use-module (ice-9 control) | ||
| 28 | #:use-module (ice-9 match) | 29 | #:use-module (ice-9 match) |
| 30 | #:use-module (ice-9 popen) | ||
| 29 | #:use-module (ice-9 rdelim) | 31 | #:use-module (ice-9 rdelim) |
| 30 | #:use-module (ice-9 regex) | 32 | #:use-module (ice-9 regex) |
| 31 | #:use-module (ice-9 format) | 33 | #:use-module (ice-9 format) |
| @@ -34,6 +36,8 @@ | |||
| 34 | read-all | 36 | read-all |
| 35 | nearest-exact-integer | 37 | nearest-exact-integer |
| 36 | read-percentage | 38 | read-percentage |
| 39 | run-external-command-with-handler | ||
| 40 | run-external-command-with-line-hooks | ||
| 37 | run-command | 41 | run-command |
| 38 | 42 | ||
| 39 | syslog-port | 43 | syslog-port |
| @@ -78,37 +82,91 @@ number. If no percentage is found, return #f" | |||
| 78 | (and result | 82 | (and result |
| 79 | (string->number (match:substring result 1))))) | 83 | (string->number (match:substring result 1))))) |
| 80 | 84 | ||
| 85 | (define* (run-external-command-with-handler handler command) | ||
| 86 | "Run command specified by the list COMMAND in a child with output handler | ||
| 87 | HANDLER. HANDLER is a procedure taking an input port, to which the command | ||
| 88 | will write its standard output and error. Returns the integer status value of | ||
| 89 | the child process as returned by waitpid." | ||
| 90 | (match-let (((input . output) (pipe))) | ||
| 91 | ;; Hack to work around Guile bug 52835 | ||
| 92 | (define dup-output (duplicate-port output "w")) | ||
| 93 | ;; Void pipe, but holds the pid for close-pipe. | ||
| 94 | (define dummy-pipe | ||
| 95 | (with-input-from-file "/dev/null" | ||
| 96 | (lambda () | ||
| 97 | (with-output-to-port output | ||
| 98 | (lambda () | ||
| 99 | (with-error-to-port dup-output | ||
| 100 | (lambda () | ||
| 101 | (apply open-pipe* (cons "" command))))))))) | ||
| 102 | (close-port output) | ||
| 103 | (close-port dup-output) | ||
| 104 | (handler input) | ||
| 105 | (close-port input) | ||
| 106 | (close-pipe dummy-pipe))) | ||
| 107 | |||
| 108 | (define (run-external-command-with-line-hooks line-hooks command) | ||
| 109 | "Run command specified by the list COMMAND in a child, processing each | ||
| 110 | output line with the procedures in LINE-HOOKS. Returns the integer status | ||
| 111 | value of the child process as returned by waitpid." | ||
| 112 | (define (handler input) | ||
| 113 | (and | ||
| 114 | (and=> (get-line input) | ||
| 115 | (lambda (line) | ||
| 116 | (if (eof-object? line) | ||
| 117 | #f | ||
| 118 | (begin (for-each (lambda (f) (f line)) | ||
| 119 | (append line-hooks | ||
| 120 | %default-installer-line-hooks)) | ||
| 121 | #t)))) | ||
| 122 | (handler input))) | ||
| 123 | (run-external-command-with-handler handler command)) | ||
| 124 | |||
| 81 | (define* (run-command command) | 125 | (define* (run-command command) |
| 82 | "Run COMMAND, a list of strings. Return true if COMMAND exited | 126 | "Run COMMAND, a list of strings. Return true if COMMAND exited |
| 83 | successfully, #f otherwise." | 127 | successfully, #f otherwise." |
| 84 | (define env (environ)) | ||
| 85 | |||
| 86 | (define (pause) | 128 | (define (pause) |
| 87 | (format #t (G_ "Press Enter to continue.~%")) | 129 | (format #t (G_ "Press Enter to continue.~%")) |
| 88 | (send-to-clients '(pause)) | 130 | (send-to-clients '(pause)) |
| 89 | (environ env) ;restore environment variables | ||
| 90 | (match (select (cons (current-input-port) (current-clients)) | 131 | (match (select (cons (current-input-port) (current-clients)) |
| 91 | '() '()) | 132 | '() '()) |
| 92 | (((port _ ...) _ _) | 133 | (((port _ ...) _ _) |
| 93 | (read-line port)))) | 134 | (read-line port)))) |
| 94 | 135 | ||
| 95 | (setenv "PATH" "/run/current-system/profile/bin") | 136 | (installer-log-line "running command ~s" command) |
| 96 | 137 | (define result (run-external-command-with-line-hooks | |
| 97 | (guard (c ((invoke-error? c) | 138 | (list %display-line-hook) |
| 98 | (newline) | 139 | command)) |
| 99 | (format (current-error-port) | 140 | (define exit-val (status:exit-val result)) |
| 100 | (G_ "Command failed with exit code ~a.~%") | 141 | (define term-sig (status:term-sig result)) |
| 101 | (invoke-error-exit-status c)) | 142 | (define stop-sig (status:stop-sig result)) |
| 102 | (installer-log-line "command ~s failed with exit code ~a" | 143 | (define succeeded? |
| 103 | command (invoke-error-exit-status c)) | 144 | (cond |
| 104 | (pause) | 145 | ((and exit-val (not (zero? exit-val))) |
| 105 | #f)) | 146 | (installer-log-line "command ~s exited with value ~a" |
| 106 | (installer-log-line "running command ~s" command) | 147 | command exit-val) |
| 107 | (apply invoke command) | 148 | (format #t (G_ "Command ~s exited with value ~a") |
| 108 | (installer-log-line "command ~s succeeded" command) | 149 | command exit-val) |
| 109 | (newline) | 150 | #f) |
| 110 | (pause) | 151 | (term-sig |
| 111 | #t)) | 152 | (installer-log-line "command ~s killed by signal ~a" |
| 153 | command term-sig) | ||
| 154 | (format #t (G_ "Command ~s killed by signal ~a") | ||
| 155 | command term-sig) | ||
| 156 | #f) | ||
| 157 | (stop-sig | ||
| 158 | (installer-log-line "command ~s stopped by signal ~a" | ||
| 159 | command stop-sig) | ||
| 160 | (format #t (G_ "Command ~s stopped by signal ~a") | ||
| 161 | command stop-sig) | ||
| 162 | #f) | ||
| 163 | (else | ||
| 164 | (installer-log-line "command ~s succeeded" command) | ||
| 165 | (format #t (G_ "Command ~s succeeded") command) | ||
| 166 | #t))) | ||
| 167 | (newline) | ||
| 168 | (pause) | ||
| 169 | succeeded?) | ||
| 112 | 170 | ||
| 113 | 171 | ||
| 114 | ;;; | 172 | ;;; |
