diff options
author | Martin Grabmüller <mgrabmue@cs.tu-berlin.de> | 2001-05-31 15:54:25 +0000 |
---|---|---|
committer | Martin Grabmüller <mgrabmue@cs.tu-berlin.de> | 2001-05-31 15:54:25 +0000 |
commit | 2de7ddb7669c6a1f964fa9ad9a874523b26f4f34 (patch) | |
tree | d1aa9e7ee83c761f46be62f9698df1471c40e5f6 /examples | |
parent | 413a1367e205e594685f4686bc4d31d670d70511 (diff) |
Added the new `examples' directory to the distribution.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/ChangeLog | 13 | ||||
-rw-r--r-- | examples/Makefile.am | 24 | ||||
-rw-r--r-- | examples/README | 12 | ||||
-rw-r--r-- | examples/box-module/Makefile.am | 31 | ||||
-rw-r--r-- | examples/box-module/README | 42 | ||||
-rw-r--r-- | examples/box-module/box.c | 160 | ||||
-rw-r--r-- | examples/box/Makefile.am | 31 | ||||
-rw-r--r-- | examples/box/README | 34 | ||||
-rw-r--r-- | examples/box/box.c | 148 | ||||
-rw-r--r-- | examples/modules/Makefile.am | 22 | ||||
-rw-r--r-- | examples/modules/README | 26 | ||||
-rw-r--r-- | examples/modules/main | 52 | ||||
-rw-r--r-- | examples/modules/module-0.scm | 22 | ||||
-rw-r--r-- | examples/modules/module-1.scm | 22 | ||||
-rw-r--r-- | examples/modules/module-2.scm | 26 | ||||
-rw-r--r-- | examples/safe/Makefile.am | 22 | ||||
-rw-r--r-- | examples/safe/README | 36 | ||||
-rw-r--r-- | examples/safe/evil.scm | 25 | ||||
-rwxr-xr-x | examples/safe/safe | 85 | ||||
-rw-r--r-- | examples/safe/untrusted.scm | 31 | ||||
-rw-r--r-- | examples/scripts/Makefile.am | 22 | ||||
-rw-r--r-- | examples/scripts/README | 33 | ||||
-rwxr-xr-x | examples/scripts/fact | 70 | ||||
-rwxr-xr-x | examples/scripts/hello | 58 | ||||
-rw-r--r-- | examples/scripts/simple-hello.scm | 14 |
25 files changed, 1061 insertions, 0 deletions
diff --git a/examples/ChangeLog b/examples/ChangeLog new file mode 100644 index 000000000..64a1976d2 --- /dev/null +++ b/examples/ChangeLog @@ -0,0 +1,13 @@ +2001-05-30 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * box-module: New directory, similar to box, but defines the + primitives in a module (box-module) instead of defining them + globally. + + * safe: New directory, explaining some aspects of using safe + environments for evaluation. + +2001-05-29 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> + + * New directory for Guile example code. + diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 000000000..c0955a17b --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,24 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +SUBDIRS = scripts box box-module modules safe + +EXTRA_DIST = README diff --git a/examples/README b/examples/README new file mode 100644 index 000000000..ff9f3b2ca --- /dev/null +++ b/examples/README @@ -0,0 +1,12 @@ + -*- text -*- + +This directory includes examples illustrating various aspects of Guile +programming. + +See the README files in the subdirectories for details. + +scripts Examples for writing simple scripts in Guile Scheme. +box Example for extending Guile with a new data type. +box-module Similar to `box', but define new procedures in a named module. +modules Examples for writing and using Guile modules. +safe Examples for creating and using safe environments. diff --git a/examples/box-module/Makefile.am b/examples/box-module/Makefile.am new file mode 100644 index 000000000..3e1f92032 --- /dev/null +++ b/examples/box-module/Makefile.am @@ -0,0 +1,31 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +EXTRA_DIST = README box.c + +CFLAGS=`guile-config compile` +LIBS=`guile-config link` + +box: box.o + $(CC) $< $(LIBS) -o box + +box.o: box.c + $(CC) $(CFLAGS) -c $<
\ No newline at end of file diff --git a/examples/box-module/README b/examples/box-module/README new file mode 100644 index 000000000..7f5d8521d --- /dev/null +++ b/examples/box-module/README @@ -0,0 +1,42 @@ + -*- text -*- + +This directory includes an example program for extending Guile with a +new (and even useful) data type. + +The `box' program created by this example is nearly identical to the +one produced in directory ../box, with one (important) difference: The +interpreter in this directory will place all defined primitive +procedures in a module called (box-module). That means that this +module must be used before the primitives can be accessed. + +To build the example, simply type + + make box + +in this directory. + +The resulting `box' program is a Guile interpreter which has one +additional data type called `box'. + +A box is simply an object for storing one other object in. It can be +used for passing parameters by reference, for example. You simply +store an object into a box, pass it to another procedure which can +store a new object into it and thus return a value via the box. + +Box objects are created with `make-box', set with `box-set!' and +examined with `box-ref'. Note that these procedures are placed in a +module called (box-module) and can thus only be accessed after using +this module. See the following example session for usage details: + +$ ./box +guile> (use-modules (box-module)) +guile> (define b (make-box)) +guile> b +#<box #f> +guile> (box-set! b '(list of values)) +guile> b +#<box (list of values)> +guile> (box-ref b) +(list of values) +guile> (quit) +$ diff --git a/examples/box-module/box.c b/examples/box-module/box.c new file mode 100644 index 000000000..2065466fc --- /dev/null +++ b/examples/box-module/box.c @@ -0,0 +1,160 @@ +/* examples/box-module/box.c + * + * Copyright (C) 1998,2001 Free Software Foundation, Inc. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +/* Include all needed declarations. */ +#include <libguile.h> + + +/* The type code for the newly created smob type will be stored into + this variable. It has the prefix `scm_tc16_' to make it usable + with the SCM_VALIDATE_SMOB macro below. */ +static scm_bits_t scm_tc16_box; + + +/* This function is responsible for marking all SCM objects included + in the smob. */ +static SCM +mark_box (SCM b) +{ + /* Since we have only one SCM object to protect, we simply return it + and the caller with mark it. */ + return SCM_CELL_OBJECT_1 (b); +} + + +/* Print a textual represenation of the smob to a given port. */ +static int +print_box (SCM b, SCM port, scm_print_state *pstate) +{ + SCM value = SCM_CELL_OBJECT_1 (b); + + scm_puts ("#<box ", port); + scm_write (value, port); + scm_puts (">", port); + + /* Non-zero means success. */ + return 1; +} + + +/* This defines the primitve `make-box', which returns a new smob of + type `box', initialized to `#f'. */ +static SCM +#define FUNC_NAME "make-box" +make_box (void) +{ + /* This macro creates the new objects, stores the value `#f' into it + and returns it to the caller. */ + SCM_RETURN_NEWSMOB (scm_tc16_box, SCM_BOOL_F); +} +#undef FUNC_NAME + + +/* This is the primitive `box-ref' which returns the object stored in + the box. */ +static SCM +box_ref (SCM b) +#define FUNC_NAME "box-ref" +{ + /* First, we have to ensure that the user really gave us a box + objects. The macro SCM_VALIDATE_SMOB will do all what is needed. + The parameters are interpreted as follows: + + 1: The position of the checked variable in the parameter list. + b: The passed parameter. + box: Concatenated with the fixed prefix scm_tc16_, names the type + code for the expected smob type. */ + SCM_VALIDATE_SMOB (1, b, box); + + /* Fetch the object from the box and return it. */ + return SCM_CELL_OBJECT_1 (b); +} +#undef FUNC_NAME + + +/* Primitive which stores an arbitrary value into a box. */ +static SCM +box_set_x (SCM b, SCM value) +#define FUNC_NAME "box-set!" +{ + SCM_VALIDATE_SMOB (1, b, box); + + /* Set the cell number 1 of the smob to the given value. */ + SCM_SET_CELL_OBJECT_1 (b, value); + + /* When this constant is returned, the REPL will not print the + returned value. All procedures in Guile which are documented as + returning `and unspecified value' actually return this value. */ + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +/* Create and initialize the new smob type, and register the + primitives withe the interpreter library. + + This function must be declared a bit different from the example in + the ../box directory, because it will be called by + `scm_c_define_module', called from below. */ +static void +init_box_type (void * unused) +{ + scm_tc16_box = scm_make_smob_type ("box", 0); + scm_set_smob_mark (scm_tc16_box, mark_box); + scm_set_smob_print (scm_tc16_box, print_box); + + scm_c_define_gsubr ("make-box", 0, 0, 0, make_box); + scm_c_define_gsubr ("box-set!", 2, 0, 0, box_set_x); + scm_c_define_gsubr ("box-ref", 1, 0, 0, box_ref); + + /* This is new too: Since the procedures are now in a module, we + have to explicitly export them before they can be used. */ + scm_c_export ("make-box", "box-set!", "box-ref", NULL); +} + + +/* This is the function which gets called by scm_boot_guile after the + Guile library is completely initialized. */ +static void +inner_main (void *closure, int argc, char **argv) +{ + /* Unlike the example in ../box, init_box_type is not called + directly, but by scm_c_define_module, which will create a module + named (box-module) and make this module current while called + init_box_type, thus placing the definitions into that module. */ + scm_c_define_module ("box-module", init_box_type, NULL); + + /* ... then we start a shell, in which the box data type can be + used (after using the module (box-module)). */ + scm_shell (argc, argv); +} + + +/* Main program. */ +int +main (int argc, char **argv) +{ + /* Initialize Guile, then call `inner_main' with the arguments 0, + argc and argv. */ + scm_boot_guile (argc, argv, inner_main, 0); + return 0; /* Never reached. */ +} + +/* End of file. */ diff --git a/examples/box/Makefile.am b/examples/box/Makefile.am new file mode 100644 index 000000000..3e1f92032 --- /dev/null +++ b/examples/box/Makefile.am @@ -0,0 +1,31 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +EXTRA_DIST = README box.c + +CFLAGS=`guile-config compile` +LIBS=`guile-config link` + +box: box.o + $(CC) $< $(LIBS) -o box + +box.o: box.c + $(CC) $(CFLAGS) -c $<
\ No newline at end of file diff --git a/examples/box/README b/examples/box/README new file mode 100644 index 000000000..78b7762ef --- /dev/null +++ b/examples/box/README @@ -0,0 +1,34 @@ + -*- text -*- + +This directory includes an example program for extending Guile with a +new (and even useful) data type. + +To build the example, simply type + + make box + +in this directory. + +The resulting `box' program is a Guile interpreter which has one +additional data type called `box'. + +A box is simply an object for storing one other object in. It can be +used for passing parameters by reference, for example. You simply +store an object into a box, pass it to another procedure which can +store a new object into it and thus return a value via the box. + +Box objects are created with `make-box', set with `box-set!' and +examined with `box-ref'. See the following example session for usage +details: + +$ ./box +guile> (define b (make-box)) +guile> b +#<box #f> +guile> (box-set! b '(list of values)) +guile> b +#<box (list of values)> +guile> (box-ref b) +(list of values) +guile> (quit) +$ diff --git a/examples/box/box.c b/examples/box/box.c new file mode 100644 index 000000000..a928c0ef3 --- /dev/null +++ b/examples/box/box.c @@ -0,0 +1,148 @@ +/* examples/box/box.c + * + * Copyright (C) 1998,2001 Free Software Foundation, Inc. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +/* Include all needed declarations. */ +#include <libguile.h> + + +/* The type code for the newly created smob type will be stored into + this variable. It has the prefix `scm_tc16_' to make it usable + with the SCM_VALIDATE_SMOB macro below. */ +static scm_bits_t scm_tc16_box; + + +/* This function is responsible for marking all SCM objects included + in the smob. */ +static SCM +mark_box (SCM b) +{ + /* Since we have only one SCM object to protect, we simply return it + and the caller with mark it. */ + return SCM_CELL_OBJECT_1 (b); +} + + +/* Print a textual represenation of the smob to a given port. */ +static int +print_box (SCM b, SCM port, scm_print_state *pstate) +{ + SCM value = SCM_CELL_OBJECT_1 (b); + + scm_puts ("#<box ", port); + scm_write (value, port); + scm_puts (">", port); + + /* Non-zero means success. */ + return 1; +} + + +/* This defines the primitve `make-box', which returns a new smob of + type `box', initialized to `#f'. */ +static SCM +#define FUNC_NAME "make-box" +make_box (void) +{ + /* This macro creates the new objects, stores the value `#f' into it + and returns it to the caller. */ + SCM_RETURN_NEWSMOB (scm_tc16_box, SCM_BOOL_F); +} +#undef FUNC_NAME + + +/* This is the primitive `box-ref' which returns the object stored in + the box. */ +static SCM +box_ref (SCM b) +#define FUNC_NAME "box-ref" +{ + /* First, we have to ensure that the user really gave us a box + objects. The macro SCM_VALIDATE_SMOB will do all what is needed. + The parameters are interpreted as follows: + + 1: The position of the checked variable in the parameter list. + b: The passed parameter. + box: Concatenated with the fixed prefix scm_tc16_, names the type + code for the expected smob type. */ + SCM_VALIDATE_SMOB (1, b, box); + + /* Fetch the object from the box and return it. */ + return SCM_CELL_OBJECT_1 (b); +} +#undef FUNC_NAME + + +/* Primitive which stores an arbitrary value into a box. */ +static SCM +box_set_x (SCM b, SCM value) +#define FUNC_NAME "box-set!" +{ + SCM_VALIDATE_SMOB (1, b, box); + + /* Set the cell number 1 of the smob to the given value. */ + SCM_SET_CELL_OBJECT_1 (b, value); + + /* When this constant is returned, the REPL will not print the + returned value. All procedures in Guile which are documented as + returning `and unspecified value' actually return this value. */ + return SCM_UNSPECIFIED; +} +#undef FUNC_NAME + + +/* Create and initialize the new smob type, and register the + primitives withe the interpreter library. */ +static void +init_box_type (void) +{ + scm_tc16_box = scm_make_smob_type ("box", 0); + scm_set_smob_mark (scm_tc16_box, mark_box); + scm_set_smob_print (scm_tc16_box, print_box); + + scm_c_define_gsubr ("make-box", 0, 0, 0, make_box); + scm_c_define_gsubr ("box-set!", 2, 0, 0, box_set_x); + scm_c_define_gsubr ("box-ref", 1, 0, 0, box_ref); +} + + +/* This is the function which gets called by scm_boot_guile after the + Guile library is completely initialized. */ +static void +inner_main (void *closure, int argc, char **argv) +{ + /* First, we create our data type... */ + init_box_type (); + /* ... then we start a shell, in which the box data type can be + used. */ + scm_shell (argc, argv); +} + + +/* Main program. */ +int +main (int argc, char **argv) +{ + /* Initialize Guile, then call `inner_main' with the arguments 0, + argc and argv. */ + scm_boot_guile (argc, argv, inner_main, 0); + return 0; /* Never reached. */ +} + +/* End of file. */ diff --git a/examples/modules/Makefile.am b/examples/modules/Makefile.am new file mode 100644 index 000000000..35988c545 --- /dev/null +++ b/examples/modules/Makefile.am @@ -0,0 +1,22 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +EXTRA_DIST = README module-0.scm module-1.scm module-2.scm main diff --git a/examples/modules/README b/examples/modules/README new file mode 100644 index 000000000..12df77f69 --- /dev/null +++ b/examples/modules/README @@ -0,0 +1,26 @@ + -*- text -*- + +This directory includes examples which show how to write and use Guile +modules in Scheme programs. + +The descriptions below assume that you have a working copy of Guile +installed and available with the standard installation prefix +`/usr/local'. + +main: + + The main program, which uses the modules described below to perform + some actions. Module usage and selective importing as well as + renaming is demonstrated here.n + + $ ./main + + or + + guile -s main + +module-0.scm, module-1.scm, module-2.scm: + + Two modules which export several procedure, some of which have the + same names (so that renaming/selection is required for proper + importing). diff --git a/examples/modules/main b/examples/modules/main new file mode 100644 index 000000000..603ea10f1 --- /dev/null +++ b/examples/modules/main @@ -0,0 +1,52 @@ +#! /usr/local/bin/guile -s +!# +;;; examples/modules/main -- Module system demo. + +;;; Commentary: + +;;; The main demo program for the modules subdirectory. +;;; +;;; This program shows how all the new fancy module import features +;;; are to be used. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(define-module (main) + ;; The module 0 is imported completely. + ;; + :use-module (module-0) + + ;; Module 1 is imported completely, too, but the procedure names are + ;; prefixed with the module name. + ;; + :use-module ((module-1) :rename (symbol-prefix-proc 'module-1:)) + + ;; From module 2, only the procedure `braz' is imported, so that the + ;; procedures `foo' and `bar' also exported by that module don't + ;; clash with the definitions of module 0. + ;; + :use-module ((module-2) :select (braz)) + + ;; Import the bindings from module 2 again, now renaming them by + ;; explicitly mentioning the original and new names. + ;; + :use-module ((module-2) :select ((braz . m-2:braz) (foo . m-2:foo)))) + +;; +;; Now call the various imported procedures. +;; + +(foo) +(bar) +(module-1:foo) +(module-1:bar) +(braz) +(m-2:braz) +(m-2:foo) + +;; Local variables: +;; mode: scheme +;; End: diff --git a/examples/modules/module-0.scm b/examples/modules/module-0.scm new file mode 100644 index 000000000..47e8433c7 --- /dev/null +++ b/examples/modules/module-0.scm @@ -0,0 +1,22 @@ +;;; examples/modules/module-0.scm -- Module system demo. + +;;; Commentary: + +;;; Module 0 of the module demo program. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(define-module (module-0)) + +(export foo bar) + +(define (foo) + (display "module-0 foo") + (newline)) + +(define (bar) + (display "module-0 bar") + (newline)) diff --git a/examples/modules/module-1.scm b/examples/modules/module-1.scm new file mode 100644 index 000000000..d62264021 --- /dev/null +++ b/examples/modules/module-1.scm @@ -0,0 +1,22 @@ +;;; examples/modules/module-1.scm -- Module system demo. + +;;; Commentary: + +;;; Module 1 of the module demo program. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(define-module (module-1)) + +(export foo bar) + +(define (foo) + (display "module-1 foo") + (newline)) + +(define (bar) + (display "module-1 bar") + (newline)) diff --git a/examples/modules/module-2.scm b/examples/modules/module-2.scm new file mode 100644 index 000000000..a63d5e492 --- /dev/null +++ b/examples/modules/module-2.scm @@ -0,0 +1,26 @@ +;;; examples/modules/module-2.scm -- Module system demo. + +;;; Commentary: + +;;; Module 2 of the module demo program. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(define-module (module-2)) + +(export foo bar braz) + +(define (foo) + (display "module-2 foo") + (newline)) + +(define (bar) + (display "module-2 bar") + (newline)) + +(define (braz) + (display "module-2 braz") + (newline)) diff --git a/examples/safe/Makefile.am b/examples/safe/Makefile.am new file mode 100644 index 000000000..cf41df73f --- /dev/null +++ b/examples/safe/Makefile.am @@ -0,0 +1,22 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +EXTRA_DIST = README safe untrusted.scm evil.scm diff --git a/examples/safe/README b/examples/safe/README new file mode 100644 index 000000000..be16e1e74 --- /dev/null +++ b/examples/safe/README @@ -0,0 +1,36 @@ + -*- text -*- + +This directory includes examples which show how to create and use safe +environments for safe (sand-boxed) execution of Scheme programs. + +*Note* that the files in this directory are only suitable for + demonstration purposes, if you have to implement safe evaluation + mechanisms in important environments, you will have to do more than + shown here -- for example disabling input/output operations. + +The descriptions below assume that you have a working copy of Guile +installed and available with the standard installation prefix +`/usr/local'. + +safe: + + The main program, which executes the Scheme code in a file given on + the command line in a safe environment. The following command will + do that with the file `untrusted.scm' (see below.) + + $ ./safe untrusted.scm + + or + + guile -s safe untrusted.scm + +untrusted.scm: + + This file contains some Scheme code, which will be executed in a + safe environment by the `safe' script. + +evil.scm + + This file also contains Scheme code, but it tries to do evil things. + Evaluating this with the `safe' script will abort on those evil + actions. diff --git a/examples/safe/evil.scm b/examples/safe/evil.scm new file mode 100644 index 000000000..9eb64db8e --- /dev/null +++ b/examples/safe/evil.scm @@ -0,0 +1,25 @@ +;;; examples/safe/evil.scm -- Evil Scheme file to be run in a safe +;;; environment. + +;;; Commentary: + +;;; This is an example file to be evaluated by the `safe' program in +;;; this directory. This program, unlike the `untrusted.scm' (which +;;; is untrusted, but a really nice fellow though), tries to do evil +;;; things and will thus break in a safe environment. +;;; +;;; *Note* that the files in this directory are only suitable for +;;; demonstration purposes, if you have to implement safe evaluation +;;; mechanisms in important environments, you will have to do more +;;; than shown here -- for example disabling input/output operations. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-30 + +;;; Code: + +(define passwd (open-input-file "/etc/passwd")) + +(let lp ((ch (read-char passwd))) + (if (not (eof-object? ch)) + (lp (read-char passwd)))) diff --git a/examples/safe/safe b/examples/safe/safe new file mode 100755 index 000000000..7653dc2b8 --- /dev/null +++ b/examples/safe/safe @@ -0,0 +1,85 @@ +#! /usr/local/bin/guile -s +!# +;;; examples/safe/safe -- Example for safe (sand-boxed) evaluation. + +;;; Commentary: + +;;; This is a demo program for evaluating arbitrary (untrusted) Scheme +;;; code in a controlled, safe environment. Evaluation in safe +;;; environments restricts the evaluated code's access to some given +;;; primitives, which are considered `safe', that means which cannot +;;; do any harm to the world outside of Guile (creating/deleting files +;;; etc.) +;;; +;;; *Note* that the files in this directory are only suitable for +;;; demonstration purposes, if you have to implement safe evaluation +;;; mechanisms in important environments, you will have to do more +;;; than shown here -- for example disabling input/output operations. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-30 + +;;; Code: + +;; Safe module creation is implemented in this module: +;; +(use-modules (ice-9 safe)) + +;; This is the main program. It expects one parameter in the format +;; returned by (command-line) and expects that exactly one file name +;; is passed in this list (after the script name, which is passed as +;; the 0th parameter.) +;; +;; The given file is opened for reading, one expression after the +;; other is read and evaluated in a safe environment. All exceptions +;; caused by this evaluation are caught and printed out. +;; +(define (main cmd-line) + + ;; Internal definition of the procedure which prints usage + ;; information. + ;; + (define (display-help) + (display "Usage: safe FILENAME") + (newline) + (quit 1)) + + ;; Check that we received exactly one command line argument after + ;; the script name + ;; + (if (not (= (length cmd-line) 2)) + (display-help) + (let ((port (open-input-file (cadr cmd-line))) + + ;; Create the safe module. + (safe-module (make-safe-module))) + + ;; Read one expression a time. + (let lp ((expr (read port))) + ;; End of file? -> Return. + (if (eof-object? expr) + #t + (catch #t + (lambda () + ;; Evaluate the expression in the safe environment. + (eval expr safe-module) + ;; ... and read the next expression if no error occured. + (lp (read port))) + + ;; Handle exceptions. This procedure will be called when an + ;; error occurs while evaluating the expression. It just + ;; prints out a message telling so and returns from the + ;; evaluation loop, thus terminating the program. + ;; + (lambda args + (display "** Exception: ") + (write args) + (newline)))))))) + +;; Start the main program. +;; +(main (command-line)) + +;; Local variables: +;; mode: scheme +;; End: diff --git a/examples/safe/untrusted.scm b/examples/safe/untrusted.scm new file mode 100644 index 000000000..9cdf1b640 --- /dev/null +++ b/examples/safe/untrusted.scm @@ -0,0 +1,31 @@ +;;; examples/safe/untrusted.scm -- Scheme file to be run in a safe +;;; environment. + +;;; Commentary: + +;;; This is an example file to be evaluated by the `safe' program in +;;; this directory. +;;; +;;; *Note* that the files in this directory are only suitable for +;;; demonstration purposes, if you have to implement safe evaluation +;;; mechanisms in important environments, you will have to do more +;;; than shown here -- for example disabling input/output operations. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-30 + +;;; Code: + +;; fact -- the everlasting factorial function... +;; +(define (fact n) + (if (< n 2) + 1 + (* n (fact (- n 1))))) + +;; Display the factorial of 0..9 to the terminal. +;; +(do ((x 0 (+ x 1))) + ((= x 11)) + (display (fact x)) + (newline)) diff --git a/examples/scripts/Makefile.am b/examples/scripts/Makefile.am new file mode 100644 index 000000000..ff6173086 --- /dev/null +++ b/examples/scripts/Makefile.am @@ -0,0 +1,22 @@ +## Process this file with Automake to create Makefile.in +## +## Copyright (C) 2001 Free Software Foundation, Inc. +## +## This file is part of GUILE. +## +## GUILE 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 2, or +## (at your option) any later version. +## +## GUILE 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 GUILE; see the file COPYING. If not, write +## to the Free Software Foundation, Inc., 59 Temple Place, Suite +## 330, Boston, MA 02111-1307 USA + +EXTRA_DIST = README simple-hello.scm hello fact diff --git a/examples/scripts/README b/examples/scripts/README new file mode 100644 index 000000000..491007c27 --- /dev/null +++ b/examples/scripts/README @@ -0,0 +1,33 @@ + -*- text -*- + +This directory includes examples which show how to write scripts using +Guile. + +The descriptions below assume that you have a working copy of Guile +installed and available with the standard installation prefix +`/usr/local'. + +simple-hello.scm: + + The simplest "Hello World!" program for Guile. Run it like this: + + $ guile -s simple-hello.scm + +hello: + + An advanced version of the script above, with command line handling + for the important options --help and --version. Run it like this: + + ./hello + + or + + guile -s hello + +fact: + + Command-line factorial calculator. Run it like this: + + ./fact 5 + + to calculate the factorial of 5. diff --git a/examples/scripts/fact b/examples/scripts/fact new file mode 100755 index 000000000..90eecd7c2 --- /dev/null +++ b/examples/scripts/fact @@ -0,0 +1,70 @@ +#! /usr/local/bin/guile -s +!# +;;; Commentary: + +;;; This is a command-line factorial calculator. Run like this: +;;; +;;; ./fact 5 +;;; +;;; to calculate the factorial of 5 + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(use-modules (ice-9 getopt-long)) + +;; This is the grammar for the command line synopsis we expect. +;; +(define command-synopsis + '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) + +;; Display version information and exit. +;; +(define (display-version) + (display "fact 0.0.1\n")) + +;; Display the usage help message and exit. +;; +(define (display-help) + (display "Usage: fact [options...] number\n") + (display " --help, -h Show this usage information\n") + (display " --version, -v Show version information\n")) + +;; Interpret options, if --help or --version was given, print out the +;; requested information and exit. Otherwise, calculate the factorial +;; of the argument. +;; +(define (main options) + (let ((help-wanted (option-ref options 'help #f)) + (version-wanted (option-ref options 'version #f)) + (args (option-ref options '() '()))) + (cond + ((or version-wanted help-wanted) + (if version-wanted + (display-version)) + (if help-wanted + (display-help))) + ((not (= (length args) 1)) + (display-help)) + (else + (display (fact (string->number (car args)))) + (newline))))) + +;; Calculate the factorial of n. +;; +(define (fact n) + (if (< n 2) + 1 + (* n (fact (- n 1))))) + +;; Call the main program with parsed command line options. +;; +(main (getopt-long (command-line) command-synopsis)) + +;; Local variables: +;; mode: scheme +;; End: + diff --git a/examples/scripts/hello b/examples/scripts/hello new file mode 100755 index 000000000..4108db400 --- /dev/null +++ b/examples/scripts/hello @@ -0,0 +1,58 @@ +#! /usr/local/bin/guile -s +!# +;;; Commentary: + +;;; This is the famous Hello-World-program, written for Guile. It is a +;;; little bit enhanced in that it understands the command line options +;;; `--help' (-h) and `--version' (-v), which print a short usage +;;; decription or version information, respectively. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(use-modules (ice-9 getopt-long)) + +;; This is the grammar for the command line synopsis we expect. +;; +(define command-synopsis + '((version (single-char #\v) (value #f)) + (help (single-char #\h) (value #f)))) + +;; Display version information and exit. +;; +(define (display-version) + (display "hello 0.0.1\n")) + +;; Display the usage help message and exit. +;; +(define (display-help) + (display "Usage: hello [options...]\n") + (display " --help, -h Show this usage information\n") + (display " --version, -v Show version information\n")) + +;; Interpret options, if --help or --version was given, print out the +;; requested information and exit. Otherwise, print the famous +;; message. +;; +(define (main options) + (let ((help-wanted (option-ref options 'help #f)) + (version-wanted (option-ref options 'version #f))) + (if (or version-wanted help-wanted) + (begin + (if version-wanted + (display-version)) + (if help-wanted + (display-help))) + (begin + (display "Hello, World!") (newline))))) + +;; Call the main program with parsed command line options. +;; +(main (getopt-long (command-line) command-synopsis)) + +;; Local variables: +;; mode: scheme +;; End: + diff --git a/examples/scripts/simple-hello.scm b/examples/scripts/simple-hello.scm new file mode 100644 index 000000000..713a1aee4 --- /dev/null +++ b/examples/scripts/simple-hello.scm @@ -0,0 +1,14 @@ +;;; Commentary: + +;;; This is the famous Hello-World-program, written for Guile. +;;; +;;; For an advanced version, see the script `hello' in the same +;;; directory. + +;;; Author: Martin Grabmueller +;;; Date: 2001-05-29 + +;;; Code: + +(display "Hello, World!") +(newline) |