mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
(scm_system_star): new function.
This commit is contained in:
parent
8141bd983d
commit
0db17ef9ab
1 changed files with 115 additions and 2 deletions
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue