Eli Zaretskii <e...@gnu.org> writes: > This patch allows the MinGW build of Guile to have the process related > functions (open-process, kill, waitpid, status:exit-val, etc.). > > Implement open-process and related functions on MinGW > > * libguile/filesys.c (fsync, link) [__MINGW32__]: Redirect Posix > functions to their Windows equivalents.
Gnulib has an 'fsync' module that apparently implements it on MinGW. I think we should use that instead, no? > (scm_chown, scm_open_fdes, scm_open, scm_close, scm_close_fdes) > (scm_link, scm_chdir, set_element, fill_select_type) > (get_element, retrieve_select_type, scm_select, scm_fcntl) > (scm_fsync, scm_symlink, scm_readlink, scm_copy_file, scm_sendfile) > (scm_dir_print, scm_dir_free): These functions are no longer > wholesale ifdef'ed away if HAVE_POSIX is not defined. As I wrote in my other recent message, I think we should simply recommend that MinGW builds be done without "--disable-posix", since we have at least one report that it works now. > (scm_init_filesys): Don't ifdef away parts of the function when > HAVE_POSIX is not defined. > > diff --git a/libguile/posix.c b/libguile/posix.c > index 0443f95..69652a3 100644 > --- a/libguile/posix.c > +++ b/libguile/posix.c > @@ -85,6 +85,27 @@ > #if HAVE_SYS_WAIT_H > # include <sys/wait.h> > #endif > +#ifdef __MINGW32__ > +# define WEXITSTATUS(stat_val) ((stat_val) & 255) > +/* Windows reports exit status from fatal exceptions as 0xC0000nnn > + codes, see winbase.h. We usurp codes above 0xC0000200 for SIGxxx > + signals. */ > +# define WIFEXITED(stat_val) (((stat_val) & 0xC0000000) == 0) > +# define WIFSIGNALED(stat_val) (((stat_val) & 0xC0000000) != 0) > +# define WTERMSIG(stat_val) ((stat_val > 0xC0000200) ? stat_val - > 0xC0000200 : stat_val) > +# define WIFSTOPPED(stat_val) (0) > +# define WSTOPSIG(stat_var) (0) > +# include <process.h> > +# define waitpid(p,s,o) _cwait(s, p, WAIT_CHILD) > +# define HAVE_WAITPID 1 > +# define getuid() (500) /* Local Administrator */ > +# define getgid() (513) /* None */ > +# define setuid(u) (0) > +# define setgid(g) (0) > +# define pipe(f) _pipe(f, 0, O_NOINHERIT) > +# define WIN32_LEAN_AND_MEAN > +# include <windows.h> > +#endif > #ifndef WEXITSTATUS > # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) > #endif > @@ -674,6 +695,25 @@ SCM_DEFINE (scm_kill, "kill", 2, 0, 0, > goto err; > } > } > +#ifdef __MINGW32__ > + else > + { > + HANDLE ph = OpenProcess (PROCESS_TERMINATE, 0, scm_to_int (pid)); > + int s = scm_to_int (sig); > + > + if (!ph) > + { > + errno = EPERM; > + goto err; > + } > + if (!TerminateProcess (ph, 0xC0000200 + s)) > + { > + errno = EINVAL; > + goto err; > + } > + CloseHandle (ph); > + } > +#endif /* __MINGW32__ */ > #endif > return SCM_UNSPECIFIED; > } > @@ -720,6 +760,7 @@ SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0, > { > int i; > int status; > +#ifndef __MINGW32__ > int ioptions; > if (SCM_UNBNDP (options)) > ioptions = 0; > @@ -728,6 +769,7 @@ SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0, > /* Flags are interned in scm_init_posix. */ > ioptions = scm_to_int (options); > } > +#endif > SCM_SYSCALL (i = waitpid (scm_to_int (pid), &status, ioptions)); > if (i == -1) > SCM_SYSERROR; > @@ -736,7 +778,6 @@ SCM_DEFINE (scm_waitpid, "waitpid", 1, 1, 0, > #undef FUNC_NAME > #endif /* HAVE_WAITPID */ > > -#ifndef __MINGW32__ > SCM_DEFINE (scm_status_exit_val, "status:exit-val", 1, 0, 0, > (SCM status), > "Return the exit status value, as would be set if a process\n" > @@ -787,7 +828,6 @@ SCM_DEFINE (scm_status_stop_sig, "status:stop-sig", 1, 0, > 0, > return SCM_BOOL_F; > } > #undef FUNC_NAME > -#endif /* __MINGW32__ */ > > #ifdef HAVE_GETPPID > SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0, > @@ -802,7 +842,6 @@ SCM_DEFINE (scm_getppid, "getppid", 0, 0, 0, > #endif /* HAVE_GETPPID */ > > > -#ifndef __MINGW32__ > SCM_DEFINE (scm_getuid, "getuid", 0, 0, 0, > (), > "Return an integer representing the current real user ID.") > @@ -932,7 +971,6 @@ SCM_DEFINE (scm_setegid, "setegid", 1, 0, 0, > > } > #undef FUNC_NAME > -#endif > > > #ifdef HAVE_GETPGRP > @@ -1248,6 +1286,7 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, > return scm_from_int (pid); > } > #undef FUNC_NAME > +#endif /* HAVE_FORK */ > > /* 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 > @@ -1321,7 +1360,130 @@ scm_open_process (SCM mode, SCM prog, SCM args) > } > #endif > > +#ifdef HAVE_FORK > pid = fork (); > +#elif defined(__MINGW32__) > + { > + int save_stdin = -1, save_stdout = -1; > + int errno_save; > + > + if (reading) > + { > + save_stdout = dup (1); > + errno_save = errno; > + if (save_stdout == -1) > + { > + close (c2p[0]); > + close (c2p[1]); > + free (exec_file); > + errno = errno_save; > + SCM_SYSERROR; > + } > + } > + > + if (writing) > + { > + save_stdin = dup (0); > + errno_save = errno; > + if (save_stdin == -1) > + { > + if (reading) > + close (save_stdout); > + close (p2c[0]); > + close (p2c[1]); > + free (exec_file); > + errno = errno_save; > + SCM_SYSERROR; > + } > + } > + > + if (reading) > + { > + close (1); > + if (dup (c2p[1]) != 1) > + { > + errno_save = errno; > + close (save_stdout); > + close (c2p[0]); > + close (c2p[1]); > + if (writing) > + { > + close (save_stdin); > + close (p2c[0]); > + close (p2c[1]); > + } > + errno = errno_save; > + SCM_SYSERROR; > + } > + close (c2p[1]); > + } > + if (writing) > + { > + close (0); > + if (dup (p2c[0]) != 0) > + { > + errno_save = errno; > + close (save_stdin); > + close (p2c[0]); > + close (p2c[1]); > + if (reading) > + { > + close (save_stdout); > + close (c2p[0]); > + close (c2p[1]); > + } > + errno = errno_save; > + SCM_SYSERROR; > + } > + close (p2c[0]); > + } > + > + pid = spawnvp (P_NOWAIT, exec_file, exec_argv); > + errno_save = errno; > + > + if (reading) > + { > + close (1); > + if (dup (save_stdout) != 1) > + { > + if (writing) > + close (save_stdin); > + close (save_stdout); > + close (p2c[1]); > + close (c2p[0]); > + errno = errno_save; > + SCM_SYSERROR; > + } > + close (save_stdout); > + } > + if (writing) > + { > + close (0); > + if (dup (save_stdin) != 0) > + { > + if (reading) > + close (save_stdout); > + close (save_stdin); > + close (p2c[1]); > + close (c2p[0]); > + errno = errno_save; > + SCM_SYSERROR; > + } > + close (save_stdin); > + } > + > + if (pid < 0) > + errno = errno_save; > + } > +#else > + close (c2p[0]); > + close (c2p[1]); > + close (p2c[0]); > + close (p2c[1]); > + free (exec_file); > + errno = ENOSYS; > + SCM_SYSERROR; > +#endif /* HAVE_FORK */ > > if (pid == -1) > { > @@ -1330,14 +1492,28 @@ scm_open_process (SCM mode, SCM prog, SCM args) > if (reading) > { > close (c2p[0]); > +#ifdef HAVE_FORK > close (c2p[1]); > +#endif > } > if (writing) > { > +#ifdef HAVE_FORK > close (p2c[0]); > +#endif > close (p2c[1]); > } > errno = errno_save; > + > +#ifndef HAVE_FORK > + /* The exec failed! There is nothing sensible to do. */ > + if (err > 0) > + { > + char *msg = strerror (errno); > + fprintf (fdopen (err, "a"), "In spawnvp of %s: %s\n", > + exec_file, msg); > + } > +#endif > SCM_SYSERROR; > } > > @@ -1363,7 +1539,8 @@ scm_open_process (SCM mode, SCM prog, SCM args) > return scm_values > (scm_list_3 (read_port, write_port, scm_from_int (pid))); > } > - > + > +#ifdef HAVE_FORK > /* The child. */ > if (reading) > close (c2p[0]); > @@ -1412,16 +1589,16 @@ scm_open_process (SCM mode, SCM prog, SCM args) > if (err > 0) > { > 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); > } > > _exit (EXIT_FAILURE); > /* Not reached. */ > return SCM_BOOL_F; > +#endif /* HAVE_FORK */ > } > #undef FUNC_NAME > -#endif /* HAVE_FORK */ > > #ifdef __MINGW32__ > # include "win32-uname.h" > @@ -2239,13 +2416,11 @@ SCM_DEFINE (scm_gethostname, "gethostname", 0, 0, 0, > #endif /* HAVE_GETHOSTNAME */ > > > -#ifdef HAVE_FORK > static void > scm_init_popen (void) > { > scm_c_define_gsubr ("open-process", 2, 0, 1, scm_open_process); > } > -#endif > > void > scm_init_posix () > @@ -2338,11 +2513,11 @@ scm_init_posix () > > #ifdef HAVE_FORK > scm_add_feature ("fork"); > +#endif /* HAVE_FORK */ > scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION, > "scm_init_popen", > (scm_t_extension_init_func) scm_init_popen, > NULL); > -#endif /* HAVE_FORK */ > } > > /*