2019-05-20 14:52:22 +01:00
|
|
|
|
;;; Gash -- Guile As SHell
|
2020-03-22 15:57:17 +00:00
|
|
|
|
;;; Copyright © 2018, 2019, 2020 Timothy Sample <samplet@ngyro.com>
|
2019-05-20 14:52:22 +01:00
|
|
|
|
;;;
|
|
|
|
|
;;; This file is part of Gash.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Gash is free software: you can redistribute it and/or modify
|
|
|
|
|
;;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;;; (at your option) any later version.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Gash is distributed in the hope that it will be useful,
|
|
|
|
|
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;;; GNU General Public License for more details.
|
|
|
|
|
;;;
|
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;;; along with Gash. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
Remove (almost) all references to Geesh.
gash/environment.scm: Remove file.
geesh/*: Move these files into the 'gash' folder and replace all
instances of the word 'geesh'.
scripts/geesh.in: Remove file.
HACKING, INSTALL, Makefile.am, configure.ac, guix.scm,
tests/bootstrap/bash-without-bash.scm, tests/spec/Makefile.am,
tests/spec/check-spec, tests/spec/oil.scm, tests/unit/*,
tools/coverage.in: Replace all instances of the word 'geesh'.
Co-authored-by: Jan Nieuwenhuizen <janneke@gnu.org>
2019-02-15 00:55:07 +00:00
|
|
|
|
(define-module (gash shell)
|
|
|
|
|
#:use-module (gash built-ins)
|
2019-08-03 01:19:52 +01:00
|
|
|
|
#:use-module (gash compat)
|
2019-05-20 00:42:48 +01:00
|
|
|
|
#:use-module (gash compat textual-ports)
|
Remove (almost) all references to Geesh.
gash/environment.scm: Remove file.
geesh/*: Move these files into the 'gash' folder and replace all
instances of the word 'geesh'.
scripts/geesh.in: Remove file.
HACKING, INSTALL, Makefile.am, configure.ac, guix.scm,
tests/bootstrap/bash-without-bash.scm, tests/spec/Makefile.am,
tests/spec/check-spec, tests/spec/oil.scm, tests/unit/*,
tools/coverage.in: Replace all instances of the word 'geesh'.
Co-authored-by: Jan Nieuwenhuizen <janneke@gnu.org>
2019-02-15 00:55:07 +00:00
|
|
|
|
#:use-module (gash environment)
|
|
|
|
|
#:use-module (gash pattern)
|
2018-07-17 03:33:03 +01:00
|
|
|
|
#:use-module (ice-9 match)
|
2018-10-15 14:43:19 +01:00
|
|
|
|
#:use-module (srfi srfi-1)
|
2018-07-19 04:41:10 +01:00
|
|
|
|
#:use-module (srfi srfi-26)
|
2018-10-16 19:14:15 +01:00
|
|
|
|
#:export (sh:and
|
2020-03-17 20:54:01 +00:00
|
|
|
|
sh:async
|
2018-11-21 16:37:05 +00:00
|
|
|
|
sh:case
|
|
|
|
|
sh:cond
|
2018-10-16 19:14:15 +01:00
|
|
|
|
sh:exec-let
|
2018-07-19 04:41:10 +01:00
|
|
|
|
sh:exec
|
2018-10-16 20:26:40 +01:00
|
|
|
|
sh:for
|
2018-10-16 19:14:15 +01:00
|
|
|
|
sh:not
|
|
|
|
|
sh:or
|
2018-10-16 18:48:52 +01:00
|
|
|
|
sh:pipeline
|
2018-11-15 19:18:16 +00:00
|
|
|
|
sh:set-redirects
|
2018-07-19 04:42:13 +01:00
|
|
|
|
sh:subshell
|
2018-07-19 04:44:04 +01:00
|
|
|
|
sh:substitute-command
|
2018-11-21 16:04:02 +00:00
|
|
|
|
sh:while
|
|
|
|
|
sh:with-redirects
|
|
|
|
|
sh:until))
|
2018-07-17 03:33:03 +01:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
;;;
|
|
|
|
|
;;; This module provides functions for executing Shell language
|
|
|
|
|
;;; constructs.
|
|
|
|
|
;;;
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(define ignore-errexit? (make-parameter #f))
|
|
|
|
|
|
|
|
|
|
(define (without-errexit thunk)
|
|
|
|
|
(parameterize ((ignore-errexit? #t)) (thunk)))
|
|
|
|
|
|
|
|
|
|
(define (errexit)
|
|
|
|
|
(unless (or (zero? (get-status)) (ignore-errexit?))
|
|
|
|
|
(when (getopt 'errexit)
|
2019-06-08 00:39:03 +01:00
|
|
|
|
(sh:exit))))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
|
2018-10-15 14:43:19 +01:00
|
|
|
|
(define (install-current-ports!)
|
|
|
|
|
"Install all current ports into their usual file descriptors. For
|
|
|
|
|
example, if @code{current-input-port} is a @code{file-port?}, make the
|
|
|
|
|
process file descriptor 0 refer to the file open for
|
|
|
|
|
@code{current-input-port}. If any current port is a @code{port?} but
|
|
|
|
|
not a @code{file-port?}, its corresponding file descriptor will refer
|
|
|
|
|
to @file{/dev/null}."
|
|
|
|
|
;; XXX: Input/output ports? Closing other FDs?
|
|
|
|
|
(for-each (lambda (i)
|
|
|
|
|
(match ((fd->current-port i))
|
|
|
|
|
((? file-port? port)
|
|
|
|
|
(dup port i))
|
|
|
|
|
((? input-port? port)
|
|
|
|
|
(dup (open-file "/dev/null" "r") i))
|
|
|
|
|
((? output-port? port)
|
|
|
|
|
(dup (open-file "/dev/null" "w") i))
|
|
|
|
|
(_ #t)))
|
|
|
|
|
(iota *fd-count*)))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (exec-utility bindings path name args)
|
|
|
|
|
"Execute @var{path} as a subprocess with extra environment variables
|
|
|
|
|
@var{bindings}. The first argument given to the new process will be
|
|
|
|
|
@var{name}, and the rest of the arguments will be @var{args}."
|
|
|
|
|
(let ((utility-env (get-environ bindings)))
|
2018-11-15 16:07:45 +00:00
|
|
|
|
;; We need to flush all ports here to ensure the proper sequence
|
|
|
|
|
;; of output. Without flushing, output that we have written could
|
|
|
|
|
;; stay in a buffer while the utility (which does not know about
|
|
|
|
|
;; the buffer) produces its output.
|
|
|
|
|
(flush-all-ports)
|
2018-07-17 03:33:03 +01:00
|
|
|
|
(match (primitive-fork)
|
2018-10-15 14:43:19 +01:00
|
|
|
|
(0 (install-current-ports!)
|
|
|
|
|
(apply execle path utility-env name args))
|
2018-07-17 03:33:03 +01:00
|
|
|
|
(pid (match-let (((pid . status) (waitpid pid)))
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(set-status! (status:exit-val status)))))))
|
2018-07-17 03:33:03 +01:00
|
|
|
|
|
2018-07-19 04:37:21 +01:00
|
|
|
|
(define (slashless? s)
|
|
|
|
|
"Test if the string @var{s} does not contain any slashes ('/')."
|
|
|
|
|
(not (string-index s #\/)))
|
|
|
|
|
|
|
|
|
|
(define (split-search-path s)
|
|
|
|
|
"Split the search path string @var{s}."
|
|
|
|
|
(if (string-null? s) '() (string-split s #\:)))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (find-utility name)
|
|
|
|
|
"Search for the path of the utility @var{name} using the current
|
|
|
|
|
search path as specified by the environment variable @code{$PATH}. If
|
2018-07-19 04:37:21 +01:00
|
|
|
|
it cannot be found, return @code{#f}."
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(let loop ((prefixes (split-search-path (getvar "PATH" ""))))
|
2018-07-19 04:37:21 +01:00
|
|
|
|
(and (pair? prefixes)
|
|
|
|
|
(let* ((prefix (car prefixes))
|
|
|
|
|
(path (if (string-suffix? "/" prefix)
|
|
|
|
|
(string-append prefix name)
|
|
|
|
|
(string-append prefix "/" name))))
|
|
|
|
|
(if (access? path X_OK)
|
|
|
|
|
path
|
|
|
|
|
(loop (cdr prefixes)))))))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:exec-let bindings name . args)
|
|
|
|
|
"Find and execute @var{name} with arguments @var{args} and extra
|
|
|
|
|
environment variable bindings @var{bindings}."
|
2018-12-31 16:12:13 +00:00
|
|
|
|
(when (getopt 'xtrace)
|
|
|
|
|
(format (current-error-port) "+~a\n"
|
|
|
|
|
(string-join (cons name
|
|
|
|
|
(map (lambda (x)
|
|
|
|
|
(if (string-null? x) "''"
|
|
|
|
|
x)) args)))))
|
2018-07-19 04:37:21 +01:00
|
|
|
|
(if (slashless? name)
|
2018-07-17 16:20:06 +01:00
|
|
|
|
(or (and=> (search-special-built-ins name)
|
|
|
|
|
(lambda (proc)
|
|
|
|
|
(for-each (match-lambda
|
|
|
|
|
((name . value)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(setvar! name value)))
|
2018-07-17 16:20:06 +01:00
|
|
|
|
bindings)
|
2019-11-27 01:50:45 +00:00
|
|
|
|
(set-status! (apply proc args))))
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(and=> (getfun name)
|
2018-11-09 03:18:32 +00:00
|
|
|
|
(lambda (proc)
|
2019-08-27 14:16:23 +01:00
|
|
|
|
(save-variables-excursion (map car bindings)
|
2018-11-09 03:18:32 +00:00
|
|
|
|
(lambda ()
|
2019-08-27 14:16:23 +01:00
|
|
|
|
(for-each (match-lambda
|
|
|
|
|
((name . value)
|
|
|
|
|
(setvar! name value)))
|
|
|
|
|
bindings)
|
|
|
|
|
(with-arguments (cons (car (program-arguments)) args)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(call-with-return
|
|
|
|
|
(lambda ()
|
|
|
|
|
(apply proc args)))))))))
|
2018-07-17 16:20:06 +01:00
|
|
|
|
(and=> (search-built-ins name)
|
|
|
|
|
(lambda (proc)
|
2019-10-22 04:30:44 +01:00
|
|
|
|
(save-variables-excursion (map car bindings)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(for-each (match-lambda
|
|
|
|
|
((name . value)
|
|
|
|
|
(setvar! name value)))
|
|
|
|
|
bindings)
|
|
|
|
|
(let ((exit-val (apply proc args)))
|
|
|
|
|
(set-status! exit-val))))))
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(and=> (find-utility name)
|
2018-07-19 04:37:21 +01:00
|
|
|
|
(lambda (path)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(exec-utility bindings path name args)))
|
2018-11-26 00:57:01 +00:00
|
|
|
|
(begin (format (current-error-port)
|
|
|
|
|
"~a: ~a: Command not found.~%"
|
|
|
|
|
(car (program-arguments)) name)
|
|
|
|
|
(set-status! 127)))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(exec-utility bindings name name args))
|
|
|
|
|
(errexit))
|
2018-07-17 03:33:03 +01:00
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:exec name . args)
|
|
|
|
|
"Find and execute @var{name} with arguments @var{args}."
|
|
|
|
|
(apply sh:exec-let '() name args))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Redirects.
|
|
|
|
|
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(define (process-redir redir)
|
|
|
|
|
"Convert @var{redir} into a list consisting of the current-port
|
|
|
|
|
parameter to be updated, the port that should be its new value (or
|
|
|
|
|
@code{#f} if it should be considered closed), and a boolean indicating
|
|
|
|
|
if it is our responsibility to close the port."
|
2018-11-15 18:32:39 +00:00
|
|
|
|
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(define* (make-processed-redir fd target #:optional (open-flags 0))
|
2018-11-15 18:32:39 +00:00
|
|
|
|
(let ((port (match target
|
|
|
|
|
((? port?) target)
|
|
|
|
|
((? string?) (open target open-flags))
|
|
|
|
|
;; TODO: Verify open-flags.
|
|
|
|
|
((? integer?) ((fd->current-port target)))
|
|
|
|
|
(#f #f))))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
`(,(fd->current-port fd) ,port ,(string? target))))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
|
|
|
|
|
(match redir
|
|
|
|
|
(('< (? integer? fd) (? string? filename))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd filename O_RDONLY))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('> (? integer? fd) (? string? filename))
|
2020-03-22 15:57:17 +00:00
|
|
|
|
(let* ((clobber-flags (logior O_WRONLY O_CREAT O_TRUNC))
|
|
|
|
|
(flags (if (getopt 'noclobber)
|
|
|
|
|
(logior clobber-flags O_EXCL)
|
|
|
|
|
clobber-flags)))
|
|
|
|
|
(make-processed-redir fd filename flags)))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('>! (? integer? fd) (? string? filename))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd filename (logior O_WRONLY O_CREAT O_TRUNC)))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('>> fd filename)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd filename (logior O_WRONLY O_CREAT O_APPEND)))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('<> fd filename)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd filename (logior O_RDWR O_CREAT)))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('<& (? integer? fd1) (? integer? fd2))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd1 fd2))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('<& (? integer? fd) '-)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd #f))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('>& (? integer? fd1) (? integer? fd2))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd1 fd2))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('>& (? integer? fd) '-)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd #f))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(('<< (? integer? fd) text)
|
2018-10-15 14:43:19 +01:00
|
|
|
|
(let ((port (tmpfile)))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
(display text port)
|
|
|
|
|
(seek port 0 SEEK_SET)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(make-processed-redir fd port)))))
|
2018-07-19 04:41:10 +01:00
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:set-redirects redirs)
|
2018-11-15 19:18:16 +00:00
|
|
|
|
"Put the redirects @var{redirs} into effect."
|
|
|
|
|
(let loop ((redirs redirs))
|
|
|
|
|
(match redirs
|
|
|
|
|
(() #t)
|
|
|
|
|
((redir . rest)
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(match (false-if-exception (process-redir redir))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(#f (set-status! 1)
|
|
|
|
|
(errexit))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
((parameter port close?)
|
2018-11-15 19:18:16 +00:00
|
|
|
|
(parameter port)
|
|
|
|
|
(loop rest)))))))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:with-redirects redirs thunk)
|
2018-07-19 04:41:10 +01:00
|
|
|
|
"Call @var{thunk} with the redirects @var{redirs} in effect."
|
2018-11-15 18:32:39 +00:00
|
|
|
|
;; This may be too clever! We need to parameterize a variable
|
|
|
|
|
;; number of things in a particular order, and this seems to be the
|
|
|
|
|
;; only way.
|
|
|
|
|
((fold-right (lambda (redir thunk)
|
|
|
|
|
(lambda ()
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(match (false-if-exception (process-redir redir))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(#f (set-status! 1)
|
|
|
|
|
(errexit))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
((parameter port close?)
|
2018-11-15 18:32:39 +00:00
|
|
|
|
(parameterize ((parameter port))
|
|
|
|
|
(thunk))
|
2019-12-02 16:05:49 +00:00
|
|
|
|
(cond
|
|
|
|
|
(close? (close-port port))
|
|
|
|
|
((output-port? port) (force-output port)))))))
|
2018-11-15 18:32:39 +00:00
|
|
|
|
thunk
|
|
|
|
|
redirs)))
|
2018-07-19 04:42:13 +01:00
|
|
|
|
|
|
|
|
|
|
2018-07-19 04:44:04 +01:00
|
|
|
|
;;; Subshells and command substitution.
|
2018-07-19 04:42:13 +01:00
|
|
|
|
|
2018-07-19 04:44:04 +01:00
|
|
|
|
(define* (%subshell thunk)
|
|
|
|
|
"Run @var{thunk} in a new process and return the ID of the new
|
|
|
|
|
process."
|
2018-11-15 16:07:45 +00:00
|
|
|
|
;; We need to flush all ports before forking to avoid copying the
|
|
|
|
|
;; port buffers into the child process, which could lead to
|
|
|
|
|
;; duplicate output.
|
|
|
|
|
(flush-all-ports)
|
2018-07-19 04:42:13 +01:00
|
|
|
|
(match (primitive-fork)
|
2019-06-08 01:13:17 +01:00
|
|
|
|
(0 (dynamic-wind
|
|
|
|
|
(lambda () #t)
|
|
|
|
|
(lambda ()
|
|
|
|
|
(restore-signals)
|
|
|
|
|
(set-atexit! #f)
|
|
|
|
|
;; We need to preserve the status given to 'exit', so we
|
|
|
|
|
;; catch the 'quit' key here.
|
|
|
|
|
(catch 'quit
|
|
|
|
|
thunk
|
|
|
|
|
(lambda (_ status)
|
|
|
|
|
(primitive-exit status)))
|
|
|
|
|
(primitive-exit (get-status)))
|
|
|
|
|
(lambda ()
|
|
|
|
|
(primitive-exit 1))))
|
2018-07-19 04:44:04 +01:00
|
|
|
|
(pid pid)))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:subshell thunk)
|
2018-07-19 04:44:04 +01:00
|
|
|
|
"Run @var{thunk} in a subshell environment."
|
|
|
|
|
(match-let* ((pid (%subshell thunk))
|
|
|
|
|
((pid . status) (waitpid pid)))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(set-status! (status:exit-val status))
|
|
|
|
|
(errexit)))
|
2018-07-19 04:44:04 +01:00
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:substitute-command thunk)
|
2018-07-19 04:44:04 +01:00
|
|
|
|
"Run @var{thunk} in a subshell environment and return its output as
|
|
|
|
|
a string."
|
|
|
|
|
(match-let* (((sink . source) (pipe))
|
|
|
|
|
(thunk* (lambda ()
|
|
|
|
|
(close-port sink)
|
2018-11-15 18:40:58 +00:00
|
|
|
|
(with-output-to-port source thunk)))
|
2018-07-19 04:44:04 +01:00
|
|
|
|
(pid (%subshell thunk*)))
|
|
|
|
|
(close-port source)
|
|
|
|
|
(match-let ((result (string-trim-right (get-string-all sink) #\newline))
|
|
|
|
|
((pid . status) (waitpid pid)))
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(set-status! (status:exit-val status))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(errexit)
|
2018-07-19 04:44:04 +01:00
|
|
|
|
result)))
|
2018-10-16 18:48:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Pipelines.
|
|
|
|
|
|
2019-12-03 02:26:59 +00:00
|
|
|
|
(define (plumb in out close thunk)
|
2018-10-16 18:48:52 +01:00
|
|
|
|
"Run @var{thunk} in a new process with @code{current-input-port} set
|
|
|
|
|
to @var{in} and @code{current-output-port} set to @var{out}. If
|
|
|
|
|
@var{in} or @var{out} is @code{#f}, the corresponding ``current'' port
|
2019-12-03 02:26:59 +00:00
|
|
|
|
is left unchanged. Unless it is @code{#f}, the port @var{close} will
|
|
|
|
|
be closed in the new process."
|
2018-10-16 18:48:52 +01:00
|
|
|
|
(let* ((thunk* (lambda ()
|
2019-12-03 02:26:59 +00:00
|
|
|
|
(when close (close-port close))
|
2018-10-16 18:48:52 +01:00
|
|
|
|
(let ((in (or in (current-input-port)))
|
|
|
|
|
(out (or out (current-output-port))))
|
|
|
|
|
(parameterize ((current-input-port in)
|
|
|
|
|
(current-output-port out))
|
|
|
|
|
(thunk)))))
|
|
|
|
|
(pid (%subshell thunk*)))
|
|
|
|
|
(when in (close-port in))
|
|
|
|
|
(when out (close-port out))
|
|
|
|
|
pid))
|
|
|
|
|
|
2019-12-03 02:34:15 +00:00
|
|
|
|
(define (waitpid/any pids)
|
|
|
|
|
"Wait for any process with an ID in the list @var{pids} to terminate
|
|
|
|
|
and return its status information."
|
|
|
|
|
(let loop ((interval 10))
|
|
|
|
|
(or (any (lambda (pid)
|
|
|
|
|
(match (waitpid pid WNOHANG)
|
|
|
|
|
((0 . _) #f)
|
|
|
|
|
(x x)))
|
|
|
|
|
pids)
|
|
|
|
|
(begin
|
|
|
|
|
(usleep interval)
|
|
|
|
|
(loop (if (< interval 160)
|
|
|
|
|
(* 2 interval)
|
|
|
|
|
interval))))))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:pipeline . thunks)
|
2018-10-16 18:48:52 +01:00
|
|
|
|
"Run each thunk in @var{thunks} in its own process with the output
|
|
|
|
|
of each thunk sent to the input of the next thunk."
|
2019-12-03 02:26:59 +00:00
|
|
|
|
(define (plumb-thunks)
|
|
|
|
|
(let loop ((thunks thunks) (in #f) (pids '()))
|
|
|
|
|
(match thunks
|
|
|
|
|
(() pids)
|
|
|
|
|
((thunk) (reverse! (cons (plumb in #f #f thunk) pids)))
|
|
|
|
|
((thunk . rest)
|
|
|
|
|
(match-let (((next-in . out) (pipe)))
|
|
|
|
|
(loop rest next-in (cons (plumb in out next-in thunk) pids)))))))
|
|
|
|
|
|
|
|
|
|
(let ((pids (plumb-thunks)))
|
2018-10-16 18:48:52 +01:00
|
|
|
|
(unless (null? pids)
|
2019-12-03 02:34:15 +00:00
|
|
|
|
(let ((last-pid (last pids)))
|
|
|
|
|
;; We have to wait for all the processes to finish so we can
|
|
|
|
|
;; reap them. We do this by polling them with 'waitpid'.
|
|
|
|
|
;; This is something of a naive approach, but it works for now
|
|
|
|
|
;; and will be easier to improve later when we have job
|
|
|
|
|
;; control.
|
|
|
|
|
(let loop ((pids pids))
|
|
|
|
|
(unless (null? pids)
|
|
|
|
|
(match (waitpid/any pids)
|
|
|
|
|
((pid . status)
|
|
|
|
|
(when (= pid last-pid)
|
|
|
|
|
(set-status! (status:exit-val status)))
|
|
|
|
|
(loop (remove (cut = pid <>) pids)))))))
|
|
|
|
|
(errexit))))
|
2018-10-16 19:14:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Boolean expressions.
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:and thunk1 thunk2)
|
|
|
|
|
"Run @var{thunk1} and if it exits with status zero, run
|
|
|
|
|
@var{thunk2}."
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(without-errexit thunk1)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(when (= (get-status) 0)
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(thunk2)
|
|
|
|
|
(errexit)))
|
2018-10-16 19:14:15 +01:00
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:or thunk1 thunk2)
|
|
|
|
|
"Run @var{thunk1} and if it exits with a nonzero status, run
|
|
|
|
|
@var{thunk2}."
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(without-errexit thunk1)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(unless (= (get-status) 0)
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(thunk2)
|
|
|
|
|
(errexit)))
|
2018-10-16 19:14:15 +01:00
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:not thunk)
|
|
|
|
|
"Run @var{thunk}, inverting its exit status."
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(without-errexit thunk)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(let ((inverted-status (if (= (get-status) 0) 1 0)))
|
|
|
|
|
(set-status! inverted-status)))
|
2018-10-16 20:26:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Loops.
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:for bindings thunk)
|
2018-10-16 20:26:40 +01:00
|
|
|
|
"Run @var{thunk} for each binding in @var{bindings}. The value of
|
|
|
|
|
@var{bindings} have the form @code{(@var{name} (@var{value} ...))}."
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(set-status! 0)
|
|
|
|
|
(match-let (((name (values ...)) bindings))
|
|
|
|
|
(call-with-break
|
2018-11-21 15:59:19 +00:00
|
|
|
|
(lambda ()
|
|
|
|
|
(for-each (lambda (value)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(setvar! name value)
|
|
|
|
|
(call-with-continue thunk))
|
|
|
|
|
values)))))
|
|
|
|
|
|
|
|
|
|
(define (sh:while test-thunk thunk)
|
|
|
|
|
(call-with-break
|
|
|
|
|
(lambda ()
|
|
|
|
|
(let loop ((last-status 0))
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(without-errexit test-thunk)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(cond
|
|
|
|
|
((= (get-status) 0)
|
2018-12-22 01:40:52 +00:00
|
|
|
|
(call-with-continue thunk)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(loop (get-status)))
|
|
|
|
|
(else
|
|
|
|
|
(set-status! last-status)))))))
|
|
|
|
|
|
|
|
|
|
(define (sh:until test-thunk thunk)
|
|
|
|
|
(sh:while (lambda () (sh:not test-thunk)) thunk))
|
2018-11-21 16:04:02 +00:00
|
|
|
|
|
2018-11-21 16:37:05 +00:00
|
|
|
|
|
|
|
|
|
;;; Conditionals.
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:case value . cases)
|
|
|
|
|
(set-status! 0)
|
2018-11-21 16:37:05 +00:00
|
|
|
|
(let loop ((cases cases))
|
|
|
|
|
(match cases
|
|
|
|
|
(() #t)
|
|
|
|
|
(((patterns thunk) . tail)
|
|
|
|
|
(if (any (cut pattern-match? <> value) patterns)
|
|
|
|
|
(thunk)
|
|
|
|
|
(loop tail))))))
|
|
|
|
|
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(define (sh:cond . cases)
|
2018-11-21 16:37:05 +00:00
|
|
|
|
(let loop ((cases cases))
|
|
|
|
|
(match cases
|
2018-11-26 01:53:06 +00:00
|
|
|
|
(() (set-status! 0))
|
2018-11-21 16:37:05 +00:00
|
|
|
|
(((#t thunk))
|
|
|
|
|
(thunk))
|
|
|
|
|
(((test-thunk thunk) . tail)
|
Respect the errexit option
* geesh/shell.scm (ignore-errexit?): New parameter.
(without-errexit): New function.
(errexit): New function.
(sh:exec-let, sh:set-redirects, sh:with-redirects, sh:subshell,
sh:substitute-command, sh:pipeline, sh:and, sh:or, sh:not, sh:while,
sh:cond): Use it to exit on nonzero status.
2018-11-26 02:50:18 +00:00
|
|
|
|
(without-errexit test-thunk)
|
Globalize the environment module
Instead of passing around references to the environment, just treat it
as a global. The old way was just the remains of an idea to make the
environment immutable and keep the interpreter from manipulating any
global state. By making everything global and mutable, we will have
less impedance mismatch with POSIX going forward.
The following changelog is only a sketch, since nearly every function
has changed.
* geesh/environment.scm: Replace this module with one that treats the
environment as a global resource.
* tests/environment.scm: Delete file.
* Makefile.am: Remove it from the list of tests.
* geesh/shell.scm, geesh/eval.scm, geesh/repl.scm, geesh/word.scm,
geesh/built-ins/break.scm, geesh/built-ins/continue.scm,
geesh/built-ins/echo.scm, geesh/built-ins/export.scm,
geesh/built-ins/false.scm, geesh/built-ins/read.scm,
geesh/built-ins/readonly.scm, geesh/built-ins/set.scm,
geesh/built-ins/true.scm, geesh/built-ins/unset.scm: Remove 'env'
parameters and use the new environment module.
* .dir-locals.el: Update indentation of functions that no longer take
an 'env' parameter and add with-arguments, with-environ, and
with-variables from the new environment module.
* tests/shell.scm, tests/word.scm: Update environment creation and
manipulation in tests.
2018-11-25 05:47:09 +00:00
|
|
|
|
(if (= (get-status) 0)
|
2018-11-21 16:37:05 +00:00
|
|
|
|
(thunk)
|
|
|
|
|
(loop tail))))))
|
2020-03-17 20:54:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Asynchronous commands.
|
|
|
|
|
|
|
|
|
|
(define (sh:async thunk)
|
|
|
|
|
"Run @var{thunk} asynchronously."
|
|
|
|
|
(let ((pid (%subshell thunk)))
|
|
|
|
|
(set-last-job! pid)
|
|
|
|
|
(set-status! 0)))
|