From 0db17ef9abd59da51ebc30d90fb2dc482b02a4a1 Mon Sep 17 00:00:00 2001 From: Rob Browning Date: Wed, 19 Nov 2003 21:40:32 +0000 Subject: [PATCH] (scm_system_star): new function. --- libguile/simpos.c | 117 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/libguile/simpos.c b/libguile/simpos.c index c9c83935c..caeb753c4 100644 --- a/libguile/simpos.c +++ b/libguile/simpos.c @@ -39,13 +39,18 @@ #ifdef HAVE_UNISTD_H #include #endif +#if HAVE_SYS_WAIT_H +# include +#endif + +#include "posix.h" extern int system(); #ifdef HAVE_SYSTEM -SCM_DEFINE (scm_system, "system", 0, 1, 0, +SCM_DEFINE (scm_system, "system", 0, 1, 0, (SCM cmd), "Execute @var{cmd} using the operating system's \"command\n" "processor\". Under Unix this is usually the default shell\n" @@ -63,7 +68,7 @@ SCM_DEFINE (scm_system, "system", 0, 1, 0, { rv = system (NULL); return SCM_BOOL(rv); - } + } SCM_VALIDATE_STRING (1, cmd); errno = 0; rv = system (SCM_STRING_CHARS (cmd)); @@ -74,6 +79,114 @@ SCM_DEFINE (scm_system, "system", 0, 1, 0, #undef FUNC_NAME #endif /* HAVE_SYSTEM */ + +#ifdef HAVE_SYSTEM +#ifdef HAVE_WAITPID + +/* return a newly allocated array of char pointers to each of the strings + in args, with a terminating NULL pointer. */ +/* Note: a similar function is defined in dynl.c, but we don't necessarily + want to export it. */ +static char ** +allocate_string_pointers (SCM args) +{ + char **result; + int n_args = scm_ilength (args); + int i; + + SCM_ASSERT (n_args >= 0, args, SCM_ARGn, "allocate_string_pointers"); + result = (char **) scm_malloc ((n_args + 1) * sizeof (char *)); + result[n_args] = NULL; + for (i = 0; i < n_args; i++) + { + SCM car = SCM_CAR (args); + + if (!SCM_STRINGP (car)) + { + free (result); + scm_wrong_type_arg ("allocate_string_pointers", SCM_ARGn, car); + } + result[i] = SCM_STRING_CHARS (SCM_CAR (args)); + args = SCM_CDR (args); + } + return result; +} + +SCM_DEFINE (scm_system_star, "system*", 0, 0, 1, + (SCM args), +"Execute the command indicated by @var{args}. The first element must\n" +"be a string indicating the command to be executed, and the remaining\n" +"items must be strings representing each of the arguments to that\n" +"command.\n" +"\n" +"This function returns the exit status of the command as provided by\n" +"@code{waitpid}. This value can be handled with @code{status:exit-val}\n" +"and the related functions.\n" +"\n" +"@code{system*} is similar to @code{system}, but accepts only one\n" +"string per-argument, and performs no shell interpretation. The\n" +"command is executed using fork and execlp. Accordingly this function\n" +"may be safer than @code{system} in situations where shell\n" +"interpretation is not required.\n" +"\n" +"Example: (system* \"echo\" \"foo\" \"bar\")") +#define FUNC_NAME s_scm_system_star +{ + if (SCM_NULLP (args)) + SCM_WRONG_NUM_ARGS (); + + if (SCM_CONSP (args)) + { + SCM oldint; + SCM oldquit; + SCM sig_ign; + SCM sigint; + SCM sigquit; + int pid; + char **execargv; + + SCM_VALIDATE_STRING (1, SCM_CAR (args)); + /* allocate before fork */ + execargv = allocate_string_pointers (args); + + /* make sure the child can't kill us (as per normal system call) */ + sig_ign = scm_long2num ((long) SIG_IGN); + sigint = scm_long2num (SIGINT); + sigquit = scm_long2num (SIGQUIT); + oldint = scm_sigaction (sigint, sig_ign, SCM_UNDEFINED); + oldquit = scm_sigaction (sigquit, sig_ign, SCM_UNDEFINED); + + pid = fork (); + if (pid == -1) + SCM_SYSERROR; + else if (pid) + { + int wait_result; + int status; + SCM_SYSCALL (wait_result = waitpid (pid, &status, 0)); + if (wait_result == -1) SCM_SYSERROR; + scm_sigaction (sigint, SCM_CAR (oldint), SCM_CDR (oldint)); + scm_sigaction (sigquit, SCM_CAR (oldquit), SCM_CDR (oldquit)); + scm_remember_upto_here_2 (oldint, oldquit); + return SCM_MAKINUM (0L + status); + } + else + { + execvp (SCM_STRING_CHARS (SCM_CAR (args)), execargv); + scm_remember_upto_here_1 (args); + SCM_SYSERROR; + /* not reached. */ + return SCM_BOOL_F; + } + } + else + SCM_WRONG_TYPE_ARG (1, SCM_CAR (args)); +} +#undef FUNC_NAME +#endif /* HAVE_WAITPID */ +#endif /* HAVE_SYSTEM */ + + SCM_DEFINE (scm_getenv, "getenv", 1, 0, 0, (SCM nam), "Looks up the string @var{name} in the current environment. The return\n" -- 2.20.1