3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #include <cygwin/kd.h>
24 #include "shared_info.h"
25 #include "cygthread.h"
26 #include "child_info.h"
28 #define close_maybe(h) \
30 if (h && h != INVALID_HANDLE_VALUE) \
34 /* pty master control pipe messages */
45 /* tty master stuff */
47 fhandler_tty_master NO_COPY *tty_master;
49 static DWORD WINAPI process_input (void *); // Input queue thread
50 static DWORD WINAPI process_output (void *); // Output queue thread
51 static DWORD WINAPI process_ioctl (void *); // Ioctl requests thread
53 fhandler_tty_master::fhandler_tty_master ()
54 : fhandler_pty_master (), console (NULL)
59 fhandler_tty_slave::get_unit ()
61 return dev () == FH_TTY ? myself->ctty : dev ().minor;
65 fhandler_tty_master::set_winsize (bool sendSIGWINCH)
68 console->ioctl (TIOCGWINSZ, &w);
69 get_ttyp ()->winsize = w;
71 tc->kill_pgrp (SIGWINCH);
75 fhandler_tty_master::init ()
77 termios_printf ("Creating master for tty%d", get_unit ());
81 termios_printf ("can't create fhandler");
90 set_close_on_exec (true);
93 h = new cygthread (process_input, 0, cygself, "ttyin");
94 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
97 h = new cygthread (process_ioctl, 0, cygself, "ttyioctl");
98 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
101 h = new cygthread (process_output, 0, cygself, "ttyout");
102 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
109 static class mutex_stack
121 fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
124 if (strace.active ())
125 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms);
126 DWORD res = WaitForSingleObject (output_mutex, ms);
127 if (res == WAIT_OBJECT_0)
130 if (strace.active ())
131 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: acquired", ln, res);
135 ostack[osi].tname = cygthread::name ();
136 termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
144 fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
146 if (ReleaseMutex (output_mutex))
149 if (strace.active ())
150 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln);
154 termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
155 termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
156 ostack[osi].ln = -ln;
162 system_printf ("couldn't release output mutex but we seem to own it, %E");
168 /* Process tty input. */
171 fhandler_pty_master::doecho (const void *str, DWORD len)
173 acquire_output_mutex (INFINITE);
174 if (!WriteFile (to_master, str, len, &len, NULL))
175 termios_printf ("Write to %p failed, %E", to_master);
176 // WaitForSingleObject (output_done_event, INFINITE);
177 release_output_mutex ();
181 fhandler_pty_master::accept_input ()
186 WaitForSingleObject (input_mutex, INFINITE);
188 bytes_left = eat_readahead (-1);
192 termios_printf ("sending EOF to slave");
193 get_ttyp ()->read_retval = 0;
201 termios_printf ("about to write %d chars to slave", bytes_left);
202 rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
205 debug_printf ("error writing to pipe %E");
206 get_ttyp ()->read_retval = -1;
211 get_ttyp ()->read_retval = 1;
213 bytes_left -= written;
216 debug_printf ("to_slave pipe is full");
217 puts_readahead (p, bytes_left);
223 SetEvent (input_available_event);
224 ReleaseMutex (input_mutex);
229 process_input (void *)
231 char rawbuf[INP_BUFFER_SIZE];
235 size_t nraw = INP_BUFFER_SIZE;
236 tty_master->console->read ((void *) rawbuf, nraw);
237 if (tty_master->line_edit (rawbuf, nraw, tty_master->get_ttyp ()->ti)
238 == line_edit_signalled)
239 tty_master->console->eat_readahead (-1);
244 fhandler_pty_master::hit_eof ()
246 if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
248 /* We have the only remaining open handle to this pty, and
249 the slave pty has been opened at least once. We treat
251 termios_printf ("all other handles closed");
257 /* Process tty output requests */
260 fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
263 char outbuf[OUT_BUFFER_SIZE + 1];
273 /* We need to return a left over \n character, resulting from
274 \r\n conversion. Note that we already checked for FLUSHO and
275 output_stopped at the time that we read the character, so we
276 don't check again here. */
287 /* Set RLEN to the number of bytes to read from the pipe. */
289 if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
291 /* We are going to expand \n to \r\n, so don't read more than
292 half of the number of bytes requested. */
297 if (rlen > sizeof outbuf)
298 rlen = sizeof outbuf;
300 HANDLE handle = get_io_handle ();
302 n = 0; // get_readahead_into_buffer (outbuf, len);
305 /* Doing a busy wait like this is quite inefficient, but nothing
306 else seems to work completely. Windows should provide some sort
307 of overlapped I/O for pipes, or something, but it doesn't. */
310 if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
316 /* DISCARD (FLUSHO) and tcflush can finish here. */
317 if (n == 0 && (get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
319 if (n == 0 && is_nonblocking ())
329 if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE)
333 termios_printf ("bytes read %u", n);
334 get_ttyp ()->write_error = 0;
335 if (output_done_event != NULL)
336 SetEvent (output_done_event);
338 if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
344 *optr++ = TIOCPKT_DATA;
346 if (!(get_ttyp ()->ti.c_oflag & OPOST)) // post-process output
348 memcpy (optr, outbuf, n);
351 else // raw output mode
360 if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
365 if (get_ttyp ()->ti.c_oflag & OCRNL)
371 if (get_ttyp ()->ti.c_oflag & ONLCR)
376 if (get_ttyp ()->ti.c_oflag & ONLRET)
384 /* Don't store data past the end of the user's buffer. This
385 can happen if the user requests a read of 1 byte when
386 doing \r\n expansion. */
387 if (optr - buf >= (int) len)
389 if (*iptr != '\n' || n != 0)
390 system_printf ("internal error: %d unexpected characters", n);
402 if (GetLastError () == ERROR_BROKEN_PIPE)
413 termios_printf ("returning %d", rc);
418 process_output (void *)
420 char buf[OUT_BUFFER_SIZE * 2];
424 int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
428 termios_printf ("ReadFile %E");
431 n = tty_master->console->write ((void *) buf, (size_t) n);
432 tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
437 /* Process tty ioctl requests */
440 process_ioctl (void *)
444 WaitForSingleObject (tty_master->ioctl_request_event, INFINITE);
445 termios_printf ("ioctl() request");
446 tty *ttyp = tty_master->get_ttyp ();
448 tty_master->console->ioctl (ttyp->cmd,
449 (ttyp->cmd == KDSKBMETA)
450 ? (void *) ttyp->arg.value
451 : (void *) &ttyp->arg);
452 SetEvent (tty_master->ioctl_done_event);
456 /**********************************************************************/
457 /* Tty slave stuff */
459 fhandler_tty_slave::fhandler_tty_slave ()
460 : fhandler_tty_common (), inuse (NULL)
462 uninterruptible_io (true);
465 /* FIXME: This function needs to close handles when it has
466 a failing condition. */
468 fhandler_tty_slave::open (int flags, mode_t)
470 HANDLE tty_owner, from_master_local, to_master_local;
473 &from_master_local, &input_available_event, &input_mutex, &inuse,
474 &ioctl_done_event, &ioctl_request_event, &output_done_event,
475 &output_mutex, &to_master_local, &tty_owner,
479 const char *errmsg = NULL;
481 for (HANDLE **h = handles; *h; h++)
484 if (get_device () == FH_TTY)
485 dev().tty_to_real_device ();
486 fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev);
489 *this = *(fhandler_tty_slave *) arch;
490 termios_printf ("copied fhandler_tty_slave archetype");
491 set_flags ((flags & ~O_TEXT) | O_BINARY);
492 cygheap->manage_console_count ("fhandler_tty_slave::open<arch>", 1);
496 tcinit (cygwin_shared->tty[get_unit ()]);
498 cygwin_shared->tty.attach (get_unit ());
500 set_flags ((flags & ~O_TEXT) | O_BINARY);
501 /* Create synchronisation events */
504 /* output_done_event may or may not exist. It will exist if the tty
505 was opened by fhandler_tty_master::init, normally called at
506 startup if use_tty is non-zero. It will not exist if this is a
507 pty opened by fhandler_pty_master::open. In the former case, tty
508 output is handled by a separate thread which controls output. */
509 shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
510 output_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
512 if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
514 errmsg = "open output mutex failed, %E";
517 if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
519 errmsg = "open input mutex failed, %E";
522 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
523 if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
525 errmsg = "open input event failed, %E";
529 /* The ioctl events may or may not exist. See output_done_event,
531 shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
532 ioctl_request_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
533 shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
534 ioctl_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
536 /* FIXME: Needs a method to eliminate tty races */
538 /* Create security attribute. Default permissions are 0620. */
539 security_descriptor sd;
540 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
541 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
542 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
543 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
544 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
546 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
547 acquire_output_mutex (500);
548 inuse = get_ttyp ()->create_inuse (&sa);
549 get_ttyp ()->was_opened = true;
550 release_output_mutex ();
553 if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
555 errmsg = "tty handles have been closed";
560 if (get_ttyp ()->master_pid < 0)
562 errmsg = "*** master is closed";
566 /* Three case for duplicating the pipe handles:
567 - Either we're the master. In this case, just duplicate the handles.
568 - Or, we have the right to open the master process for handle duplication.
569 In this case, just duplicate the handles.
570 - Or, we have to ask the master process itself. In this case, send our
571 pid to the master process and check the reply. The reply contains
572 either the handles, or an error code which tells us why we didn't
574 if (myself->pid == get_ttyp ()->master_pid)
576 /* This is the most common case, just calling openpty. */
577 termios_printf ("dup handles within myself.");
578 tty_owner = GetCurrentProcess ();
582 pinfo p (get_ttyp ()->master_pid);
584 termios_printf ("*** couldn't find tty master");
587 tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
589 termios_printf ("dup handles directly since I'm allmighty.");
594 if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
595 GetCurrentProcess (), &from_master_local, 0, TRUE,
596 DUPLICATE_SAME_ACCESS))
598 termios_printf ("can't duplicate input from %u/%p, %E",
599 get_ttyp ()->master_pid, get_ttyp ()->from_master);
603 if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
604 GetCurrentProcess (), &to_master_local, 0, TRUE,
605 DUPLICATE_SAME_ACCESS))
607 errmsg = "can't duplicate output, %E";
610 if (tty_owner != GetCurrentProcess ())
611 CloseHandle (tty_owner);
615 pipe_request req = { GetCurrentProcessId () };
619 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
620 &installation_key, get_unit ());
621 termios_printf ("dup handles via master control pipe %s", buf);
622 if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl,
625 errmsg = "can't call master, %E";
628 from_master_local = repl.from_master;
629 to_master_local = repl.to_master;
630 if (!from_master_local || !to_master_local)
632 SetLastError (repl.error);
633 errmsg = "error duplicating pipes, %E";
637 VerifyHandle (from_master_local);
638 VerifyHandle (to_master_local);
640 termios_printf ("duplicated from_master %p->%p from tty_owner",
641 get_ttyp ()->from_master, from_master_local);
642 termios_printf ("duplicated to_master %p->%p from tty_owner",
643 get_ttyp ()->to_master, to_master_local);
645 set_io_handle (from_master_local);
646 set_output_handle (to_master_local);
647 set_close_on_exec (!!(flags & O_CLOEXEC));
650 if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1
651 && !output_done_event)
652 fhandler_console::need_invisible ();
654 // FIXME: Do this better someday
655 arch = (fhandler_tty_slave *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
656 *((fhandler_tty_slave **) cygheap->fdtab.add_archetype ()) = arch;
663 report_tty_counts (this, "opened", "");
664 myself->set_ctty (get_ttyp (), flags, arch);
671 termios_printf (errmsg);
673 for (HANDLE **h = handles; *h; h++)
674 if (**h && **h != INVALID_HANDLE_VALUE)
680 fhandler_tty_slave::close ()
682 /* This used to always call fhandler_tty_common::close when hExeced but that
683 caused multiple closes of the handles associated with this tty. Since
684 close_all_files is not called until after the cygwin process has synced
685 or before a non-cygwin process has exited, it should be safe to just
686 close this normally. cgf 2006-05-20 */
687 cygheap->manage_console_count ("fhandler_tty_slave::close", -1);
689 archetype->usecount--;
690 report_tty_counts (this, "closed", "");
692 if (archetype->usecount)
695 if (archetype->usecount < 0)
696 system_printf ("error: usecount %d", archetype->usecount);
698 termios_printf ("just returning because archetype usecount is != 0");
702 termios_printf ("closing last open %s handle", ttyname ());
703 if (inuse && !CloseHandle (inuse))
704 termios_printf ("CloseHandle (inuse), %E");
705 return fhandler_tty_common::close ();
709 fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
713 a &= GENERIC_READ | GENERIC_WRITE;
714 if (a == GENERIC_READ)
716 if (a == GENERIC_WRITE)
718 if (a == (GENERIC_READ | GENERIC_WRITE))
721 int ret = open (flags);
722 if (ret && !cygwin_finished_initializing && !IsDebuggerPresent ())
724 /* This only occurs when called from dtable::init_std_file_from_handle
725 We have been started from a non-Cygwin process. So we should become
726 tty process group leader.
727 TODO: Investigate how SIGTTIN should be handled with pure-windows
729 tc->pgid = myself->pgid;
732 if (f != INVALID_HANDLE_VALUE)
733 CloseHandle (f); /* Reopened by open */
739 fhandler_tty_slave::write (const void *ptr, size_t len)
741 DWORD n, towrite = len;
743 termios_printf ("tty%d, write(%x, %d)", get_unit (), ptr, len);
745 acquire_output_mutex (INFINITE);
749 n = min (OUT_BUFFER_SIZE, len);
750 char *buf = (char *)ptr;
751 ptr = (char *) ptr + n;
754 /* Previous write may have set write_error to != 0. Check it here.
755 This is less than optimal, but the alternative slows down tty
756 writes enormously. */
757 if (get_ttyp ()->write_error)
759 set_errno (get_ttyp ()->write_error);
760 towrite = (DWORD) -1;
764 if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
766 DWORD err = GetLastError ();
767 termios_printf ("WriteFile failed, %E");
771 err = ERROR_IO_DEVICE;
773 __seterrno_from_win_error (err);
775 raise (SIGHUP); /* FIXME: Should this be SIGTTOU? */
776 towrite = (DWORD) -1;
780 if (output_done_event != NULL)
784 rc = WaitForSingleObject (output_done_event, x);
785 termios_printf ("waited %d ms for output_done_event, WFSO %d", x, rc);
788 release_output_mutex ();
793 fhandler_tty_slave::read (void *ptr, size_t& len)
797 int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
800 char buf[INP_BUFFER_SIZE];
801 char peek_buf[INP_BUFFER_SIZE];
806 termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
808 if (!ptr) /* Indicating tcflush(). */
810 else if ((get_ttyp ()->ti.c_lflag & ICANON))
811 time_to_wait = INFINITE;
814 vmin = get_ttyp ()->ti.c_cc[VMIN];
815 if (vmin > INP_BUFFER_SIZE)
816 vmin = INP_BUFFER_SIZE;
817 vtime = get_ttyp ()->ti.c_cc[VTIME];
825 time_to_wait = !vtime ? INFINITE : 100 * vtime;
828 w4[0] = signal_arrived;
829 w4[1] = input_available_event;
831 DWORD waiter = time_to_wait;
834 rc = WaitForMultipleObjects (2, w4, FALSE, waiter);
836 if (rc == WAIT_TIMEOUT)
838 termios_printf ("wait timed out, waiter %u", waiter);
842 if (rc == WAIT_FAILED)
844 termios_printf ("wait for input event failed, %E");
848 if (rc == WAIT_OBJECT_0)
850 /* if we've received signal after successfully reading some data,
851 just return all data successfully read */
854 set_sig_errno (EINTR);
859 rc = WaitForSingleObject (input_mutex, 1000);
860 if (rc == WAIT_FAILED)
862 termios_printf ("wait for input mutex failed, %E");
865 else if (rc == WAIT_TIMEOUT)
867 termios_printf ("failed to acquire input mutex after input event arrived");
870 if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
872 termios_printf ("PeekNamedPipe failed, %E");
877 /* On first peek determine no. of bytes to flush. */
878 if (!ptr && len == UINT_MAX)
879 len = (size_t) bytes_in_pipe;
881 if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
883 ReleaseMutex (input_mutex);
884 len = (size_t) bytes_in_pipe;
888 readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
890 if (ptr && vmin && readlen > (unsigned) vmin)
896 termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
897 if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
899 termios_printf ("read failed, %E");
902 /* MSDN states that 5th prameter can be used to determine total
903 number of bytes in pipe, but for some reason this number doesn't
904 change after successful read. So we have to peek into the pipe
905 again to see if input is still available */
906 if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
908 termios_printf ("PeekNamedPipe failed, %E");
918 memcpy (ptr, buf, n);
919 ptr = (char *) ptr + n;
925 ResetEvent (input_available_event);
927 ReleaseMutex (input_mutex);
936 if (get_ttyp ()->read_retval < 0) // read error
938 set_errno (-get_ttyp ()->read_retval);
942 if (get_ttyp ()->read_retval == 0) //EOF
944 termios_printf ("saw EOF");
947 if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
949 if (vmin && totalread >= vmin)
952 /* vmin == 0 && vtime == 0:
953 * we've already read all input, if any, so return immediately
954 * vmin == 0 && vtime > 0:
955 * we've waited for input 10*vtime ms in WFSO(input_available_event),
956 * no matter whether any input arrived, we shouldn't wait any longer,
957 * so return immediately
958 * vmin > 0 && vtime == 0:
959 * here, totalread < vmin, so continue waiting until more data
961 * vmin > 0 && vtime > 0:
962 * similar to the previous here, totalread < vmin, and timer
963 * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
964 * so "restart timer" and wait until more data arrive
971 waiter = time_to_wait;
973 termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
974 len = (size_t) totalread;
978 fhandler_tty_slave::dup (fhandler_base *child)
980 fhandler_tty_slave *arch = (fhandler_tty_slave *) archetype;
981 *(fhandler_tty_slave *) child = *arch;
982 child->set_flags (get_flags ());
985 cygheap->manage_console_count ("fhandler_tty_slave::dup", 1);
986 report_tty_counts (child, "duped", "");
991 fhandler_pty_master::dup (fhandler_base *child)
993 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
994 *(fhandler_tty_master *) child = *arch;
995 child->set_flags (get_flags ());
998 report_tty_counts (child, "duped master", "");
1003 fhandler_tty_slave::tcgetattr (struct termios *t)
1005 *t = get_ttyp ()->ti;
1010 fhandler_tty_slave::tcsetattr (int, const struct termios *t)
1012 acquire_output_mutex (INFINITE);
1013 get_ttyp ()->ti = *t;
1014 release_output_mutex ();
1019 fhandler_tty_slave::tcflush (int queue)
1023 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1025 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1027 size_t len = UINT_MAX;
1029 ret = ((int) len) >= 0 ? 0 : -1;
1031 if (queue == TCOFLUSH || queue == TCIOFLUSH)
1033 /* do nothing for now. */
1036 termios_printf ("%d=tcflush(%d)", ret, queue);
1041 fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
1043 termios_printf ("ioctl (%x)", cmd);
1045 if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid
1046 && myself->ctty == get_unit () && (get_ttyp ()->ti.c_lflag & TOSTOP))
1048 /* background process */
1049 termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
1050 get_ttyp ()->getpgid (), myctty ());
1064 set_nonblocking (*(int *) arg);
1072 acquire_output_mutex (INFINITE);
1074 get_ttyp ()->cmd = cmd;
1075 get_ttyp ()->ioctl_retval = 0;
1080 get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1081 if (ioctl_request_event)
1082 SetEvent (ioctl_request_event);
1083 *(struct winsize *) arg = get_ttyp ()->arg.winsize;
1084 if (ioctl_done_event)
1085 WaitForSingleObject (ioctl_done_event, INFINITE);
1086 get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1089 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1090 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1092 get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1093 if (ioctl_request_event)
1095 get_ttyp ()->ioctl_retval = -EINVAL;
1096 SetEvent (ioctl_request_event);
1100 get_ttyp ()->winsize = *(struct winsize *) arg;
1101 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1103 if (ioctl_done_event)
1104 WaitForSingleObject (ioctl_done_event, INFINITE);
1108 val = *(unsigned char *) arg;
1109 if (val != 6 || !ioctl_request_event || !ioctl_done_event)
1110 get_ttyp ()->ioctl_retval = -EINVAL;
1113 get_ttyp ()->arg.value = val;
1114 SetEvent (ioctl_request_event);
1115 WaitForSingleObject (ioctl_done_event, INFINITE);
1116 *(unsigned char *) arg = (unsigned char) (get_ttyp ()->arg.value);
1120 if (ioctl_request_event)
1122 SetEvent (ioctl_request_event);
1123 if (ioctl_done_event)
1124 WaitForSingleObject (ioctl_done_event, INFINITE);
1125 *(int *) arg = get_ttyp ()->arg.value;
1128 get_ttyp ()->ioctl_retval = -EINVAL;
1131 if (ioctl_request_event)
1133 get_ttyp ()->arg.value = (int) arg;
1134 SetEvent (ioctl_request_event);
1135 if (ioctl_done_event)
1136 WaitForSingleObject (ioctl_done_event, INFINITE);
1139 get_ttyp ()->ioctl_retval = -EINVAL;
1143 release_output_mutex ();
1144 retval = get_ttyp ()->ioctl_retval;
1147 set_errno (-retval);
1152 termios_printf ("%d = ioctl (%x)", retval, cmd);
1157 fhandler_tty_slave::fstat (struct __stat64 *st)
1159 fhandler_base::fstat (st);
1161 bool to_close = false;
1162 if (!input_available_event)
1165 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1166 input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
1167 if (input_available_event)
1170 if (!input_available_event
1171 || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
1174 /* If we can't access the ACL, or if the tty doesn't actually exist,
1175 then fake uid and gid to strict, system-like values. */
1176 st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
1181 CloseHandle (input_available_event);
1185 /* Helper function for fchmod and fchown, which just opens all handles
1186 and signals success via bool return. */
1188 fhandler_tty_slave::fch_open_handles ()
1192 tc = cygwin_shared->tty[get_unit ()];
1193 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1194 input_available_event = OpenEvent (READ_CONTROL | WRITE_DAC | WRITE_OWNER,
1196 output_mutex = get_ttyp ()->open_output_mutex (WRITE_DAC | WRITE_OWNER);
1197 input_mutex = get_ttyp ()->open_input_mutex (WRITE_DAC | WRITE_OWNER);
1198 inuse = get_ttyp ()->open_inuse (WRITE_DAC | WRITE_OWNER);
1199 if (!input_available_event || !output_mutex || !input_mutex || !inuse)
1204 /* These members are optional, no error checking */
1205 shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
1206 output_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1207 shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
1208 ioctl_request_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1209 shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
1210 ioctl_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1214 /* Helper function for fchmod and fchown, which sets the new security
1215 descriptor on all objects representing the tty. */
1217 fhandler_tty_slave::fch_set_sd (security_descriptor &sd, bool chown)
1219 security_descriptor sd_old;
1221 get_object_sd (input_available_event, sd_old);
1222 if (!set_object_sd (input_available_event, sd, chown)
1223 && !set_object_sd (output_mutex, sd, chown)
1224 && !set_object_sd (input_mutex, sd, chown)
1225 && !set_object_sd (inuse, sd, chown)
1226 && (!output_done_event
1227 || !set_object_sd (output_done_event, sd, chown))
1228 && (!ioctl_request_event
1229 || !set_object_sd (ioctl_request_event, sd, chown))
1230 && (!ioctl_done_event
1231 || !set_object_sd (ioctl_done_event, sd, chown)))
1233 set_object_sd (input_available_event, sd_old, chown);
1234 set_object_sd (output_mutex, sd_old, chown);
1235 set_object_sd (input_mutex, sd_old, chown);
1236 set_object_sd (inuse, sd_old, chown);
1237 if (!output_done_event)
1238 set_object_sd (output_done_event, sd_old, chown);
1239 if (!ioctl_request_event)
1240 set_object_sd (ioctl_request_event, sd_old, chown);
1241 if (!ioctl_done_event)
1242 set_object_sd (ioctl_done_event, sd_old, chown);
1246 /* Helper function for fchmod and fchown, which closes all object handles in
1249 fhandler_tty_slave::fch_close_handles ()
1251 close_maybe (get_io_handle ());
1252 close_maybe (get_output_handle ());
1253 close_maybe (output_done_event);
1254 close_maybe (ioctl_done_event);
1255 close_maybe (ioctl_request_event);
1256 close_maybe (input_available_event);
1257 close_maybe (output_mutex);
1258 close_maybe (input_mutex);
1259 close_maybe (inuse);
1263 fhandler_tty_slave::fchmod (mode_t mode)
1266 bool to_close = false;
1267 security_descriptor sd;
1271 if (!input_available_event)
1274 if (!fch_open_handles ())
1277 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1278 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1279 if (!get_object_attribute (input_available_event, &uid, &gid, NULL)
1280 && !create_object_sd_from_attribute (NULL, uid, gid, S_IFCHR | mode, sd))
1281 ret = fch_set_sd (sd, false);
1284 fch_close_handles ();
1289 fhandler_tty_slave::fchown (__uid32_t uid, __gid32_t gid)
1292 bool to_close = false;
1296 security_descriptor sd;
1298 if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
1300 if (!input_available_event)
1303 if (!fch_open_handles ())
1306 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1307 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1308 if (!get_object_attribute (input_available_event, &o_uid, &o_gid, &mode))
1310 if ((uid == ILLEGAL_UID || uid == o_uid)
1311 && (gid == ILLEGAL_GID || gid == o_gid))
1313 else if (!create_object_sd_from_attribute (input_available_event,
1314 uid, gid, S_IFCHR | mode, sd))
1315 ret = fch_set_sd (sd, true);
1319 fch_close_handles ();
1323 /*******************************************************
1326 fhandler_pty_master::fhandler_pty_master ()
1327 : fhandler_tty_common (), pktmode (0), need_nl (0), dwProcessId (0)
1332 fhandler_pty_master::open (int flags, mode_t)
1335 ntty = cygwin_shared->tty.allocate (false);
1339 dev().devn = FHDEV (DEV_TTYM_MAJOR, ntty);
1342 lock_ttys::release ();
1345 lock_ttys::release ();
1346 set_flags ((flags & ~O_TEXT) | O_BINARY);
1349 // FIXME: Do this better someday
1350 fhandler_pty_master *arch = (fhandler_tty_master *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
1351 *((fhandler_pty_master **) cygheap->fdtab.add_archetype ()) = arch;
1354 arch->dwProcessId = GetCurrentProcessId ();
1358 char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
1359 __small_sprintf (buf, "opened pty master for tty%d", get_unit ());
1360 report_tty_counts (this, buf, "");
1365 fhandler_tty_common::lseek (_off64_t, int)
1372 fhandler_tty_common::close ()
1374 termios_printf ("tty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1375 if (output_done_event && !CloseHandle (output_done_event))
1376 termios_printf ("CloseHandle (output_done_event), %E");
1377 if (ioctl_done_event && !CloseHandle (ioctl_done_event))
1378 termios_printf ("CloseHandle (ioctl_done_event), %E");
1379 if (ioctl_request_event && !CloseHandle (ioctl_request_event))
1380 termios_printf ("CloseHandle (ioctl_request_event), %E");
1381 if (!ForceCloseHandle (input_mutex))
1382 termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
1383 if (!ForceCloseHandle (output_mutex))
1384 termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
1385 if (!ForceCloseHandle1 (get_handle (), from_pty))
1386 termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1387 if (!ForceCloseHandle1 (get_output_handle (), to_pty))
1388 termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
1390 if (!ForceCloseHandle (input_available_event))
1391 termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1397 fhandler_pty_master::close ()
1400 while (accept_input () > 0)
1403 archetype->usecount--;
1404 report_tty_counts (this, "closing master", "");
1406 if (archetype->usecount)
1409 if (archetype->usecount < 0)
1410 system_printf ("error: usecount %d", archetype->usecount);
1412 termios_printf ("just returning because archetype usecount is != 0");
1416 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1417 termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1418 arch->from_master, arch->to_master, arch->dwProcessId);
1419 if (cygwin_finished_initializing)
1421 if (arch->master_ctl && get_ttyp ()->master_pid == myself->pid)
1424 pipe_request req = { (DWORD) -1 };
1428 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1429 &installation_key, get_unit ());
1430 CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500);
1431 CloseHandle (arch->master_ctl);
1433 if (!ForceCloseHandle (arch->from_master))
1434 termios_printf ("error closing from_master %p, %E", arch->from_master);
1435 if (!ForceCloseHandle (arch->to_master))
1436 termios_printf ("error closing from_master %p, %E", arch->to_master);
1438 fhandler_tty_common::close ();
1440 if (hExeced || get_ttyp ()->master_pid != myself->pid)
1441 termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid);
1443 get_ttyp ()->set_master_closed ();
1449 fhandler_pty_master::write (const void *ptr, size_t len)
1452 char *p = (char *) ptr;
1453 termios ti = tc->ti;
1455 for (i = 0; i < (int) len; i++)
1457 line_edit_status status = line_edit (p++, 1, ti);
1458 if (status > line_edit_signalled)
1460 if (status != line_edit_pipe_full)
1469 fhandler_pty_master::read (void *ptr, size_t& len)
1471 len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1475 fhandler_pty_master::tcgetattr (struct termios *t)
1477 *t = cygwin_shared->tty[get_unit ()]->ti;
1482 fhandler_pty_master::tcsetattr (int, const struct termios *t)
1484 cygwin_shared->tty[get_unit ()]->ti = *t;
1489 fhandler_pty_master::tcflush (int queue)
1493 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1495 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1496 ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1497 else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1499 /* do nothing for now. */
1502 termios_printf ("%d=tcflush(%d)", ret, queue);
1507 fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1512 pktmode = *(int *) arg;
1515 *(struct winsize *) arg = get_ttyp ()->winsize;
1518 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1519 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1521 get_ttyp ()->winsize = *(struct winsize *) arg;
1522 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1526 set_nonblocking (*(int *) arg);
1536 fhandler_pty_master::ptsname ()
1538 static char buf[TTY_NAME_MAX];
1540 __small_sprintf (buf, "/dev/tty%d", get_unit ());
1545 fhandler_tty_common::set_close_on_exec (bool val)
1547 // Cygwin processes will handle this specially on exec.
1548 close_on_exec (val);
1552 fhandler_tty_slave::fixup_after_fork (HANDLE parent)
1554 // fork_fixup (parent, inuse, "inuse");
1555 // fhandler_tty_common::fixup_after_fork (parent);
1556 report_tty_counts (this, "inherited", "");
1560 fhandler_tty_slave::fixup_after_exec ()
1562 if (!close_on_exec ())
1563 fixup_after_fork (NULL);
1567 fhandler_tty_master::init_console ()
1569 console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym");
1570 if (console == NULL)
1573 console->init (INVALID_HANDLE_VALUE, GENERIC_READ | GENERIC_WRITE, O_BINARY);
1574 cygheap->manage_console_count ("fhandler_tty_master::init_console", -1, true);
1575 console->uninterruptible_io (true);
1579 extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
1581 /* This thread function handles the master control pipe. It waits for a
1582 client to connect. Then it checks if the client process has permissions
1583 to access the tty handles. If so, it opens the client process and
1584 duplicates the handles into that process. If that fails, it sends a reply
1585 with at least one handle set to NULL and an error code. Last but not
1586 least, the client is disconnected and the thread waits for the next client.
1588 A special case is when the master side of the tty is about to be closed.
1589 The client side is the fhandler_pty_master::close function and it sends
1590 a PID -1 in that case. On Vista and later a check is performed that the
1591 request to leave really comes from the master process itself. On earlier
1592 OSes there's no function to check for the PID of the client process so
1593 we have to trust the client side.
1596 always only one pipe instance, there's a chance that clients have to
1597 wait to connect to the master control pipe. Therefore the client calls
1598 to CallNamedPipe should have a big enough timeout value. For now this
1599 is 500ms. Hope that's enough. */
1602 fhandler_pty_master::pty_master_thread ()
1605 GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
1606 EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
1609 security_descriptor sd;
1615 termios_printf ("Entered");
1616 while (!exit && ConnectNamedPipe (master_ctl, NULL))
1618 pipe_reply repl = { NULL, NULL, 0 };
1621 ACCESS_MASK access = EVENT_MODIFY_STATE;
1622 HANDLE client = NULL;
1624 if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
1626 termios_printf ("ReadFile, %E");
1629 /* This function is only available since Vista, unfortunately.
1630 In earlier OSes we simply have to believe that the client
1631 has no malicious intent (== sends arbitrary PIDs). */
1632 if (!GetNamedPipeClientProcessId (master_ctl, &pid))
1634 if (get_object_sd (input_available_event, sd))
1636 termios_printf ("get_object_sd, %E");
1639 cygheap->user.deimpersonate ();
1641 if (!ImpersonateNamedPipeClient (master_ctl))
1643 termios_printf ("ImpersonateNamedPipeClient, %E");
1646 if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &token))
1648 termios_printf ("OpenThreadToken, %E");
1652 ret = AccessCheck (sd, token, access, &map, &ps, &len, &access, &allow);
1653 CloseHandle (token);
1656 termios_printf ("AccessCheck, %E");
1659 if (!RevertToSelf ())
1661 termios_printf ("RevertToSelf, %E");
1664 if (req.pid == (DWORD) -1) /* Request to finish thread. */
1666 /* Pre-Vista: Just believe in the good of the client process.
1667 Post-Vista: Check if the requesting process is the master
1669 if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
1675 client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
1678 termios_printf ("OpenProcess, %E");
1681 if (!DuplicateHandle (GetCurrentProcess (), from_master,
1682 client, &repl.from_master,
1683 0, TRUE, DUPLICATE_SAME_ACCESS))
1685 termios_printf ("DuplicateHandle (from_master), %E");
1688 if (!DuplicateHandle (GetCurrentProcess (), to_master,
1689 client, &repl.to_master,
1690 0, TRUE, DUPLICATE_SAME_ACCESS))
1692 termios_printf ("DuplicateHandle (to_master), %E");
1697 repl.error = GetLastError ();
1699 CloseHandle (client);
1701 cygheap->user.reimpersonate ();
1703 termios_printf ("Reply: from %p, to %p, error %lu",
1704 repl.from_master, repl.to_master, repl.error );
1705 if (!WriteFile (master_ctl, &repl, sizeof repl, &len, NULL))
1706 termios_printf ("WriteFile, %E");
1707 if (!DisconnectNamedPipe (master_ctl))
1708 termios_printf ("DisconnectNamedPipe, %E");
1710 termios_printf ("Leaving");
1715 pty_master_thread (VOID *arg)
1717 return ((fhandler_pty_master *) arg)->pty_master_thread ();
1721 fhandler_pty_master::setup (bool ispty)
1724 security_descriptor sd;
1725 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
1727 tty& t = *cygwin_shared->tty[get_unit ()];
1729 tcinit (&t, true); /* Set termios information. Force initialization. */
1731 const char *errstr = NULL;
1732 DWORD pipe_mode = PIPE_NOWAIT;
1734 /* Create communication pipes */
1735 char pipename[sizeof("ttyNNNN-from-master")];
1736 __small_sprintf (pipename, "tty%d-from-master", get_unit ());
1737 res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1738 from_master, get_output_handle (),
1739 128 * 1024, pipename);
1742 errstr = "input pipe";
1746 if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
1747 termios_printf ("can't set output_handle(%p) to non-blocking mode",
1748 get_output_handle ());
1750 __small_sprintf (pipename, "tty%d-to-master", get_unit ());
1751 res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1752 get_io_handle (), to_master,
1753 128 * 1024, pipename);
1756 errstr = "output pipe";
1762 /* Create security attribute. Default permissions are 0620. */
1763 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1764 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1765 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
1766 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
1768 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
1770 /* Create synchronisation events */
1774 if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT, &sa)))
1776 if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT, &sa)))
1778 if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT,
1783 /* Carefully check that the input_available_event didn't already exist.
1784 This is a measure to make sure that the event security descriptor
1785 isn't occupied by a malicious process. We must make sure that the
1786 event's security descriptor is what we expect it to be. */
1787 if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT,
1789 || GetLastError () == ERROR_ALREADY_EXISTS)
1793 errstr = shared_name (buf, OUTPUT_MUTEX, t.ntty);
1794 if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
1797 errstr = shared_name (buf, INPUT_MUTEX, t.ntty);
1798 if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
1803 /* Create master control pipe which allows the master to duplicate
1804 the pty pipe handles to processes which deserve it. */
1806 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1807 &installation_key, get_unit ());
1808 master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX,
1809 PIPE_WAIT | PIPE_TYPE_MESSAGE
1810 | PIPE_READMODE_MESSAGE, 1, 4096, 4096,
1812 if (master_ctl == INVALID_HANDLE_VALUE)
1814 errstr = "pty master control pipe";
1817 h = new cygthread (::pty_master_thread, 0, this, "pty_master");
1820 errstr = "pty master control thread";
1826 t.from_master = from_master;
1827 t.to_master = to_master;
1828 // /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
1829 // /* screws up tty master */ ProtectHandle1INH (input_mutex, input_mutex);
1830 t.winsize.ws_col = 80;
1831 t.winsize.ws_row = 25;
1832 t.master_pid = myself->pid;
1834 termios_printf ("tty%d opened - from_slave %p, to_slave %p", t.ntty,
1835 get_io_handle (), get_output_handle ());
1840 close_maybe (get_io_handle ());
1841 close_maybe (get_output_handle ());
1842 close_maybe (output_done_event);
1843 close_maybe (ioctl_done_event);
1844 close_maybe (ioctl_request_event);
1845 close_maybe (input_available_event);
1846 close_maybe (output_mutex);
1847 close_maybe (input_mutex);
1848 close_maybe (from_master);
1849 close_maybe (to_master);
1850 close_maybe (master_ctl);
1851 termios_printf ("tty%d open failed - failed to create %s", errstr);
1856 fhandler_pty_master::fixup_after_fork (HANDLE parent)
1858 DWORD wpid = GetCurrentProcessId ();
1859 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1860 if (arch->dwProcessId != wpid)
1862 tty& t = *get_ttyp ();
1863 if (!DuplicateHandle (parent, arch->from_master, GetCurrentProcess (),
1864 &arch->from_master, 0, false, DUPLICATE_SAME_ACCESS))
1865 system_printf ("couldn't duplicate from_parent(%p), %E", arch->from_master);
1866 if (!DuplicateHandle (parent, arch->to_master, GetCurrentProcess (),
1867 &arch->to_master, 0, false, DUPLICATE_SAME_ACCESS))
1868 system_printf ("couldn't duplicate to_parent(%p), %E", arch->from_master);
1869 if (myself->pid == t.master_pid)
1871 t.from_master = arch->from_master;
1872 t.to_master = arch->to_master;
1874 arch->dwProcessId = wpid;
1876 from_master = arch->from_master;
1877 to_master = arch->to_master;
1878 report_tty_counts (this, "inherited master", "");
1882 fhandler_pty_master::fixup_after_exec ()
1884 if (!close_on_exec ())
1885 fixup_after_fork (spawn_info->parent);
1887 from_master = to_master = NULL;