mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Factor start_child out of open_process
* libguile/posix.c (start_child): Factor out from open_process. Based on initial work by Eli Zaretskii.
This commit is contained in:
parent
f632d45c69
commit
10ae9cc601
1 changed files with 105 additions and 85 deletions
222
libguile/posix.c
222
libguile/posix.c
|
@ -1236,71 +1236,21 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0,
|
||||||
return scm_from_int (pid);
|
return scm_from_int (pid);
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
#endif /* HAVE_FORK */
|
||||||
|
|
||||||
|
#ifdef HAVE_FORK
|
||||||
|
#define HAVE_START_CHILD 1
|
||||||
/* Since Guile uses threads, we have to be very careful to avoid calling
|
/* Since Guile uses threads, we have to be very careful to avoid calling
|
||||||
functions that are not async-signal-safe in the child. That's why
|
functions that are not async-signal-safe in the child. That's why
|
||||||
this function is implemented in C. */
|
this function is implemented in C. */
|
||||||
static SCM
|
static pid_t
|
||||||
scm_open_process (SCM mode, SCM prog, SCM args)
|
start_child (const char *exec_file, char **exec_argv,
|
||||||
#define FUNC_NAME "open-process"
|
int reading, int c2p[2], int writing, int p2c[2],
|
||||||
|
int in, int out, int err)
|
||||||
{
|
{
|
||||||
long mode_bits;
|
|
||||||
int reading, writing;
|
|
||||||
int c2p[2]; /* Child to parent. */
|
|
||||||
int p2c[2]; /* Parent to child. */
|
|
||||||
int in = -1, out = -1, err = -1;
|
|
||||||
int pid;
|
int pid;
|
||||||
char *exec_file;
|
|
||||||
char **exec_argv;
|
|
||||||
int max_fd = 1024;
|
int max_fd = 1024;
|
||||||
|
|
||||||
exec_file = scm_to_locale_string (prog);
|
|
||||||
exec_argv = scm_i_allocate_string_pointers (scm_cons (prog, args));
|
|
||||||
|
|
||||||
mode_bits = scm_i_mode_bits (mode);
|
|
||||||
reading = mode_bits & SCM_RDNG;
|
|
||||||
writing = mode_bits & SCM_WRTNG;
|
|
||||||
|
|
||||||
if (reading)
|
|
||||||
{
|
|
||||||
if (pipe (c2p))
|
|
||||||
{
|
|
||||||
int errno_save = errno;
|
|
||||||
free (exec_file);
|
|
||||||
errno = errno_save;
|
|
||||||
SCM_SYSERROR;
|
|
||||||
}
|
|
||||||
out = c2p[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writing)
|
|
||||||
{
|
|
||||||
if (pipe (p2c))
|
|
||||||
{
|
|
||||||
int errno_save = errno;
|
|
||||||
free (exec_file);
|
|
||||||
if (reading)
|
|
||||||
{
|
|
||||||
close (c2p[0]);
|
|
||||||
close (c2p[1]);
|
|
||||||
}
|
|
||||||
errno = errno_save;
|
|
||||||
SCM_SYSERROR;
|
|
||||||
}
|
|
||||||
in = p2c[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
SCM port;
|
|
||||||
|
|
||||||
if (SCM_OPOUTFPORTP ((port = scm_current_error_port ())))
|
|
||||||
err = SCM_FPORT_FDES (port);
|
|
||||||
if (out == -1 && SCM_OPOUTFPORTP ((port = scm_current_output_port ())))
|
|
||||||
out = SCM_FPORT_FDES (port);
|
|
||||||
if (in == -1 && SCM_OPINFPORTP ((port = scm_current_input_port ())))
|
|
||||||
in = SCM_FPORT_FDES (port);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_NOFILE)
|
#if defined (HAVE_GETRLIMIT) && defined (RLIMIT_NOFILE)
|
||||||
{
|
{
|
||||||
struct rlimit lim = { 0, 0 };
|
struct rlimit lim = { 0, 0 };
|
||||||
|
@ -1311,44 +1261,10 @@ scm_open_process (SCM mode, SCM prog, SCM args)
|
||||||
|
|
||||||
pid = fork ();
|
pid = fork ();
|
||||||
|
|
||||||
if (pid == -1)
|
if (pid != 0)
|
||||||
{
|
/* The parent, with either and error (pid == -1), or the PID of the
|
||||||
int errno_save = errno;
|
child. Return directly in either case. */
|
||||||
free (exec_file);
|
return pid;
|
||||||
if (reading)
|
|
||||||
{
|
|
||||||
close (c2p[0]);
|
|
||||||
close (c2p[1]);
|
|
||||||
}
|
|
||||||
if (writing)
|
|
||||||
{
|
|
||||||
close (p2c[0]);
|
|
||||||
close (p2c[1]);
|
|
||||||
}
|
|
||||||
errno = errno_save;
|
|
||||||
SCM_SYSERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid)
|
|
||||||
/* Parent. */
|
|
||||||
{
|
|
||||||
SCM read_port = SCM_BOOL_F, write_port = SCM_BOOL_F;
|
|
||||||
|
|
||||||
/* There is no sense in catching errors on close(). */
|
|
||||||
if (reading)
|
|
||||||
{
|
|
||||||
close (c2p[1]);
|
|
||||||
read_port = scm_fdes_to_port (c2p[0], "r0", sym_read_pipe);
|
|
||||||
}
|
|
||||||
if (writing)
|
|
||||||
{
|
|
||||||
close (p2c[0]);
|
|
||||||
write_port = scm_fdes_to_port (p2c[1], "w0", sym_write_pipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scm_values
|
|
||||||
(scm_list_3 (read_port, write_port, scm_from_int (pid)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The child. */
|
/* The child. */
|
||||||
if (reading)
|
if (reading)
|
||||||
|
@ -1398,16 +1314,118 @@ scm_open_process (SCM mode, SCM prog, SCM args)
|
||||||
if (err > 0)
|
if (err > 0)
|
||||||
{
|
{
|
||||||
char *msg = strerror (errno);
|
char *msg = strerror (errno);
|
||||||
fprintf (fdopen (err, "a"), "In execlp of %s: %s\n",
|
fprintf (fdopen (err, "a"), "In execvp of %s: %s\n",
|
||||||
exec_file, msg);
|
exec_file, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
|
|
||||||
/* Not reached. */
|
/* Not reached. */
|
||||||
return SCM_BOOL_F;
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_START_CHILD
|
||||||
|
static SCM
|
||||||
|
scm_open_process (SCM mode, SCM prog, SCM args)
|
||||||
|
#define FUNC_NAME "open-process"
|
||||||
|
{
|
||||||
|
long mode_bits;
|
||||||
|
int reading, writing;
|
||||||
|
int c2p[2]; /* Child to parent. */
|
||||||
|
int p2c[2]; /* Parent to child. */
|
||||||
|
int in = -1, out = -1, err = -1;
|
||||||
|
int pid;
|
||||||
|
char *exec_file;
|
||||||
|
char **exec_argv;
|
||||||
|
SCM read_port = SCM_BOOL_F, write_port = SCM_BOOL_F;
|
||||||
|
|
||||||
|
exec_file = scm_to_locale_string (prog);
|
||||||
|
exec_argv = scm_i_allocate_string_pointers (scm_cons (prog, args));
|
||||||
|
|
||||||
|
mode_bits = scm_i_mode_bits (mode);
|
||||||
|
reading = mode_bits & SCM_RDNG;
|
||||||
|
writing = mode_bits & SCM_WRTNG;
|
||||||
|
|
||||||
|
if (reading)
|
||||||
|
{
|
||||||
|
if (pipe (c2p))
|
||||||
|
{
|
||||||
|
int errno_save = errno;
|
||||||
|
free (exec_file);
|
||||||
|
errno = errno_save;
|
||||||
|
SCM_SYSERROR;
|
||||||
|
}
|
||||||
|
out = c2p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (writing)
|
||||||
|
{
|
||||||
|
if (pipe (p2c))
|
||||||
|
{
|
||||||
|
int errno_save = errno;
|
||||||
|
free (exec_file);
|
||||||
|
if (reading)
|
||||||
|
{
|
||||||
|
close (c2p[0]);
|
||||||
|
close (c2p[1]);
|
||||||
|
}
|
||||||
|
errno = errno_save;
|
||||||
|
SCM_SYSERROR;
|
||||||
|
}
|
||||||
|
in = p2c[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
SCM port;
|
||||||
|
|
||||||
|
if (SCM_OPOUTFPORTP ((port = scm_current_error_port ())))
|
||||||
|
err = SCM_FPORT_FDES (port);
|
||||||
|
if (out == -1 && SCM_OPOUTFPORTP ((port = scm_current_output_port ())))
|
||||||
|
out = SCM_FPORT_FDES (port);
|
||||||
|
if (in == -1 && SCM_OPINFPORTP ((port = scm_current_input_port ())))
|
||||||
|
in = SCM_FPORT_FDES (port);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = start_child (exec_file, exec_argv, reading, c2p, writing, p2c,
|
||||||
|
in, out, err);
|
||||||
|
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
int errno_save = errno;
|
||||||
|
free (exec_file);
|
||||||
|
if (reading)
|
||||||
|
{
|
||||||
|
close (c2p[0]);
|
||||||
|
close (c2p[1]);
|
||||||
|
}
|
||||||
|
if (writing)
|
||||||
|
{
|
||||||
|
close (p2c[0]);
|
||||||
|
close (p2c[1]);
|
||||||
|
}
|
||||||
|
errno = errno_save;
|
||||||
|
SCM_SYSERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is no sense in catching errors on close(). */
|
||||||
|
if (reading)
|
||||||
|
{
|
||||||
|
close (c2p[1]);
|
||||||
|
read_port = scm_fdes_to_port (c2p[0], "r0", sym_read_pipe);
|
||||||
|
}
|
||||||
|
if (writing)
|
||||||
|
{
|
||||||
|
close (p2c[0]);
|
||||||
|
write_port = scm_fdes_to_port (p2c[1], "w0", sym_write_pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scm_values (scm_list_3 (read_port,
|
||||||
|
write_port,
|
||||||
|
scm_from_int (pid)));
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
#endif /* HAVE_FORK */
|
#endif /* HAVE_START_CHILD */
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
# include "win32-uname.h"
|
# include "win32-uname.h"
|
||||||
|
@ -2215,13 +2233,13 @@ SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0,
|
||||||
#endif /* HAVE_GETHOSTNAME */
|
#endif /* HAVE_GETHOSTNAME */
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_START_CHILD
|
||||||
static void
|
static void
|
||||||
scm_init_popen (void)
|
scm_init_popen (void)
|
||||||
{
|
{
|
||||||
scm_c_define_gsubr ("open-process", 2, 0, 1, scm_open_process);
|
scm_c_define_gsubr ("open-process", 2, 0, 1, scm_open_process);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* HAVE_START_CHILD */
|
||||||
|
|
||||||
void
|
void
|
||||||
scm_init_posix ()
|
scm_init_posix ()
|
||||||
|
@ -2320,11 +2338,13 @@ scm_init_posix ()
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
#ifdef HAVE_FORK
|
||||||
scm_add_feature ("fork");
|
scm_add_feature ("fork");
|
||||||
|
#endif /* HAVE_FORK */
|
||||||
|
#ifdef HAVE_START_CHILD
|
||||||
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
|
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
|
||||||
"scm_init_popen",
|
"scm_init_popen",
|
||||||
(scm_t_extension_init_func) scm_init_popen,
|
(scm_t_extension_init_func) scm_init_popen,
|
||||||
NULL);
|
NULL);
|
||||||
#endif /* HAVE_FORK */
|
#endif /* HAVE_START_CHILD */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue