Commit | Line | Data |
---|---|---|
2de7ddb7 MG |
1 | #! /usr/local/bin/guile -s |
2 | !# | |
3 | ;;; examples/safe/safe -- Example for safe (sand-boxed) evaluation. | |
4 | ||
5 | ;;; Commentary: | |
6 | ||
7 | ;;; This is a demo program for evaluating arbitrary (untrusted) Scheme | |
8 | ;;; code in a controlled, safe environment. Evaluation in safe | |
9 | ;;; environments restricts the evaluated code's access to some given | |
10 | ;;; primitives, which are considered `safe', that means which cannot | |
11 | ;;; do any harm to the world outside of Guile (creating/deleting files | |
12 | ;;; etc.) | |
13 | ;;; | |
14 | ;;; *Note* that the files in this directory are only suitable for | |
15 | ;;; demonstration purposes, if you have to implement safe evaluation | |
16 | ;;; mechanisms in important environments, you will have to do more | |
17 | ;;; than shown here -- for example disabling input/output operations. | |
18 | ||
19 | ;;; Author: Martin Grabmueller | |
20 | ;;; Date: 2001-05-30 | |
21 | ||
22 | ;;; Code: | |
23 | ||
24 | ;; Safe module creation is implemented in this module: | |
25 | ;; | |
26 | (use-modules (ice-9 safe)) | |
27 | ||
28 | ;; This is the main program. It expects one parameter in the format | |
29 | ;; returned by (command-line) and expects that exactly one file name | |
30 | ;; is passed in this list (after the script name, which is passed as | |
31 | ;; the 0th parameter.) | |
32 | ;; | |
33 | ;; The given file is opened for reading, one expression after the | |
34 | ;; other is read and evaluated in a safe environment. All exceptions | |
35 | ;; caused by this evaluation are caught and printed out. | |
36 | ;; | |
37 | (define (main cmd-line) | |
38 | ||
39 | ;; Internal definition of the procedure which prints usage | |
40 | ;; information. | |
41 | ;; | |
42 | (define (display-help) | |
43 | (display "Usage: safe FILENAME") | |
44 | (newline) | |
45 | (quit 1)) | |
46 | ||
47 | ;; Check that we received exactly one command line argument after | |
48 | ;; the script name | |
49 | ;; | |
50 | (if (not (= (length cmd-line) 2)) | |
51 | (display-help) | |
52 | (let ((port (open-input-file (cadr cmd-line))) | |
53 | ||
54 | ;; Create the safe module. | |
55 | (safe-module (make-safe-module))) | |
56 | ||
57 | ;; Read one expression a time. | |
58 | (let lp ((expr (read port))) | |
59 | ;; End of file? -> Return. | |
60 | (if (eof-object? expr) | |
61 | #t | |
62 | (catch #t | |
63 | (lambda () | |
64 | ;; Evaluate the expression in the safe environment. | |
65 | (eval expr safe-module) | |
66 | ;; ... and read the next expression if no error occured. | |
67 | (lp (read port))) | |
68 | ||
69 | ;; Handle exceptions. This procedure will be called when an | |
70 | ;; error occurs while evaluating the expression. It just | |
71 | ;; prints out a message telling so and returns from the | |
72 | ;; evaluation loop, thus terminating the program. | |
73 | ;; | |
74 | (lambda args | |
75 | (display "** Exception: ") | |
76 | (write args) | |
77 | (newline)))))))) | |
78 | ||
79 | ;; Start the main program. | |
80 | ;; | |
81 | (main (command-line)) | |
82 | ||
83 | ;; Local variables: | |
84 | ;; mode: scheme | |
85 | ;; End: |