* child_info.h (child_info_spawn::__stdin): New element.
(child_info_spawn::__stdin): Ditto. (CURR_CHILD_INFO_MAGIC): Regenerate. * dcrt0.cc (check_sanity_and_sync): Minor cleanup. (child_info_spawn::handle_spawn): Handle new __std* elements by calling move_fd. * dtable.cc (dtable::move_fd): Define new function. * dtable.h (dtable::move_fd): Declare new function. * fhandler.h (fhandler_pipe::popen_pid): Declare new element. * fhandler.h (fhandler_pipe::get_popen_pid): Define new function. * fhandler.h (fhandler_pipe::set_popen_pid): Ditto. * pipe.cc (fhandler_pipe::fhandler_pipe): Zero popen_pid. (fhandler_pipe::dup): Ditto. * spawn.cc (handle): Change second argument to bool. (spawn_guts): Accept __stdin/__stdout arguments and set them appropriately in child_info structure and in STARTUPINFO structure. * syscalls.cc (popen): New cygwin-specific implementation using spawn. (pclose): Ditto. * winsup.h (spawn_guts): Accommodate new arguments for spawn_guts. * fhandler.cc (fhandler_base::set_no_inheritance): Make second arg a bool. * fhandler.h (fhandler_base::set_no_inheritance): Ditto for declaration. * child_info.h (child_info::msv_count): Rename from the now-inappropriate "zero". (child_info_spawn::filler): Add filler to work around Vista bug. (child_info_fork::filler): Ditto. * dcrt0.cc (get_cygwin_startup_info): Remove "zero" check since it is now always filled out. * fork.cc (frok::parent): Move ch.zero manipulation to constructor. * spawn.cc (spawn_guts): Ditto. Remove _ch wrapper. * sigproc.cc (child_info::child_info): Initialize starter[]. * shared.cc (shared_info::heap_slop_size): Remove noisy system_printfs. * shared_info.h (CURR_SHARED_MAGIC): Regenerate.
This commit is contained in:
@@ -40,6 +40,7 @@ details. */
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/wait.h>
|
||||
#include <winnls.h>
|
||||
#include <wininet.h>
|
||||
#include <winioctl.h>
|
||||
@@ -3242,3 +3243,109 @@ funlockfile (FILE *file)
|
||||
{
|
||||
_funlockfile (file);
|
||||
}
|
||||
|
||||
extern "C" FILE *
|
||||
popen (const char *command, const char *type)
|
||||
{
|
||||
int fds[2];
|
||||
|
||||
if (pipe (fds) < 0)
|
||||
return NULL;
|
||||
int fd, other_fd, __stdin, __stdout, stdwhat;
|
||||
if (type[1] != '\0')
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
if (*type == 'r')
|
||||
{
|
||||
__stdin = -1;
|
||||
stdwhat = 1;
|
||||
other_fd = __stdout = fds[1];
|
||||
fd = fds[0];
|
||||
}
|
||||
else if (*type == 'w')
|
||||
{
|
||||
__stdout = -1;
|
||||
stdwhat = 0;
|
||||
other_fd = __stdin = fds[0];
|
||||
fd = fds[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *fp = fdopen (fd, type);
|
||||
fcntl (fd, F_SETFD, fcntl (fd, F_GETFD, 0) | FD_CLOEXEC);
|
||||
|
||||
if (!fp)
|
||||
goto err;
|
||||
|
||||
pid_t pid;
|
||||
const char *argv[4];
|
||||
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = command;
|
||||
argv[3] = NULL;
|
||||
|
||||
{
|
||||
lock_process now;
|
||||
int state = fcntl (stdwhat, F_GETFD, 0);
|
||||
fcntl (stdwhat, F_SETFD, state | FD_CLOEXEC);
|
||||
pid = spawn_guts ("/bin/sh", argv, cur_environ (), _P_NOWAIT,
|
||||
__stdin, __stdout);
|
||||
fcntl (stdwhat, F_SETFD, state);
|
||||
}
|
||||
|
||||
if (pid < 0)
|
||||
goto err;
|
||||
close (other_fd);
|
||||
|
||||
fhandler_pipe *fh = (fhandler_pipe *) cygheap->fdtab[fd];
|
||||
fh->set_popen_pid (pid);
|
||||
|
||||
return fp;
|
||||
|
||||
err:
|
||||
int save_errno = get_errno ();
|
||||
close (fds[0]);
|
||||
close (fds[1]);
|
||||
set_errno (save_errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
pclose (FILE *fp)
|
||||
{
|
||||
fhandler_pipe *fh = (fhandler_pipe *) cygheap->fdtab[fileno(fp)];
|
||||
|
||||
if (fh->get_device () != FH_PIPEW && fh->get_device () != FH_PIPER)
|
||||
{
|
||||
set_errno (EBADF);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pid = fh->get_popen_pid ();
|
||||
if (!pid)
|
||||
{
|
||||
set_errno (ECHILD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fclose (fp))
|
||||
return -1;
|
||||
|
||||
int status;
|
||||
while (1)
|
||||
if (waitpid (pid, &status, 0) == pid)
|
||||
break;
|
||||
else if (get_errno () == EINTR)
|
||||
continue;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Reference in New Issue
Block a user