summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2022-07-13 17:14:20 +0200
committerLudovic Courtès <ludo@gnu.org>2022-07-14 01:05:34 +0200
commit8af749224fd69daee5b67295186c77becb1a4479 (patch)
tree3b6b15a2590565f8402366f17ec1d23438f8aef3
parent9e4cbb307665f061d6e8bc75660ae9421886f6b2 (diff)
downloadguix-8af749224fd69daee5b67295186c77becb1a4479.tar.gz
home: services: shells: Double-quote environment variable values.
Fixes <https://issues.guix.gnu.org/56540>.

Until now, environment variable values were emitted unquoted, producing
invalid shell code if the value contains spaces for example.

* gnu/home/services/shells.scm (serialize-posix-env-vars): Define
'shell-quote' procedure in staged code and use it for #$value.
* tests/guix-home.sh: Add test for PS1 variable with a value containing
spaces.
-rw-r--r--gnu/home/services/shells.scm34
-rw-r--r--tests/guix-home.sh3
2 files changed, 27 insertions, 10 deletions
diff --git a/gnu/home/services/shells.scm b/gnu/home/services/shells.scm
index 27190934f0..28d717f03d 100644
--- a/gnu/home/services/shells.scm
+++ b/gnu/home/services/shells.scm
@@ -111,16 +111,30 @@ service type can be extended with a list of file-like objects.")))
 
 (define (serialize-boolean field-name val) "")
 (define (serialize-posix-env-vars field-name val)
-  #~(string-append
-     #$@(map
-         (match-lambda
-           ((key . #f)
-            "")
-           ((key . #t)
-            #~(string-append "export " #$key "\n"))
-           ((key . value)
-            #~(string-append "export " #$key "=" #$value "\n")))
-         val)))
+  #~(let ((shell-quote
+           (lambda (value)
+             ;; Double-quote VALUE, leaving dollar sign as is.
+             (let ((quoted (list->string
+                            (string-fold-right
+                             (lambda (chr lst)
+                               (case chr
+                                 ((#\" #\\)
+                                  (append (list chr #\\) lst))
+                                 (else (cons chr lst))))
+                             '()
+                             value))))
+               (string-append "\"" quoted "\"")))))
+      (string-append
+       #$@(map
+           (match-lambda
+             ((key . #f)
+              "")
+             ((key . #t)
+              #~(string-append "export " #$key "\n"))
+             ((key . value)
+              #~(string-append "export " #$key "="
+                               (shell-quote #$value) "\n")))
+           val))))
 
 
 ;;;
diff --git a/tests/guix-home.sh b/tests/guix-home.sh
index 8a7048a9ca..a3c979530d 100644
--- a/tests/guix-home.sh
+++ b/tests/guix-home.sh
@@ -82,6 +82,8 @@ trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
    (simple-service 'home-bash-service-extension-test
                    home-bash-service-type
                    (home-bash-extension
+                    (environment-variables
+                      '(("PS1" . "$GUIX_ENVIRONMENT λ ")))
                     (bashrc
                      (list
                       (plain-file
@@ -138,6 +140,7 @@ EOF
 # dot-bashrc test file for guix home
 # the content of bashrc-test-config.sh"
     grep -q "the content of ~/.config/test.conf" "${HOME}/.config/test.conf"
+    grep '^export PS1="\$GUIX_ENVIRONMENT λ "$' "${HOME}/.bash_profile"
 
     # This one should still be here.
     grep "stay around" "$HOME/.config/random-file"