mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-09 02:29:07 +08:00
Cygwin: AF_UNIX: SCM_RIGHTS: support pty slave descriptors
This is the first case where the fhandler being sent uses an archetype. This archetype is of no use to the receiving process, so we have to make the following changes: - Modify fhandler_pty_slave::dup so that it duplicates handles when it is called on an fhandler that doesn't yet have an archetype. - Modify dtable::dup_worker so that it creates an archetype for the new fhandler after fhandler_pty_slave::dup returns.
This commit is contained in:
parent
81e265492a
commit
c605ea0d6d
@ -677,11 +677,21 @@ out:
|
||||
fhandler_base *
|
||||
dtable::dup_worker (fhandler_base *oldfh, int flags, DWORD src_pid)
|
||||
{
|
||||
bool need_new_arch = false;
|
||||
fhandler_base *newfh = oldfh->clone ();
|
||||
|
||||
if (!newfh)
|
||||
debug_printf ("clone failed");
|
||||
else
|
||||
{
|
||||
debug_printf ("clone failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If we're duplicating an fhandler from a different process and we
|
||||
use an archetype, the old archetype is useless. */
|
||||
if (src_pid && oldfh->archetype
|
||||
&& !(newfh->archetype = find_archetype (oldfh->dev ())))
|
||||
need_new_arch = true;
|
||||
|
||||
if (!oldfh->archetype)
|
||||
newfh->set_handle (NULL);
|
||||
|
||||
@ -691,9 +701,20 @@ dtable::dup_worker (fhandler_base *oldfh, int flags, DWORD src_pid)
|
||||
delete newfh;
|
||||
newfh = NULL;
|
||||
debug_printf ("oldfh->dup failed");
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
if (need_new_arch)
|
||||
{
|
||||
newfh->set_name (newfh->dev ().name ());
|
||||
newfh->archetype = newfh->clone ();
|
||||
debug_printf ("created an archetype (%p) for %s(%d/%d)",
|
||||
newfh->archetype, newfh->get_name (),
|
||||
newfh->dev ().get_major (), newfh->dev ().get_minor ());
|
||||
newfh->archetype->archetype = NULL;
|
||||
newfh->archetype->usecount = 0;
|
||||
*add_archetype () = newfh->archetype;
|
||||
}
|
||||
|
||||
/* Don't increment refcnt here since we don't know if this is a
|
||||
allocated fd. So we leave this chore to the caller. */
|
||||
|
||||
@ -704,8 +725,8 @@ dtable::dup_worker (fhandler_base *oldfh, int flags, DWORD src_pid)
|
||||
newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
|
||||
debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
|
||||
oldfh->get_handle (), newfh->get_handle ());
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return newfh;
|
||||
}
|
||||
|
||||
|
@ -2008,6 +2008,7 @@ fhandler_socket_unix::serialize (int fd)
|
||||
switch (dev.get_major ())
|
||||
{
|
||||
case DEV_PTYS_MAJOR:
|
||||
break;
|
||||
case DEV_PTYM_MAJOR:
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_CDROM_MAJOR:
|
||||
@ -2091,20 +2092,37 @@ fhandler_socket_unix::deserialize (void *bufp)
|
||||
{
|
||||
fh_ser *fhs = (fh_ser *) bufp;
|
||||
fhandler_base *oldfh, *newfh;
|
||||
DWORD winpid = fhs->winpid;
|
||||
|
||||
cygheap_fdnew cfd;
|
||||
if (cfd < 0)
|
||||
return -1;
|
||||
|
||||
oldfh = (fhandler_base *) &fhs->fhu;
|
||||
newfh = cygheap->fdtab.dup_worker (oldfh, 0, winpid);
|
||||
newfh = cygheap->fdtab.dup_worker (oldfh, 0, fhs->winpid);
|
||||
|
||||
/* Tell sender it can delete its temporary copy of the fhandler. */
|
||||
if (!send_scm_fd_ack (fhs->uniq_id))
|
||||
debug_printf ("can't send ack");
|
||||
if (!newfh)
|
||||
return -1;
|
||||
switch ((dev_t) newfh->dev ())
|
||||
device dev = newfh->dev ();
|
||||
switch (dev.get_major ())
|
||||
{
|
||||
case DEV_PTYS_MAJOR:
|
||||
break;
|
||||
case DEV_PTYM_MAJOR:
|
||||
case DEV_FLOPPY_MAJOR:
|
||||
case DEV_CDROM_MAJOR:
|
||||
case DEV_SD_MAJOR:
|
||||
case DEV_SD1_MAJOR ... DEV_SD7_MAJOR:
|
||||
case DEV_SD_HIGHPART_START ... DEV_SD_HIGHPART_END:
|
||||
case DEV_TAPE_MAJOR:
|
||||
case DEV_SERIAL_MAJOR:
|
||||
case DEV_CONS_MAJOR:
|
||||
set_errno (EOPNOTSUPP);
|
||||
return -1;
|
||||
default:
|
||||
switch ((dev_t) dev)
|
||||
{
|
||||
case FH_FS:
|
||||
newfh->set_name_from_handle ();
|
||||
@ -2116,6 +2134,7 @@ fhandler_socket_unix::deserialize (void *bufp)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
cfd = newfh;
|
||||
return cfd;
|
||||
}
|
||||
|
@ -1081,8 +1081,11 @@ out:
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD)
|
||||
fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD src_pid)
|
||||
{
|
||||
if (src_pid && !child->archetype)
|
||||
goto dup_handles;
|
||||
|
||||
/* This code was added in Oct 2001 for some undisclosed reason.
|
||||
However, setting the controlling tty on a dup causes rxvt to
|
||||
hang when the parent does a dup since the controlling pgid changes.
|
||||
@ -1095,6 +1098,112 @@ fhandler_pty_slave::dup (fhandler_base *child, int flags, DWORD)
|
||||
myself->set_ctty (this, flags);
|
||||
report_tty_counts (child, "duped slave", "");
|
||||
return 0;
|
||||
|
||||
dup_handles:
|
||||
/* We're being called from dtable::dup_worker with src_pid != 0, and
|
||||
we don't have an archetype yet. We need to duplicate handles
|
||||
from the source process, and the caller will create a new
|
||||
archetype. The following code is adapted from
|
||||
fhandler_pty_slave::open. */
|
||||
|
||||
fhandler_pty_slave *fhp = (fhandler_pty_slave *) child;
|
||||
HANDLE src_proc;
|
||||
HANDLE from_master_local, from_master_cyg_local;
|
||||
HANDLE to_master_local, to_master_cyg_local;
|
||||
|
||||
HANDLE *handles[] =
|
||||
{
|
||||
&src_proc,
|
||||
&from_master_local, &from_master_cyg_local,
|
||||
&to_master_local, &to_master_cyg_local,
|
||||
&fhp->output_mutex, &fhp->input_mutex, &fhp->inuse,
|
||||
&fhp->input_available_event,
|
||||
NULL
|
||||
};
|
||||
|
||||
for (HANDLE **h = handles; *h; h++)
|
||||
**h = NULL;
|
||||
|
||||
src_proc = OpenProcess (PROCESS_DUP_HANDLE, FALSE, src_pid);
|
||||
if (!src_proc)
|
||||
{
|
||||
termios_printf ("can't open source process, %E");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle (src_proc, output_mutex, GetCurrentProcess (),
|
||||
&fhp->output_mutex, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate output_mutex from %u/%p, %E",
|
||||
src_pid, output_mutex);
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, input_mutex, GetCurrentProcess (),
|
||||
&fhp->input_mutex, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate input_mutex from %u/%p, %E",
|
||||
src_pid, input_mutex);
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, input_available_event, GetCurrentProcess (),
|
||||
&fhp->input_available_event, 0, TRUE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate input_available_event from %u/%p, %E",
|
||||
src_pid, input_available_event);
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, inuse, GetCurrentProcess (),
|
||||
&fhp->inuse, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate inuse from %u/%p, %E",
|
||||
src_pid, inuse);
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, get_ttyp ()->from_master (),
|
||||
GetCurrentProcess (), &from_master_local,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate input from %u/%p, %E",
|
||||
src_pid, get_ttyp ()->from_master ());
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, get_ttyp ()->from_master_cyg (),
|
||||
GetCurrentProcess (), &from_master_cyg_local,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate input from %u/%p, %E",
|
||||
src_pid, get_ttyp ()->from_master_cyg ());
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, get_ttyp ()->to_master (),
|
||||
GetCurrentProcess (), &to_master_local,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate to_master_local from %u/%p, %E",
|
||||
src_pid, get_ttyp ()->to_master ());
|
||||
goto err;
|
||||
}
|
||||
if (!DuplicateHandle (src_proc, get_ttyp ()->to_master_cyg (),
|
||||
GetCurrentProcess (), &to_master_cyg_local,
|
||||
0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
termios_printf ("can't duplicate to_master_cyg_local from %u/%p, %E",
|
||||
src_pid, get_ttyp ()->to_master_cyg ());
|
||||
goto err;
|
||||
}
|
||||
CloseHandle (src_proc);
|
||||
fhp->set_handle (from_master_local);
|
||||
fhp->set_handle_cyg (from_master_cyg_local);
|
||||
fhp->set_output_handle (to_master_local);
|
||||
fhp->set_output_handle_cyg (to_master_cyg_local);
|
||||
return 0;
|
||||
err:
|
||||
__seterrno ();
|
||||
for (HANDLE **h = handles; *h; h++)
|
||||
if (**h)
|
||||
CloseHandle (**h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user