From 9a1cef589abf01b61e22656f44c76441f4c50ffd Mon Sep 17 00:00:00 2001 From: Chris Marusich Date: Fri, 11 Mar 2022 00:20:12 -0800 Subject: [PATCH] environment: Prevent PS1 from clobbering output in 'check'. Fixes: . * guix/scripts/environment.scm (child-shell-environment) [shell-pipe] [shell-pipe-in, shell-pipe-out]: New local variables. [script]: Redirect the stdout of each command to the file descriptor of the shell-pipe-out port. [lines]: In the child, close shell-pipe-in before starting the shell. In the parent, close shell-pipe-out before sending the script to the shell. Read lines from shell-pipe-in, not port, so that the shell's PS1 prompt cannot clobber the lines. Close shell-pipe-in just before waiting on the child. --- guix/scripts/environment.scm | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index 3216235937..f0cb341aab 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -48,6 +48,7 @@ (define-module (guix scripts environment) #:autoload (gnu packages bash) (bash) #:autoload (gnu packages bootstrap) (bootstrap-executable %bootstrap-guile) #:use-module (ice-9 match) + #:use-module (ice-9 format) #:autoload (ice-9 rdelim) (read-line) #:use-module (ice-9 vlist) #:use-module (srfi srfi-1) @@ -418,11 +419,23 @@ (define (child-shell-environment shell profile manifest) (define-values (controller inferior) (openpty)) + (define shell-pipe (pipe)) + (define shell-pipe-in (car shell-pipe)) + (define shell-pipe-out (cdr shell-pipe)) + (define script - ;; Script to obtain the list of environment variable values. On a POSIX - ;; shell we can rely on 'set', but on fish we have to use 'env' (fish's - ;; 'set' truncates values and prints them in a different format.) - "env || /usr/bin/env || set; echo GUIX-CHECK-DONE; read x; exit\n") + ;; Script to obtain the list of environment variable values. + ;; + ;; On a POSIX shell we can rely on 'set', but on fish we have to use 'env' + ;; (fish's 'set' truncates values and prints them in a different format). + ;; + ;; Unless we redirect output to a dedicated file descriptor, there is a + ;; risk that the shell's PS1 prompt might clobber the output. See: + ;; https://issues.guix.gnu.org/53355 + (let ((out-fd (port->fdes shell-pipe-out))) + (format + #f "env 1>&~d || /usr/bin/env 1>&~d || set 1>&~d; \ +echo GUIX-CHECK-DONE 1>&~d; read x; exit\n" out-fd out-fd out-fd out-fd))) (define lines (match (primitive-fork) @@ -432,17 +445,22 @@ (define lines (load-profile profile manifest #:pure? #t) (setenv "GUIX_ENVIRONMENT" profile) (close-fdes controller) + (close-port shell-pipe-in) (login-tty inferior) (execl shell shell)) (lambda _ (primitive-exit 127)))) (pid (close-fdes inferior) + (close-port shell-pipe-out) (let* ((port (fdopen controller "r+l")) (result (begin (display script port) (let loop ((lines '())) - (match (read-line port) + ;; Read from our special port, not from the + ;; controller port, to prevent the shell's PS1 + ;; prompt from getting mixed into what we read. + (match (read-line shell-pipe-in) ((? eof-object?) (reverse lines)) ("GUIX-CHECK-DONE\r" (display "done\n" port) @@ -452,6 +470,7 @@ (define lines (loop (cons (string-drop-right line 1) lines)))))))) (close-port port) + (close-port shell-pipe-in) (waitpid pid) result)))) base-commit: adf5ae5a412ed13302186dd4ce8e2df783d4515d -- 2.34.0