From 8739cafad9e3a7f9a6bcb9e971a508b2af178f48 Mon Sep 17 00:00:00 2001 From: Timothy Sample Date: Wed, 18 Jul 2018 23:42:13 -0400 Subject: [PATCH] Add subshell semantics * geesh/shell.scm (subshell): New public function. * tests/shell.scm: Test it. * .dir-locals.el: Indent it nicely. --- .dir-locals.el | 1 + geesh/shell.scm | 12 ++++++++++++ tests/shell.scm | 14 ++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/.dir-locals.el b/.dir-locals.el index aeaf6f2..638bf5b 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -9,4 +9,5 @@ (eval . (put ' 'scheme-indent-function 1)) (eval . (put 'call-with-backquoted-input-port 'scheme-indent-function 1)) (eval . (put 'make-script 'scheme-indent-function 1)) + (eval . (put 'sh:subshell 'scheme-indent-function 1)) (eval . (put 'sh:with-redirects 'scheme-indent-function 2))))) diff --git a/geesh/shell.scm b/geesh/shell.scm index 584b475..ea7978b 100644 --- a/geesh/shell.scm +++ b/geesh/shell.scm @@ -5,6 +5,7 @@ #:use-module (srfi srfi-26) #:export (sh:exec-let sh:exec + sh:subshell sh:with-redirects)) ;;; Commentary: @@ -149,3 +150,14 @@ filename used for the here-document contents." (lambda () (flush-all-ports) (for-each restore-saved-fdes! (reverse saved-fds)))))) + + +;;; Subshells. + +(define (sh:subshell env thunk) + "Run @var{thunk} in a subshell environment." + (match (primitive-fork) + (0 (thunk) + (primitive-exit)) + (pid (match-let (((pid . status) (waitpid pid))) + (set-var! env "?" (number->string (status:exit-val status))))))) diff --git a/tests/shell.scm b/tests/shell.scm index 9b949ab..141d13b 100644 --- a/tests/shell.scm +++ b/tests/shell.scm @@ -311,4 +311,18 @@ ;; TODO: Read-write tests, closing tests, clobbering tests. + +;;; Subshells. + +(test-equal "Subshells cannot change variables" + "foo" + (let ((env (make-environment '(("x" . "foo"))))) + (sh:subshell env + (lambda () + (set-var! env "x" "bar"))) + (var-ref env "x"))) + +;; TODO: Test other means of manipulating the environment and exit +;; statuses. + (test-end)