diff --git a/Makefile.am b/Makefile.am
index 5d8054a..5a4fa26 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,8 +47,10 @@ MODULES = \
geesh/built-ins/export.scm \
geesh/built-ins/false.scm \
geesh/built-ins/read.scm \
+ geesh/built-ins/readonly.scm \
geesh/built-ins/true.scm \
geesh/built-ins/unset.scm \
+ geesh/built-ins/utils.scm \
geesh/built-ins.scm \
geesh/environment.scm \
geesh/eval.scm \
diff --git a/geesh/built-ins.scm b/geesh/built-ins.scm
index 298d5cf..249cf31 100644
--- a/geesh/built-ins.scm
+++ b/geesh/built-ins.scm
@@ -40,7 +40,7 @@
("exec" . ,undefined)
("exit" . ,undefined)
("export" . ,(@@ (geesh built-ins export) main))
- ("readonly" . ,undefined)
+ ("readonly" . ,(@@ (geesh built-ins readonly) main))
("return" . ,undefined)
("set" . ,undefined)
("shift" . ,undefined)
diff --git a/geesh/built-ins/export.scm b/geesh/built-ins/export.scm
index bd0ef1a..cd06378 100644
--- a/geesh/built-ins/export.scm
+++ b/geesh/built-ins/export.scm
@@ -17,6 +17,7 @@
;;; along with Geesh. If not, see .
(define-module (geesh built-ins export)
+ #:use-module (geesh built-ins utils)
#:use-module (geesh environment)
#:use-module (ice-9 match))
@@ -26,14 +27,6 @@
;;;
;;; Code:
-(define (split-assignment assignment)
- (match (string-index assignment #\=)
- (#f (values assignment #f))
- (index (let ((name (substring assignment 0 index)))
- (match (substring assignment (1+ index))
- ((? string-null?) (values name #f))
- (value (values name value)))))))
-
(define (main env . args)
(match args
(("-p") (throw 'not-implemented "export -p"))
diff --git a/geesh/built-ins/readonly.scm b/geesh/built-ins/readonly.scm
new file mode 100644
index 0000000..5a7f3e6
--- /dev/null
+++ b/geesh/built-ins/readonly.scm
@@ -0,0 +1,38 @@
+;;; The Geesh Shell Interpreter
+;;; Copyright 2018 Timothy Sample
+;;;
+;;; This file is part of Geesh.
+;;;
+;;; Geesh 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.
+;;;
+;;; Geesh 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 Geesh. If not, see .
+
+(define-module (geesh built-ins readonly)
+ #:use-module (geesh built-ins utils)
+ #:use-module (geesh environment)
+ #:use-module (ice-9 match))
+
+;;; Commentary:
+;;;
+;;; The 'readonly' utility.
+;;;
+;;; Code:
+
+(define (main env . args)
+ (match args
+ (("-p") (throw 'not-implemented "readonly -p"))
+ (_ (for-each (lambda (assignment)
+ (call-with-values (lambda () (split-assignment assignment))
+ (lambda (name value)
+ (set-var-read-only! env name value))))
+ args)
+ 0)))
diff --git a/geesh/built-ins/utils.scm b/geesh/built-ins/utils.scm
new file mode 100644
index 0000000..41e5bdd
--- /dev/null
+++ b/geesh/built-ins/utils.scm
@@ -0,0 +1,35 @@
+;;; The Geesh Shell Interpreter
+;;; Copyright 2018 Timothy Sample
+;;;
+;;; This file is part of Geesh.
+;;;
+;;; Geesh 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.
+;;;
+;;; Geesh 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 Geesh. If not, see .
+
+(define-module (geesh built-ins utils)
+ #:use-module (ice-9 match)
+ #:export (split-assignment))
+
+;;; Commentary:
+;;;
+;;; Utility functions shared by built-ins.
+;;;
+;;; Code:
+
+(define (split-assignment assignment)
+ (match (string-index assignment #\=)
+ (#f (values assignment #f))
+ (index (let ((name (substring assignment 0 index)))
+ (match (substring assignment (1+ index))
+ ((? string-null?) (values name #f))
+ (value (values name value)))))))