1 /* FFI interface for TinySCHEME.
3 * Copyright (C) 2016 g10 code GmbH
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <https://www.gnu.org/licenses/>.
28 #include <gpg-error.h>
33 #include <sys/types.h>
38 #define GNUPG_LIBREADLINE_H_INCLUDED
39 #include <readline/readline.h>
40 #include <readline/history.h>
43 #include "../../common/util.h"
44 #include "../../common/exechelp.h"
45 #include "../../common/sysutils.h"
49 #include "ffi-private.h"
51 /* For use in nice error messages. */
53 ordinal_suffix (int n)
68 ffi_bool_value (scheme *sc, pointer p)
70 return ! (p == sc->F);
76 do_logand (scheme *sc, pointer args)
79 unsigned int v, acc = ~0;
80 while (args != sc->NIL)
82 FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
85 FFI_RETURN_INT (sc, acc);
89 do_logior (scheme *sc, pointer args)
92 unsigned int v, acc = 0;
93 while (args != sc->NIL)
95 FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
98 FFI_RETURN_INT (sc, acc);
102 do_logxor (scheme *sc, pointer args)
105 unsigned int v, acc = 0;
106 while (args != sc->NIL)
108 FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
111 FFI_RETURN_INT (sc, acc);
115 do_lognot (scheme *sc, pointer args)
119 FFI_ARG_OR_RETURN (sc, unsigned int, v, number, args);
120 FFI_ARGS_DONE_OR_RETURN (sc, args);
121 FFI_RETURN_INT (sc, ~v);
124 /* User interface. */
127 do_flush_stdio (scheme *sc, pointer args)
130 FFI_ARGS_DONE_OR_RETURN (sc, args);
139 /* Read a string, and return a pointer to it. Returns NULL on EOF. */
141 rl_gets (const char *prompt)
143 static char *line = NULL;
149 line = readline (prompt);
155 size_t max_size = 0xff;
156 printf ("%s", prompt);
158 line = xtrymalloc (max_size);
160 fgets (line, max_size, stdin);
164 /* Strip trailing whitespace. */
165 if (line && strlen (line) > 0)
166 for (p = &line[strlen (line) - 1]; isspace (*p); p--)
173 do_prompt (scheme *sc, pointer args)
178 FFI_ARG_OR_RETURN (sc, const char *, prompt, string, args);
179 FFI_ARGS_DONE_OR_RETURN (sc, args);
180 line = rl_gets (prompt);
182 FFI_RETURN_POINTER (sc, sc->EOF_OBJ);
184 FFI_RETURN_STRING (sc, line);
188 do_sleep (scheme *sc, pointer args)
191 unsigned int seconds;
192 FFI_ARG_OR_RETURN (sc, unsigned int, seconds, number, args);
193 FFI_ARGS_DONE_OR_RETURN (sc, args);
199 do_usleep (scheme *sc, pointer args)
202 useconds_t microseconds;
203 FFI_ARG_OR_RETURN (sc, useconds_t, microseconds, number, args);
204 FFI_ARGS_DONE_OR_RETURN (sc, args);
205 usleep (microseconds);
210 do_chdir (scheme *sc, pointer args)
214 FFI_ARG_OR_RETURN (sc, char *, name, path, args);
215 FFI_ARGS_DONE_OR_RETURN (sc, args);
217 FFI_RETURN_ERR (sc, errno);
222 do_strerror (scheme *sc, pointer args)
226 FFI_ARG_OR_RETURN (sc, int, error, number, args);
227 FFI_ARGS_DONE_OR_RETURN (sc, args);
228 FFI_RETURN_STRING (sc, gpg_strerror (error));
232 do_getenv (scheme *sc, pointer args)
237 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
238 FFI_ARGS_DONE_OR_RETURN (sc, args);
239 value = getenv (name);
240 FFI_RETURN_STRING (sc, value ? value : "");
244 do_setenv (scheme *sc, pointer args)
250 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
251 FFI_ARG_OR_RETURN (sc, char *, value, string, args);
252 FFI_ARG_OR_RETURN (sc, int, overwrite, bool, args);
253 FFI_ARGS_DONE_OR_RETURN (sc, args);
254 if (gnupg_setenv (name, value, overwrite))
255 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
260 do_exit (scheme *sc, pointer args)
264 FFI_ARG_OR_RETURN (sc, int, retcode, number, args);
265 FFI_ARGS_DONE_OR_RETURN (sc, args);
269 /* XXX: use gnupgs variant b/c mode as string */
271 do_open (scheme *sc, pointer args)
278 FFI_ARG_OR_RETURN (sc, char *, pathname, path, args);
279 FFI_ARG_OR_RETURN (sc, int, flags, number, args);
281 FFI_ARG_OR_RETURN (sc, mode_t, mode, number, args);
282 FFI_ARGS_DONE_OR_RETURN (sc, args);
284 fd = open (pathname, flags, mode);
286 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
287 FFI_RETURN_INT (sc, fd);
291 do_fdopen (scheme *sc, pointer args)
298 FFI_ARG_OR_RETURN (sc, int, fd, number, args);
299 FFI_ARG_OR_RETURN (sc, char *, mode, string, args);
300 FFI_ARGS_DONE_OR_RETURN (sc, args);
302 stream = fdopen (fd, mode);
304 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
306 if (setvbuf (stream, NULL, _IONBF, 0) != 0)
307 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
310 if (strchr (mode, 'r'))
312 if (strchr (mode, 'w'))
315 FFI_RETURN_POINTER (sc, sc->vptr->mk_port_from_file (sc, stream, kind));
319 do_close (scheme *sc, pointer args)
323 FFI_ARG_OR_RETURN (sc, int, fd, number, args);
324 FFI_ARGS_DONE_OR_RETURN (sc, args);
325 FFI_RETURN_ERR (sc, close (fd) == 0 ? 0 : gpg_error_from_syserror ());
329 do_seek (scheme *sc, pointer args)
335 FFI_ARG_OR_RETURN (sc, int, fd, number, args);
336 FFI_ARG_OR_RETURN (sc, off_t, offset, number, args);
337 FFI_ARG_OR_RETURN (sc, int, whence, number, args);
338 FFI_ARGS_DONE_OR_RETURN (sc, args);
339 FFI_RETURN_ERR (sc, lseek (fd, offset, whence) == (off_t) -1
340 ? gpg_error_from_syserror () : 0);
344 do_mkdtemp (scheme *sc, pointer args)
350 FFI_ARG_OR_RETURN (sc, char *, template, string, args);
351 FFI_ARGS_DONE_OR_RETURN (sc, args);
353 if (strlen (template) > sizeof buffer - 1)
354 FFI_RETURN_ERR (sc, EINVAL);
355 strncpy (buffer, template, sizeof buffer);
357 name = gnupg_mkdtemp (buffer);
359 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
360 FFI_RETURN_STRING (sc, name);
364 do_unlink (scheme *sc, pointer args)
368 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
369 FFI_ARGS_DONE_OR_RETURN (sc, args);
370 if (unlink (name) == -1)
371 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
376 unlink_recursively (const char *name)
381 if (stat (name, &st) == -1)
382 return gpg_error_from_syserror ();
384 if (S_ISDIR (st.st_mode))
389 dir = opendir (name);
391 return gpg_error_from_syserror ();
393 while ((dent = readdir (dir)))
397 if (strcmp (dent->d_name, ".") == 0
398 || strcmp (dent->d_name, "..") == 0)
401 child = xtryasprintf ("%s/%s", name, dent->d_name);
404 err = gpg_error_from_syserror ();
408 err = unlink_recursively (child);
410 if (err == gpg_error_from_errno (ENOENT))
423 if (unlink (name) == -1)
424 return gpg_error_from_syserror ();
429 do_unlink_recursively (scheme *sc, pointer args)
433 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
434 FFI_ARGS_DONE_OR_RETURN (sc, args);
435 err = unlink_recursively (name);
440 do_rename (scheme *sc, pointer args)
445 FFI_ARG_OR_RETURN (sc, char *, old, string, args);
446 FFI_ARG_OR_RETURN (sc, char *, new, string, args);
447 FFI_ARGS_DONE_OR_RETURN (sc, args);
448 if (rename (old, new) == -1)
449 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
454 do_getcwd (scheme *sc, pointer args)
459 FFI_ARGS_DONE_OR_RETURN (sc, args);
460 cwd = gnupg_getcwd ();
462 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
463 result = sc->vptr->mk_string (sc, cwd);
465 FFI_RETURN_POINTER (sc, result);
469 do_mkdir (scheme *sc, pointer args)
474 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
475 FFI_ARG_OR_RETURN (sc, char *, mode, string, args);
476 FFI_ARGS_DONE_OR_RETURN (sc, args);
477 if (gnupg_mkdir (name, mode) == -1)
478 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
483 do_rmdir (scheme *sc, pointer args)
487 FFI_ARG_OR_RETURN (sc, char *, name, string, args);
488 FFI_ARGS_DONE_OR_RETURN (sc, args);
489 if (rmdir (name) == -1)
490 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
495 do_get_isotime (scheme *sc, pointer args)
498 gnupg_isotime_t timebuf;
499 FFI_ARGS_DONE_OR_RETURN (sc, args);
500 gnupg_get_isotime (timebuf);
501 FFI_RETURN_STRING (sc, timebuf);
505 do_getpid (scheme *sc, pointer args)
508 FFI_ARGS_DONE_OR_RETURN (sc, args);
509 FFI_RETURN_INT (sc, getpid ());
513 do_srandom (scheme *sc, pointer args)
517 FFI_ARG_OR_RETURN (sc, int, seed, number, args);
518 FFI_ARGS_DONE_OR_RETURN (sc, args);
524 random_scaled (int scale)
533 #ifndef RAND_MAX /* for SunOS */
534 #define RAND_MAX 32767
537 return ((int) (1 + (int) ((float) scale * v / (RAND_MAX + 1.0))) - 1);
541 do_random (scheme *sc, pointer args)
545 FFI_ARG_OR_RETURN (sc, int, scale, number, args);
546 FFI_ARGS_DONE_OR_RETURN (sc, args);
547 FFI_RETURN_INT (sc, random_scaled (scale));
551 do_make_random_string (scheme *sc, pointer args)
557 FFI_ARG_OR_RETURN (sc, int, size, number, args);
558 FFI_ARGS_DONE_OR_RETURN (sc, args);
560 return ffi_sprintf (sc, "size must be positive");
562 chunk = sc->vptr->mk_counted_string (sc, NULL, size);
564 FFI_RETURN_ERR (sc, ENOMEM);
566 for (p = sc->vptr->string_value (chunk); size; p++, size--)
567 *p = (char) random_scaled (256);
568 FFI_RETURN_POINTER (sc, chunk);
573 /* estream functions. */
582 es_object_finalize (scheme *sc, void *data)
584 struct es_object_box *box = data;
588 es_fclose (box->stream);
593 es_object_to_string (scheme *sc, char *out, size_t size, void *data)
595 struct es_object_box *box = data;
598 snprintf (out, size, "#estream %p", box->stream);
601 static struct foreign_object_vtable es_object_vtable =
608 es_wrap (scheme *sc, estream_t stream)
610 struct es_object_box *box = xmalloc (sizeof *box);
614 box->stream = stream;
616 return sc->vptr->mk_foreign_object (sc, &es_object_vtable, box);
619 static struct es_object_box *
620 es_unwrap (scheme *sc, pointer object)
624 if (! is_foreign_object (object))
627 if (sc->vptr->get_foreign_object_vtable (object) != &es_object_vtable)
630 return sc->vptr->get_foreign_object_data (object);
633 #define CONVERSION_estream(SC, X) es_unwrap (SC, X)
634 #define IS_A_estream(SC, X) es_unwrap (SC, X)
637 do_es_fclose (scheme *sc, pointer args)
640 struct es_object_box *box;
641 FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
642 FFI_ARGS_DONE_OR_RETURN (sc, args);
643 err = es_fclose (box->stream);
650 do_es_read (scheme *sc, pointer args)
653 struct es_object_box *box;
654 size_t bytes_to_read;
660 FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
661 FFI_ARG_OR_RETURN (sc, size_t, bytes_to_read, number, args);
662 FFI_ARGS_DONE_OR_RETURN (sc, args);
664 buffer = xtrymalloc (bytes_to_read);
666 FFI_RETURN_ERR (sc, ENOMEM);
668 err = es_read (box->stream, buffer, bytes_to_read, &bytes_read);
670 FFI_RETURN_ERR (sc, err);
672 result = sc->vptr->mk_counted_string (sc, buffer, bytes_read);
674 FFI_RETURN_POINTER (sc, result);
678 do_es_feof (scheme *sc, pointer args)
681 struct es_object_box *box;
682 FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
683 FFI_ARGS_DONE_OR_RETURN (sc, args);
685 FFI_RETURN_POINTER (sc, es_feof (box->stream) ? sc->T : sc->F);
689 do_es_write (scheme *sc, pointer args)
692 struct es_object_box *box;
694 size_t bytes_to_write, bytes_written;
696 FFI_ARG_OR_RETURN (sc, struct es_object_box *, box, estream, args);
697 /* XXX how to get the length of the string buffer? scheme strings
699 FFI_ARG_OR_RETURN (sc, const char *, buffer, string, args);
700 FFI_ARGS_DONE_OR_RETURN (sc, args);
702 bytes_to_write = strlen (buffer);
703 while (bytes_to_write > 0)
705 err = es_write (box->stream, buffer, bytes_to_write, &bytes_written);
708 bytes_to_write -= bytes_written;
709 buffer += bytes_written;
717 /* Process handling. */
720 do_spawn_process (scheme *sc, pointer args)
733 FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
734 FFI_ARG_OR_RETURN (sc, unsigned int, flags, number, args);
735 FFI_ARGS_DONE_OR_RETURN (sc, args);
737 err = ffi_list2argv (sc, arguments, &argv, &len);
738 if (err == gpg_error (GPG_ERR_INV_VALUE))
739 return ffi_sprintf (sc, "%luth element of first argument is "
740 "neither string nor symbol",
741 (unsigned long) len);
743 FFI_RETURN_ERR (sc, err);
748 fprintf (stderr, "Executing:");
749 for (p = argv; *p; p++)
750 fprintf (stderr, " '%s'", *p);
751 fprintf (stderr, "\n");
754 err = gnupg_spawn_process (argv[0], (const char **) &argv[1],
758 &infp, &outfp, &errfp, &pid);
761 _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
763 _cons (sc, es_wrap (sc, (A)), (B), 1)
764 FFI_RETURN_POINTER (sc, IMS (infp,
767 IMC (pid, sc->NIL)))));
773 do_spawn_process_fd (scheme *sc, pointer args)
779 int infd, outfd, errfd;
783 FFI_ARG_OR_RETURN (sc, pointer, arguments, list, args);
784 FFI_ARG_OR_RETURN (sc, int, infd, number, args);
785 FFI_ARG_OR_RETURN (sc, int, outfd, number, args);
786 FFI_ARG_OR_RETURN (sc, int, errfd, number, args);
787 FFI_ARGS_DONE_OR_RETURN (sc, args);
789 err = ffi_list2argv (sc, arguments, &argv, &len);
790 if (err == gpg_error (GPG_ERR_INV_VALUE))
791 return ffi_sprintf (sc, "%luth element of first argument is "
792 "neither string nor symbol",
793 (unsigned long) len);
795 FFI_RETURN_ERR (sc, err);
800 fprintf (stderr, "Executing:");
801 for (p = argv; *p; p++)
802 fprintf (stderr, " '%s'", *p);
803 fprintf (stderr, "\n");
806 err = gnupg_spawn_process_fd (argv[0], (const char **) &argv[1],
807 infd, outfd, errfd, &pid);
809 FFI_RETURN_INT (sc, pid);
813 do_wait_process (scheme *sc, pointer args)
822 FFI_ARG_OR_RETURN (sc, const char *, name, string, args);
823 FFI_ARG_OR_RETURN (sc, pid_t, pid, number, args);
824 FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
825 FFI_ARGS_DONE_OR_RETURN (sc, args);
826 err = gnupg_wait_process (name, pid, hang, &retcode);
827 if (err == GPG_ERR_GENERAL)
828 err = 0; /* Let the return code speak for itself. */
830 FFI_RETURN_INT (sc, retcode);
835 do_wait_processes (scheme *sc, pointer args)
845 pointer retcodes_list = sc->NIL;
847 FFI_ARG_OR_RETURN (sc, pointer, list_names, list, args);
848 FFI_ARG_OR_RETURN (sc, pointer, list_pids, list, args);
849 FFI_ARG_OR_RETURN (sc, int, hang, bool, args);
850 FFI_ARGS_DONE_OR_RETURN (sc, args);
852 if (sc->vptr->list_length (sc, list_names)
853 != sc->vptr->list_length (sc, list_pids))
855 sc->vptr->mk_string (sc, "length of first two arguments must match");
857 err = ffi_list2argv (sc, list_names, &names, &count);
858 if (err == gpg_error (GPG_ERR_INV_VALUE))
859 return ffi_sprintf (sc, "%lu%s element of first argument is "
860 "neither string nor symbol",
861 (unsigned long) count,
862 ordinal_suffix ((int) count));
864 FFI_RETURN_ERR (sc, err);
866 err = ffi_list2intv (sc, list_pids, (int **) &pids, &count);
867 if (err == gpg_error (GPG_ERR_INV_VALUE))
868 return ffi_sprintf (sc, "%lu%s element of second argument is "
870 (unsigned long) count,
871 ordinal_suffix ((int) count));
873 FFI_RETURN_ERR (sc, err);
875 retcodes = xtrycalloc (sizeof *retcodes, count);
876 if (retcodes == NULL)
880 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
883 err = gnupg_wait_processes ((const char **) names, pids, count, hang,
885 if (err == GPG_ERR_GENERAL)
886 err = 0; /* Let the return codes speak. */
888 for (i = 0; i < count; i++)
890 (sc->vptr->cons) (sc,
891 sc->vptr->mk_integer (sc,
892 (long) retcodes[count-1-i]),
898 FFI_RETURN_POINTER (sc, retcodes_list);
903 do_pipe (scheme *sc, pointer args)
907 FFI_ARGS_DONE_OR_RETURN (sc, args);
908 err = gnupg_create_pipe (filedes);
910 _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
911 FFI_RETURN_POINTER (sc, IMC (filedes[0],
912 IMC (filedes[1], sc->NIL)));
917 do_inbound_pipe (scheme *sc, pointer args)
921 FFI_ARGS_DONE_OR_RETURN (sc, args);
922 err = gnupg_create_inbound_pipe (filedes, NULL, 0);
924 _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
925 FFI_RETURN_POINTER (sc, IMC (filedes[0],
926 IMC (filedes[1], sc->NIL)));
931 do_outbound_pipe (scheme *sc, pointer args)
935 FFI_ARGS_DONE_OR_RETURN (sc, args);
936 err = gnupg_create_outbound_pipe (filedes, NULL, 0);
938 _cons (sc, sc->vptr->mk_integer (sc, (unsigned long) (A)), (B), 1)
939 FFI_RETURN_POINTER (sc, IMC (filedes[0],
940 IMC (filedes[1], sc->NIL)));
946 /* Test helper functions. */
948 do_file_equal (scheme *sc, pointer args)
951 pointer result = sc->F;
952 char *a_name, *b_name;
955 FILE *a_stream = NULL, *b_stream = NULL;
956 struct stat a_stat, b_stat;
957 #define BUFFER_SIZE 1024
958 char a_buf[BUFFER_SIZE], b_buf[BUFFER_SIZE];
962 FFI_ARG_OR_RETURN (sc, char *, a_name, string, args);
963 FFI_ARG_OR_RETURN (sc, char *, b_name, string, args);
964 FFI_ARG_OR_RETURN (sc, int, binary, bool, args);
965 FFI_ARGS_DONE_OR_RETURN (sc, args);
967 mode = binary ? "rb" : "r";
968 a_stream = fopen (a_name, mode);
969 if (a_stream == NULL)
972 b_stream = fopen (b_name, mode);
973 if (b_stream == NULL)
976 if (fstat (fileno (a_stream), &a_stat) < 0)
979 if (fstat (fileno (b_stream), &b_stat) < 0)
982 if (binary && a_stat.st_size != b_stat.st_size)
985 fprintf (stderr, "Files %s and %s differ in size %lu != %lu\n",
986 a_name, b_name, (unsigned long) a_stat.st_size,
987 (unsigned long) b_stat.st_size);
992 while (! feof (a_stream))
994 chunk = sizeof a_buf;
996 chunk = fread (a_buf, 1, chunk, a_stream);
997 if (chunk == 0 && ferror (a_stream))
998 goto errout; /* some error */
1000 if (fread (b_buf, 1, chunk, b_stream) < chunk)
1002 if (feof (b_stream))
1003 goto out; /* short read */
1004 goto errout; /* some error */
1007 if (chunk > 0 && memcmp (a_buf, b_buf, chunk) != 0)
1011 fread (b_buf, 1, 1, b_stream);
1012 if (! feof (b_stream))
1013 goto out; /* b is longer */
1023 FFI_RETURN_POINTER (sc, result);
1025 err = gpg_error_from_syserror ();
1030 do_splice (scheme *sc, pointer args)
1036 pointer sinks, sink;
1037 FFI_ARG_OR_RETURN (sc, int, source, number, args);
1039 if (sinks == sc->NIL)
1040 return ffi_sprintf (sc, "need at least one sink");
1041 for (sink = sinks; sink != sc->NIL; sink = pair_cdr (sink), ffi_arg_index++)
1042 if (! sc->vptr->is_number (pair_car (sink)))
1043 return ffi_sprintf (sc, "%d%s argument is not a number",
1044 ffi_arg_index, ordinal_suffix (ffi_arg_index));
1048 bytes_read = read (source, buffer, sizeof buffer);
1049 if (bytes_read == 0)
1052 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
1054 for (sink = sinks; sink != sc->NIL; sink = pair_cdr (sink))
1056 int fd = sc->vptr->ivalue (pair_car (sink));
1058 ssize_t left = bytes_read;
1062 ssize_t written = write (fd, p, left);
1064 FFI_RETURN_ERR (sc, gpg_error_from_syserror ());
1065 assert (written <= left);
1075 do_string_index (scheme *sc, pointer args)
1082 FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
1083 FFI_ARG_OR_RETURN (sc, char, needle, character, args);
1084 if (args != sc->NIL)
1086 FFI_ARG_OR_RETURN (sc, ssize_t, offset, number, args);
1088 return ffi_sprintf (sc, "offset must be positive");
1089 if (offset > strlen (haystack))
1090 return ffi_sprintf (sc, "offset exceeds haystack");
1092 FFI_ARGS_DONE_OR_RETURN (sc, args);
1094 position = strchr (haystack+offset, needle);
1096 FFI_RETURN_INT (sc, position - haystack);
1098 FFI_RETURN_POINTER (sc, sc->F);
1102 do_string_rindex (scheme *sc, pointer args)
1109 FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
1110 FFI_ARG_OR_RETURN (sc, char, needle, character, args);
1111 if (args != sc->NIL)
1113 FFI_ARG_OR_RETURN (sc, ssize_t, offset, number, args);
1115 return ffi_sprintf (sc, "offset must be positive");
1116 if (offset > strlen (haystack))
1117 return ffi_sprintf (sc, "offset exceeds haystack");
1119 FFI_ARGS_DONE_OR_RETURN (sc, args);
1121 position = strrchr (haystack+offset, needle);
1123 FFI_RETURN_INT (sc, position - haystack);
1125 FFI_RETURN_POINTER (sc, sc->F);
1129 do_string_contains (scheme *sc, pointer args)
1134 FFI_ARG_OR_RETURN (sc, char *, haystack, string, args);
1135 FFI_ARG_OR_RETURN (sc, char *, needle, string, args);
1136 FFI_ARGS_DONE_OR_RETURN (sc, args);
1137 FFI_RETURN_POINTER (sc, strstr (haystack, needle) ? sc->T : sc->F);
1143 do_get_verbose (scheme *sc, pointer args)
1146 FFI_ARGS_DONE_OR_RETURN (sc, args);
1147 FFI_RETURN_INT (sc, verbose);
1151 do_set_verbose (scheme *sc, pointer args)
1154 int new_verbosity, old;
1155 FFI_ARG_OR_RETURN (sc, int, new_verbosity, number, args);
1156 FFI_ARGS_DONE_OR_RETURN (sc, args);
1159 verbose = new_verbosity;
1161 FFI_RETURN_INT (sc, old);
1166 ffi_list2argv (scheme *sc, pointer list, char ***argv, size_t *len)
1170 *len = sc->vptr->list_length (sc, list);
1171 *argv = xtrycalloc (*len + 1, sizeof **argv);
1173 return gpg_error_from_syserror ();
1175 for (i = 0; sc->vptr->is_pair (list); list = sc->vptr->pair_cdr (list))
1177 if (sc->vptr->is_string (sc->vptr->pair_car (list)))
1178 (*argv)[i++] = sc->vptr->string_value (sc->vptr->pair_car (list));
1179 else if (sc->vptr->is_symbol (sc->vptr->pair_car (list)))
1180 (*argv)[i++] = sc->vptr->symname (sc->vptr->pair_car (list));
1186 return gpg_error (GPG_ERR_INV_VALUE);
1194 ffi_list2intv (scheme *sc, pointer list, int **intv, size_t *len)
1198 *len = sc->vptr->list_length (sc, list);
1199 *intv = xtrycalloc (*len, sizeof **intv);
1201 return gpg_error_from_syserror ();
1203 for (i = 0; sc->vptr->is_pair (list); list = sc->vptr->pair_cdr (list))
1205 if (sc->vptr->is_number (sc->vptr->pair_car (list)))
1206 (*intv)[i++] = sc->vptr->ivalue (sc->vptr->pair_car (list));
1212 return gpg_error (GPG_ERR_INV_VALUE);
1221 ffi_schemify_name (const char *s, int macro)
1223 /* Fixme: We should use xtrystrdup and return NULL. However, this
1224 * requires a lot more changes. Simply returning S as done
1225 * originally is not an option. */
1226 char *n = xstrdup (s), *p;
1227 /* if (n == NULL) */
1230 for (p = n; *p; p++)
1232 *p = (char) tolower (*p);
1233 /* We convert _ to - in identifiers. We allow, however, for
1234 function names to start with a leading _. The functions in
1235 this namespace are not yet finalized and might change or
1236 vanish without warning. Use them with care. */
1246 ffi_sprintf (scheme *sc, const char *format, ...)
1253 va_start (listp, format);
1254 size = vsnprintf (NULL, 0, format, listp);
1257 expression = xtrymalloc (size + 1);
1258 if (expression == NULL)
1261 va_start (listp, format);
1262 written = vsnprintf (expression, size + 1, format, listp);
1265 assert (size == written);
1267 result = sc->vptr->mk_string (sc, expression);
1273 ffi_scheme_eval (scheme *sc, const char *format, ...)
1279 va_start (listp, format);
1280 size = vsnprintf (NULL, 0, format, listp);
1283 expression = xtrymalloc (size + 1);
1284 if (expression == NULL)
1287 va_start (listp, format);
1288 written = vsnprintf (expression, size + 1, format, listp);
1291 assert (size == written);
1293 sc->vptr->load_string (sc, expression);
1298 ffi_init (scheme *sc, const char *argv0, const char *scriptname,
1299 int argc, const char **argv)
1302 pointer args = sc->NIL;
1304 /* bitwise arithmetic */
1305 ffi_define_function (sc, logand);
1306 ffi_define_function (sc, logior);
1307 ffi_define_function (sc, logxor);
1308 ffi_define_function (sc, lognot);
1311 ffi_define_constant (sc, O_RDONLY);
1312 ffi_define_constant (sc, O_WRONLY);
1313 ffi_define_constant (sc, O_RDWR);
1314 ffi_define_constant (sc, O_CREAT);
1315 ffi_define_constant (sc, O_APPEND);
1322 ffi_define_constant (sc, O_BINARY);
1323 ffi_define_constant (sc, O_TEXT);
1324 ffi_define_constant (sc, STDIN_FILENO);
1325 ffi_define_constant (sc, STDOUT_FILENO);
1326 ffi_define_constant (sc, STDERR_FILENO);
1327 ffi_define_constant (sc, SEEK_SET);
1328 ffi_define_constant (sc, SEEK_CUR);
1329 ffi_define_constant (sc, SEEK_END);
1331 ffi_define_function (sc, sleep);
1332 ffi_define_function (sc, usleep);
1333 ffi_define_function (sc, chdir);
1334 ffi_define_function (sc, strerror);
1335 ffi_define_function (sc, getenv);
1336 ffi_define_function (sc, setenv);
1337 ffi_define_function_name (sc, "_exit", exit);
1338 ffi_define_function (sc, open);
1339 ffi_define_function (sc, fdopen);
1340 ffi_define_function (sc, close);
1341 ffi_define_function (sc, seek);
1342 ffi_define_function_name (sc, "_mkdtemp", mkdtemp);
1343 ffi_define_function (sc, unlink);
1344 ffi_define_function (sc, unlink_recursively);
1345 ffi_define_function (sc, rename);
1346 ffi_define_function (sc, getcwd);
1347 ffi_define_function (sc, mkdir);
1348 ffi_define_function (sc, rmdir);
1349 ffi_define_function (sc, get_isotime);
1350 ffi_define_function (sc, getpid);
1352 /* Random numbers. */
1353 ffi_define_function (sc, srandom);
1354 ffi_define_function (sc, random);
1355 ffi_define_function (sc, make_random_string);
1357 /* Process management. */
1358 ffi_define_function (sc, spawn_process);
1359 ffi_define_function (sc, spawn_process_fd);
1360 ffi_define_function (sc, wait_process);
1361 ffi_define_function (sc, wait_processes);
1362 ffi_define_function (sc, pipe);
1363 ffi_define_function (sc, inbound_pipe);
1364 ffi_define_function (sc, outbound_pipe);
1366 /* estream functions. */
1367 ffi_define_function_name (sc, "es-fclose", es_fclose);
1368 ffi_define_function_name (sc, "es-read", es_read);
1369 ffi_define_function_name (sc, "es-feof", es_feof);
1370 ffi_define_function_name (sc, "es-write", es_write);
1372 /* Test helper functions. */
1373 ffi_define_function (sc, file_equal);
1374 ffi_define_function (sc, splice);
1375 ffi_define_function (sc, string_index);
1376 ffi_define_function (sc, string_rindex);
1377 ffi_define_function_name (sc, "string-contains?", string_contains);
1379 /* User interface. */
1380 ffi_define_function (sc, flush_stdio);
1381 ffi_define_function (sc, prompt);
1383 /* Configuration. */
1384 ffi_define_function_name (sc, "*verbose*", get_verbose);
1385 ffi_define_function_name (sc, "*set-verbose!*", set_verbose);
1387 ffi_define (sc, "*argv0*", sc->vptr->mk_string (sc, argv0));
1388 ffi_define (sc, "*scriptname*", sc->vptr->mk_string (sc, scriptname));
1389 for (i = argc - 1; i >= 0; i--)
1391 pointer value = sc->vptr->mk_string (sc, argv[i]);
1392 args = (sc->vptr->cons) (sc, value, args);
1394 ffi_define (sc, "*args*", args);
1397 ffi_define (sc, "*pathsep*", sc->vptr->mk_character (sc, ';'));
1399 ffi_define (sc, "*pathsep*", sc->vptr->mk_character (sc, ':'));
1402 ffi_define (sc, "*win32*",
1411 ffi_define (sc, "*stdin*",
1412 sc->vptr->mk_port_from_file (sc, stdin, port_input));
1413 ffi_define (sc, "*stdout*",
1414 sc->vptr->mk_port_from_file (sc, stdout, port_output));
1415 ffi_define (sc, "*stderr*",
1416 sc->vptr->mk_port_from_file (sc, stderr, port_output));