summaryrefslogtreecommitdiff
path: root/libguile/simpos.c
diff options
context:
space:
mode:
authorRob Browning <rlb@defaultvalue.org>2003-11-19 21:40:32 +0000
committerRob Browning <rlb@defaultvalue.org>2003-11-19 21:40:32 +0000
commit0db17ef9abd59da51ebc30d90fb2dc482b02a4a1 (patch)
tree7d9dd355f05657d4a00dae002916c49eec33325d /libguile/simpos.c
parent8141bd983dc6f29445016e56c786bae26f705a4c (diff)
downloadguile-0db17ef9abd59da51ebc30d90fb2dc482b02a4a1.tar.gz
(scm_system_star): new function.
Diffstat (limited to 'libguile/simpos.c')
-rw-r--r--libguile/simpos.c117
1 files 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 <unistd.h>
#endif
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#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"