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 void WINAPI process_input (void *) __attribute__((noreturn)); // Input queue thread
50 static void WINAPI process_output (void *) __attribute__((noreturn)); // Output queue thread
51 static void WINAPI process_ioctl (void *) __attribute__((noreturn)); // 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);
92 new cygthread (process_input, cygself, "ttyin");
93 new cygthread (process_ioctl, cygself, "ttyioctl");
94 new cygthread (process_output, cygself, "ttyout");
100 static class mutex_stack
112 fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
115 if (strace.active ())
116 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms);
117 DWORD res = WaitForSingleObject (output_mutex, ms);
118 if (res == WAIT_OBJECT_0)
121 if (strace.active ())
122 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: acquired", ln, res);
126 ostack[osi].tname = cygthread::name ();
127 termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
135 fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
137 if (ReleaseMutex (output_mutex))
140 if (strace.active ())
141 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln);
145 termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
146 termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
147 ostack[osi].ln = -ln;
153 system_printf ("couldn't release output mutex but we seem to own it, %E");
159 /* Process tty input. */
162 fhandler_pty_master::doecho (const void *str, DWORD len)
164 acquire_output_mutex (INFINITE);
165 if (!WriteFile (to_master, str, len, &len, NULL))
166 termios_printf ("Write to %p failed, %E", to_master);
167 // WaitForSingleObject (output_done_event, INFINITE);
168 release_output_mutex ();
172 fhandler_pty_master::accept_input ()
177 WaitForSingleObject (input_mutex, INFINITE);
179 bytes_left = eat_readahead (-1);
183 termios_printf ("sending EOF to slave");
184 get_ttyp ()->read_retval = 0;
192 termios_printf ("about to write %d chars to slave", bytes_left);
193 rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
196 debug_printf ("error writing to pipe %E");
197 get_ttyp ()->read_retval = -1;
202 get_ttyp ()->read_retval = 1;
204 bytes_left -= written;
207 debug_printf ("to_slave pipe is full");
208 puts_readahead (p, bytes_left);
214 SetEvent (input_available_event);
215 ReleaseMutex (input_mutex);
220 process_input (void *)
222 char rawbuf[INP_BUFFER_SIZE];
226 size_t nraw = INP_BUFFER_SIZE;
227 tty_master->console->read ((void *) rawbuf, nraw);
228 if (tty_master->line_edit (rawbuf, nraw, tty_master->get_ttyp ()->ti)
229 == line_edit_signalled)
230 tty_master->console->eat_readahead (-1);
235 fhandler_pty_master::hit_eof ()
237 if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
239 /* We have the only remaining open handle to this pty, and
240 the slave pty has been opened at least once. We treat
242 termios_printf ("all other handles closed");
248 /* Process tty output requests */
251 fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
254 char outbuf[OUT_BUFFER_SIZE + 1];
264 /* We need to return a left over \n character, resulting from
265 \r\n conversion. Note that we already checked for FLUSHO and
266 output_stopped at the time that we read the character, so we
267 don't check again here. */
278 /* Set RLEN to the number of bytes to read from the pipe. */
280 if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
282 /* We are going to expand \n to \r\n, so don't read more than
283 half of the number of bytes requested. */
288 if (rlen > sizeof outbuf)
289 rlen = sizeof outbuf;
291 HANDLE handle = get_io_handle ();
293 n = 0; // get_readahead_into_buffer (outbuf, len);
296 /* Doing a busy wait like this is quite inefficient, but nothing
297 else seems to work completely. Windows should provide some sort
298 of overlapped I/O for pipes, or something, but it doesn't. */
301 if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
307 /* DISCARD (FLUSHO) and tcflush can finish here. */
308 if (n == 0 && (get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
310 if (n == 0 && is_nonblocking ())
320 if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE)
324 termios_printf ("bytes read %u", n);
325 get_ttyp ()->write_error = 0;
326 if (output_done_event != NULL)
327 SetEvent (output_done_event);
329 if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
335 *optr++ = TIOCPKT_DATA;
337 if (!(get_ttyp ()->ti.c_oflag & OPOST)) // post-process output
339 memcpy (optr, outbuf, n);
342 else // raw output mode
351 if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
356 if (get_ttyp ()->ti.c_oflag & OCRNL)
362 if (get_ttyp ()->ti.c_oflag & ONLCR)
367 if (get_ttyp ()->ti.c_oflag & ONLRET)
375 /* Don't store data past the end of the user's buffer. This
376 can happen if the user requests a read of 1 byte when
377 doing \r\n expansion. */
378 if (optr - buf >= (int) len)
380 if (*iptr != '\n' || n != 0)
381 system_printf ("internal error: %d unexpected characters", n);
393 if (GetLastError () == ERROR_BROKEN_PIPE)
404 termios_printf ("returning %d", rc);
409 process_output (void *)
411 char buf[OUT_BUFFER_SIZE * 2];
415 int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
419 termios_printf ("ReadFile %E");
422 n = tty_master->console->write ((void *) buf, (size_t) n);
423 tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
428 /* Process tty ioctl requests */
431 process_ioctl (void *)
435 WaitForSingleObject (tty_master->ioctl_request_event, INFINITE);
436 termios_printf ("ioctl() request");
437 tty *ttyp = tty_master->get_ttyp ();
439 tty_master->console->ioctl (ttyp->cmd,
440 (ttyp->cmd == KDSKBMETA)
441 ? (void *) ttyp->arg.value
442 : (void *) &ttyp->arg);
443 SetEvent (tty_master->ioctl_done_event);
447 /**********************************************************************/
448 /* Tty slave stuff */
450 fhandler_tty_slave::fhandler_tty_slave ()
451 : fhandler_tty_common (), inuse (NULL)
453 uninterruptible_io (true);
456 /* FIXME: This function needs to close handles when it has
457 a failing condition. */
459 fhandler_tty_slave::open (int flags, mode_t)
461 HANDLE tty_owner, from_master_local, to_master_local;
464 &from_master_local, &input_available_event, &input_mutex, &inuse,
465 &ioctl_done_event, &ioctl_request_event, &output_done_event,
466 &output_mutex, &to_master_local, &tty_owner,
470 const char *errmsg = NULL;
472 for (HANDLE **h = handles; *h; h++)
475 if (get_device () == FH_TTY)
476 dev().tty_to_real_device ();
477 fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev);
480 *this = *(fhandler_tty_slave *) arch;
481 termios_printf ("copied fhandler_tty_slave archetype");
482 set_flags ((flags & ~O_TEXT) | O_BINARY);
483 cygheap->manage_console_count ("fhandler_tty_slave::open<arch>", 1);
487 tcinit (cygwin_shared->tty[get_unit ()]);
489 cygwin_shared->tty.attach (get_unit ());
491 set_flags ((flags & ~O_TEXT) | O_BINARY);
492 /* Create synchronisation events */
495 /* output_done_event may or may not exist. It will exist if the tty
496 was opened by fhandler_tty_master::init, normally called at
497 startup if use_tty is non-zero. It will not exist if this is a
498 pty opened by fhandler_pty_master::open. In the former case, tty
499 output is handled by a separate thread which controls output. */
500 shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
501 output_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
503 if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
505 errmsg = "open output mutex failed, %E";
508 if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
510 errmsg = "open input mutex failed, %E";
513 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
514 if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
516 errmsg = "open input event failed, %E";
520 /* The ioctl events may or may not exist. See output_done_event,
522 shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
523 ioctl_request_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
524 shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
525 ioctl_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
527 /* FIXME: Needs a method to eliminate tty races */
529 /* Create security attribute. Default permissions are 0620. */
530 security_descriptor sd;
531 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
532 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
533 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
534 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
535 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
537 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
538 acquire_output_mutex (500);
539 inuse = get_ttyp ()->create_inuse (&sa);
540 get_ttyp ()->was_opened = true;
541 release_output_mutex ();
544 if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
546 errmsg = "tty handles have been closed";
551 if (get_ttyp ()->master_pid < 0)
553 errmsg = "*** master is closed";
557 /* Three case for duplicating the pipe handles:
558 - Either we're the master. In this case, just duplicate the handles.
559 - Or, we have the right to open the master process for handle duplication.
560 In this case, just duplicate the handles.
561 - Or, we have to ask the master process itself. In this case, send our
562 pid to the master process and check the reply. The reply contains
563 either the handles, or an error code which tells us why we didn't
565 if (myself->pid == get_ttyp ()->master_pid)
567 /* This is the most common case, just calling openpty. */
568 termios_printf ("dup handles within myself.");
569 tty_owner = GetCurrentProcess ();
573 pinfo p (get_ttyp ()->master_pid);
575 termios_printf ("*** couldn't find tty master");
578 tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
580 termios_printf ("dup handles directly since I'm allmighty.");
585 if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
586 GetCurrentProcess (), &from_master_local, 0, TRUE,
587 DUPLICATE_SAME_ACCESS))
589 termios_printf ("can't duplicate input from %u/%p, %E",
590 get_ttyp ()->master_pid, get_ttyp ()->from_master);
594 if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
595 GetCurrentProcess (), &to_master_local, 0, TRUE,
596 DUPLICATE_SAME_ACCESS))
598 errmsg = "can't duplicate output, %E";
601 if (tty_owner != GetCurrentProcess ())
602 CloseHandle (tty_owner);
606 pipe_request req = { GetCurrentProcessId () };
610 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
611 &installation_key, get_unit ());
612 termios_printf ("dup handles via master control pipe %s", buf);
613 if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl,
616 errmsg = "can't call master, %E";
619 from_master_local = repl.from_master;
620 to_master_local = repl.to_master;
621 if (!from_master_local || !to_master_local)
623 SetLastError (repl.error);
624 errmsg = "error duplicating pipes, %E";
628 VerifyHandle (from_master_local);
629 VerifyHandle (to_master_local);
631 termios_printf ("duplicated from_master %p->%p from tty_owner",
632 get_ttyp ()->from_master, from_master_local);
633 termios_printf ("duplicated to_master %p->%p from tty_owner",
634 get_ttyp ()->to_master, to_master_local);
636 set_io_handle (from_master_local);
637 set_output_handle (to_master_local);
638 set_close_on_exec (!!(flags & O_CLOEXEC));
641 if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1
642 && !output_done_event)
643 fhandler_console::need_invisible ();
645 // FIXME: Do this better someday
646 arch = (fhandler_tty_slave *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
647 *((fhandler_tty_slave **) cygheap->fdtab.add_archetype ()) = arch;
654 report_tty_counts (this, "opened", "");
655 myself->set_ctty (get_ttyp (), flags, arch);
662 termios_printf (errmsg);
664 for (HANDLE **h = handles; *h; h++)
665 if (**h && **h != INVALID_HANDLE_VALUE)
671 fhandler_tty_slave::close ()
673 /* This used to always call fhandler_tty_common::close when hExeced but that
674 caused multiple closes of the handles associated with this tty. Since
675 close_all_files is not called until after the cygwin process has synced
676 or before a non-cygwin process has exited, it should be safe to just
677 close this normally. cgf 2006-05-20 */
678 cygheap->manage_console_count ("fhandler_tty_slave::close", -1);
680 archetype->usecount--;
681 report_tty_counts (this, "closed", "");
683 if (archetype->usecount)
686 if (archetype->usecount < 0)
687 system_printf ("error: usecount %d", archetype->usecount);
689 termios_printf ("just returning because archetype usecount is != 0");
693 termios_printf ("closing last open %s handle", ttyname ());
694 if (inuse && !CloseHandle (inuse))
695 termios_printf ("CloseHandle (inuse), %E");
696 return fhandler_tty_common::close ();
700 fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
704 a &= GENERIC_READ | GENERIC_WRITE;
705 if (a == GENERIC_READ)
707 if (a == GENERIC_WRITE)
709 if (a == (GENERIC_READ | GENERIC_WRITE))
712 int ret = open (flags);
713 if (ret && !cygwin_finished_initializing && !IsDebuggerPresent ())
715 /* This only occurs when called from dtable::init_std_file_from_handle
716 We have been started from a non-Cygwin process. So we should become
717 tty process group leader.
718 TODO: Investigate how SIGTTIN should be handled with pure-windows
720 tc->pgid = myself->pgid;
723 if (f != INVALID_HANDLE_VALUE)
724 CloseHandle (f); /* Reopened by open */
730 fhandler_tty_slave::write (const void *ptr, size_t len)
732 DWORD n, towrite = len;
734 termios_printf ("tty%d, write(%x, %d)", get_unit (), ptr, len);
736 acquire_output_mutex (INFINITE);
740 n = min (OUT_BUFFER_SIZE, len);
741 char *buf = (char *)ptr;
742 ptr = (char *) ptr + n;
745 /* Previous write may have set write_error to != 0. Check it here.
746 This is less than optimal, but the alternative slows down tty
747 writes enormously. */
748 if (get_ttyp ()->write_error)
750 set_errno (get_ttyp ()->write_error);
751 towrite = (DWORD) -1;
755 if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
757 DWORD err = GetLastError ();
758 termios_printf ("WriteFile failed, %E");
762 err = ERROR_IO_DEVICE;
764 __seterrno_from_win_error (err);
766 raise (SIGHUP); /* FIXME: Should this be SIGTTOU? */
767 towrite = (DWORD) -1;
771 if (output_done_event != NULL)
775 rc = WaitForSingleObject (output_done_event, x);
776 termios_printf ("waited %d ms for output_done_event, WFSO %d", x, rc);
779 release_output_mutex ();
784 fhandler_tty_slave::read (void *ptr, size_t& len)
788 int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
791 char buf[INP_BUFFER_SIZE];
792 char peek_buf[INP_BUFFER_SIZE];
797 termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
799 if (!ptr) /* Indicating tcflush(). */
801 else if ((get_ttyp ()->ti.c_lflag & ICANON))
802 time_to_wait = INFINITE;
805 vmin = get_ttyp ()->ti.c_cc[VMIN];
806 if (vmin > INP_BUFFER_SIZE)
807 vmin = INP_BUFFER_SIZE;
808 vtime = get_ttyp ()->ti.c_cc[VTIME];
816 time_to_wait = !vtime ? INFINITE : 100 * vtime;
819 w4[0] = signal_arrived;
820 w4[1] = input_available_event;
822 DWORD waiter = time_to_wait;
825 rc = WaitForMultipleObjects (2, w4, FALSE, waiter);
827 if (rc == WAIT_TIMEOUT)
829 termios_printf ("wait timed out, waiter %u", waiter);
833 if (rc == WAIT_FAILED)
835 termios_printf ("wait for input event failed, %E");
839 if (rc == WAIT_OBJECT_0)
841 /* if we've received signal after successfully reading some data,
842 just return all data successfully read */
845 set_sig_errno (EINTR);
850 rc = WaitForSingleObject (input_mutex, 1000);
851 if (rc == WAIT_FAILED)
853 termios_printf ("wait for input mutex failed, %E");
856 else if (rc == WAIT_TIMEOUT)
858 termios_printf ("failed to acquire input mutex after input event arrived");
861 if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
863 termios_printf ("PeekNamedPipe failed, %E");
868 /* On first peek determine no. of bytes to flush. */
869 if (!ptr && len == UINT_MAX)
870 len = (size_t) bytes_in_pipe;
872 if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
874 ReleaseMutex (input_mutex);
875 len = (size_t) bytes_in_pipe;
879 readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
881 if (ptr && vmin && readlen > (unsigned) vmin)
887 termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
888 if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
890 termios_printf ("read failed, %E");
893 /* MSDN states that 5th prameter can be used to determine total
894 number of bytes in pipe, but for some reason this number doesn't
895 change after successful read. So we have to peek into the pipe
896 again to see if input is still available */
897 if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
899 termios_printf ("PeekNamedPipe failed, %E");
909 memcpy (ptr, buf, n);
910 ptr = (char *) ptr + n;
916 ResetEvent (input_available_event);
918 ReleaseMutex (input_mutex);
927 if (get_ttyp ()->read_retval < 0) // read error
929 set_errno (-get_ttyp ()->read_retval);
933 if (get_ttyp ()->read_retval == 0) //EOF
935 termios_printf ("saw EOF");
938 if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
940 if (vmin && totalread >= vmin)
943 /* vmin == 0 && vtime == 0:
944 * we've already read all input, if any, so return immediately
945 * vmin == 0 && vtime > 0:
946 * we've waited for input 10*vtime ms in WFSO(input_available_event),
947 * no matter whether any input arrived, we shouldn't wait any longer,
948 * so return immediately
949 * vmin > 0 && vtime == 0:
950 * here, totalread < vmin, so continue waiting until more data
952 * vmin > 0 && vtime > 0:
953 * similar to the previous here, totalread < vmin, and timer
954 * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
955 * so "restart timer" and wait until more data arrive
962 waiter = time_to_wait;
964 termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
965 len = (size_t) totalread;
969 fhandler_tty_slave::dup (fhandler_base *child)
971 fhandler_tty_slave *arch = (fhandler_tty_slave *) archetype;
972 *(fhandler_tty_slave *) child = *arch;
973 child->set_flags (get_flags ());
976 cygheap->manage_console_count ("fhandler_tty_slave::dup", 1);
977 report_tty_counts (child, "duped", "");
982 fhandler_pty_master::dup (fhandler_base *child)
984 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
985 *(fhandler_tty_master *) child = *arch;
986 child->set_flags (get_flags ());
989 report_tty_counts (child, "duped master", "");
994 fhandler_tty_slave::tcgetattr (struct termios *t)
996 *t = get_ttyp ()->ti;
1001 fhandler_tty_slave::tcsetattr (int, const struct termios *t)
1003 acquire_output_mutex (INFINITE);
1004 get_ttyp ()->ti = *t;
1005 release_output_mutex ();
1010 fhandler_tty_slave::tcflush (int queue)
1014 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1016 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1018 size_t len = UINT_MAX;
1020 ret = ((int) len) >= 0 ? 0 : -1;
1022 if (queue == TCOFLUSH || queue == TCIOFLUSH)
1024 /* do nothing for now. */
1027 termios_printf ("%d=tcflush(%d)", ret, queue);
1032 fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
1034 termios_printf ("ioctl (%x)", cmd);
1036 if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid
1037 && myself->ctty == get_unit () && (get_ttyp ()->ti.c_lflag & TOSTOP))
1039 /* background process */
1040 termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
1041 get_ttyp ()->getpgid (), myctty ());
1055 set_nonblocking (*(int *) arg);
1063 acquire_output_mutex (INFINITE);
1065 get_ttyp ()->cmd = cmd;
1066 get_ttyp ()->ioctl_retval = 0;
1071 get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1072 if (ioctl_request_event)
1073 SetEvent (ioctl_request_event);
1074 *(struct winsize *) arg = get_ttyp ()->arg.winsize;
1075 if (ioctl_done_event)
1076 WaitForSingleObject (ioctl_done_event, INFINITE);
1077 get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1080 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1081 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1083 get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1084 if (ioctl_request_event)
1086 get_ttyp ()->ioctl_retval = -EINVAL;
1087 SetEvent (ioctl_request_event);
1091 get_ttyp ()->winsize = *(struct winsize *) arg;
1092 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1094 if (ioctl_done_event)
1095 WaitForSingleObject (ioctl_done_event, INFINITE);
1099 val = *(unsigned char *) arg;
1100 if (val != 6 || !ioctl_request_event || !ioctl_done_event)
1101 get_ttyp ()->ioctl_retval = -EINVAL;
1104 get_ttyp ()->arg.value = val;
1105 SetEvent (ioctl_request_event);
1106 WaitForSingleObject (ioctl_done_event, INFINITE);
1107 *(unsigned char *) arg = (unsigned char) (get_ttyp ()->arg.value);
1111 if (ioctl_request_event)
1113 SetEvent (ioctl_request_event);
1114 if (ioctl_done_event)
1115 WaitForSingleObject (ioctl_done_event, INFINITE);
1116 *(int *) arg = get_ttyp ()->arg.value;
1119 get_ttyp ()->ioctl_retval = -EINVAL;
1122 if (ioctl_request_event)
1124 get_ttyp ()->arg.value = (int) arg;
1125 SetEvent (ioctl_request_event);
1126 if (ioctl_done_event)
1127 WaitForSingleObject (ioctl_done_event, INFINITE);
1130 get_ttyp ()->ioctl_retval = -EINVAL;
1134 release_output_mutex ();
1135 retval = get_ttyp ()->ioctl_retval;
1138 set_errno (-retval);
1143 termios_printf ("%d = ioctl (%x)", retval, cmd);
1148 fhandler_tty_slave::fstat (struct __stat64 *st)
1150 fhandler_base::fstat (st);
1152 bool to_close = false;
1153 if (!input_available_event)
1156 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1157 input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
1158 if (input_available_event)
1161 if (!input_available_event
1162 || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
1165 /* If we can't access the ACL, or if the tty doesn't actually exist,
1166 then fake uid and gid to strict, system-like values. */
1167 st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
1172 CloseHandle (input_available_event);
1176 /* Helper function for fchmod and fchown, which just opens all handles
1177 and signals success via bool return. */
1179 fhandler_tty_slave::fch_open_handles ()
1183 tc = cygwin_shared->tty[get_unit ()];
1184 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1185 input_available_event = OpenEvent (READ_CONTROL | WRITE_DAC | WRITE_OWNER,
1187 output_mutex = get_ttyp ()->open_output_mutex (WRITE_DAC | WRITE_OWNER);
1188 input_mutex = get_ttyp ()->open_input_mutex (WRITE_DAC | WRITE_OWNER);
1189 inuse = get_ttyp ()->open_inuse (WRITE_DAC | WRITE_OWNER);
1190 if (!input_available_event || !output_mutex || !input_mutex || !inuse)
1195 /* These members are optional, no error checking */
1196 shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
1197 output_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1198 shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
1199 ioctl_request_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1200 shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
1201 ioctl_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1205 /* Helper function for fchmod and fchown, which sets the new security
1206 descriptor on all objects representing the tty. */
1208 fhandler_tty_slave::fch_set_sd (security_descriptor &sd, bool chown)
1210 security_descriptor sd_old;
1212 get_object_sd (input_available_event, sd_old);
1213 if (!set_object_sd (input_available_event, sd, chown)
1214 && !set_object_sd (output_mutex, sd, chown)
1215 && !set_object_sd (input_mutex, sd, chown)
1216 && !set_object_sd (inuse, sd, chown)
1217 && (!output_done_event
1218 || !set_object_sd (output_done_event, sd, chown))
1219 && (!ioctl_request_event
1220 || !set_object_sd (ioctl_request_event, sd, chown))
1221 && (!ioctl_done_event
1222 || !set_object_sd (ioctl_done_event, sd, chown)))
1224 set_object_sd (input_available_event, sd_old, chown);
1225 set_object_sd (output_mutex, sd_old, chown);
1226 set_object_sd (input_mutex, sd_old, chown);
1227 set_object_sd (inuse, sd_old, chown);
1228 if (!output_done_event)
1229 set_object_sd (output_done_event, sd_old, chown);
1230 if (!ioctl_request_event)
1231 set_object_sd (ioctl_request_event, sd_old, chown);
1232 if (!ioctl_done_event)
1233 set_object_sd (ioctl_done_event, sd_old, chown);
1237 /* Helper function for fchmod and fchown, which closes all object handles in
1240 fhandler_tty_slave::fch_close_handles ()
1242 close_maybe (get_io_handle ());
1243 close_maybe (get_output_handle ());
1244 close_maybe (output_done_event);
1245 close_maybe (ioctl_done_event);
1246 close_maybe (ioctl_request_event);
1247 close_maybe (input_available_event);
1248 close_maybe (output_mutex);
1249 close_maybe (input_mutex);
1250 close_maybe (inuse);
1254 fhandler_tty_slave::fchmod (mode_t mode)
1257 bool to_close = false;
1258 security_descriptor sd;
1262 if (!input_available_event)
1265 if (!fch_open_handles ())
1268 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1269 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1270 if (!get_object_attribute (input_available_event, &uid, &gid, NULL)
1271 && !create_object_sd_from_attribute (NULL, uid, gid, S_IFCHR | mode, sd))
1272 ret = fch_set_sd (sd, false);
1275 fch_close_handles ();
1280 fhandler_tty_slave::fchown (__uid32_t uid, __gid32_t gid)
1283 bool to_close = false;
1287 security_descriptor sd;
1289 if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
1291 if (!input_available_event)
1294 if (!fch_open_handles ())
1297 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1298 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1299 if (!get_object_attribute (input_available_event, &o_uid, &o_gid, &mode))
1301 if ((uid == ILLEGAL_UID || uid == o_uid)
1302 && (gid == ILLEGAL_GID || gid == o_gid))
1304 else if (!create_object_sd_from_attribute (input_available_event,
1305 uid, gid, S_IFCHR | mode, sd))
1306 ret = fch_set_sd (sd, true);
1310 fch_close_handles ();
1314 /*******************************************************
1317 fhandler_pty_master::fhandler_pty_master ()
1318 : fhandler_tty_common (), pktmode (0), need_nl (0), dwProcessId (0)
1323 fhandler_pty_master::open (int flags, mode_t)
1326 ntty = cygwin_shared->tty.allocate (false);
1330 dev().devn = FHDEV (DEV_TTYM_MAJOR, ntty);
1333 lock_ttys::release ();
1336 lock_ttys::release ();
1337 set_flags ((flags & ~O_TEXT) | O_BINARY);
1340 // FIXME: Do this better someday
1341 fhandler_pty_master *arch = (fhandler_tty_master *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
1342 *((fhandler_pty_master **) cygheap->fdtab.add_archetype ()) = arch;
1345 arch->dwProcessId = GetCurrentProcessId ();
1349 char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
1350 __small_sprintf (buf, "opened pty master for tty%d", get_unit ());
1351 report_tty_counts (this, buf, "");
1356 fhandler_tty_common::lseek (_off64_t, int)
1363 fhandler_tty_common::close ()
1365 termios_printf ("tty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1366 if (output_done_event && !CloseHandle (output_done_event))
1367 termios_printf ("CloseHandle (output_done_event), %E");
1368 if (ioctl_done_event && !CloseHandle (ioctl_done_event))
1369 termios_printf ("CloseHandle (ioctl_done_event), %E");
1370 if (ioctl_request_event && !CloseHandle (ioctl_request_event))
1371 termios_printf ("CloseHandle (ioctl_request_event), %E");
1372 if (!ForceCloseHandle (input_mutex))
1373 termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
1374 if (!ForceCloseHandle (output_mutex))
1375 termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
1376 if (!ForceCloseHandle1 (get_handle (), from_pty))
1377 termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1378 if (!ForceCloseHandle1 (get_output_handle (), to_pty))
1379 termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
1381 if (!ForceCloseHandle (input_available_event))
1382 termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1388 fhandler_pty_master::close ()
1391 while (accept_input () > 0)
1394 archetype->usecount--;
1395 report_tty_counts (this, "closing master", "");
1397 if (archetype->usecount)
1400 if (archetype->usecount < 0)
1401 system_printf ("error: usecount %d", archetype->usecount);
1403 termios_printf ("just returning because archetype usecount is != 0");
1407 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1408 termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1409 arch->from_master, arch->to_master, arch->dwProcessId);
1410 if (cygwin_finished_initializing)
1412 if (arch->master_ctl && get_ttyp ()->master_pid == myself->pid)
1415 pipe_request req = { (DWORD) -1 };
1419 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1420 &installation_key, get_unit ());
1421 CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500);
1422 CloseHandle (arch->master_ctl);
1423 arch->master_thread->detach ();
1425 if (!ForceCloseHandle (arch->from_master))
1426 termios_printf ("error closing from_master %p, %E", arch->from_master);
1427 if (!ForceCloseHandle (arch->to_master))
1428 termios_printf ("error closing from_master %p, %E", arch->to_master);
1430 fhandler_tty_common::close ();
1432 if (hExeced || get_ttyp ()->master_pid != myself->pid)
1433 termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid);
1435 get_ttyp ()->set_master_closed ();
1441 fhandler_pty_master::write (const void *ptr, size_t len)
1444 char *p = (char *) ptr;
1445 termios ti = tc->ti;
1447 for (i = 0; i < (int) len; i++)
1449 line_edit_status status = line_edit (p++, 1, ti);
1450 if (status > line_edit_signalled)
1452 if (status != line_edit_pipe_full)
1461 fhandler_pty_master::read (void *ptr, size_t& len)
1463 len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1467 fhandler_pty_master::tcgetattr (struct termios *t)
1469 *t = cygwin_shared->tty[get_unit ()]->ti;
1474 fhandler_pty_master::tcsetattr (int, const struct termios *t)
1476 cygwin_shared->tty[get_unit ()]->ti = *t;
1481 fhandler_pty_master::tcflush (int queue)
1485 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1487 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1488 ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1489 else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1491 /* do nothing for now. */
1494 termios_printf ("%d=tcflush(%d)", ret, queue);
1499 fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1504 pktmode = *(int *) arg;
1507 *(struct winsize *) arg = get_ttyp ()->winsize;
1510 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1511 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1513 get_ttyp ()->winsize = *(struct winsize *) arg;
1514 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1518 set_nonblocking (*(int *) arg);
1528 fhandler_pty_master::ptsname ()
1530 static char buf[TTY_NAME_MAX];
1532 __small_sprintf (buf, "/dev/tty%d", get_unit ());
1537 fhandler_tty_common::set_close_on_exec (bool val)
1539 // Cygwin processes will handle this specially on exec.
1540 close_on_exec (val);
1544 fhandler_tty_slave::fixup_after_fork (HANDLE parent)
1546 // fork_fixup (parent, inuse, "inuse");
1547 // fhandler_tty_common::fixup_after_fork (parent);
1548 report_tty_counts (this, "inherited", "");
1552 fhandler_tty_slave::fixup_after_exec ()
1554 if (!close_on_exec ())
1555 fixup_after_fork (NULL);
1559 fhandler_tty_master::init_console ()
1561 console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym");
1562 if (console == NULL)
1565 console->init (INVALID_HANDLE_VALUE, GENERIC_READ | GENERIC_WRITE, O_BINARY);
1566 cygheap->manage_console_count ("fhandler_tty_master::init_console", -1, true);
1567 console->uninterruptible_io (true);
1571 extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
1573 /* This thread function handles the master control pipe. It waits for a
1574 client to connect. Then it checks if the client process has permissions
1575 to access the tty handles. If so, it opens the client process and
1576 duplicates the handles into that process. If that fails, it sends a reply
1577 with at least one handle set to NULL and an error code. Last but not
1578 least, the client is disconnected and the thread waits for the next client.
1580 A special case is when the master side of the tty is about to be closed.
1581 The client side is the fhandler_pty_master::close function and it sends
1582 a PID -1 in that case. On Vista and later a check is performed that the
1583 request to leave really comes from the master process itself. On earlier
1584 OSes there's no function to check for the PID of the client process so
1585 we have to trust the client side.
1588 always only one pipe instance, there's a chance that clients have to
1589 wait to connect to the master control pipe. Therefore the client calls
1590 to CallNamedPipe should have a big enough timeout value. For now this
1591 is 500ms. Hope that's enough. */
1594 fhandler_pty_master::pty_master_thread ()
1597 GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
1598 EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
1601 security_descriptor sd;
1607 termios_printf ("Entered");
1608 while (!exit && ConnectNamedPipe (master_ctl, NULL))
1610 pipe_reply repl = { NULL, NULL, 0 };
1613 ACCESS_MASK access = EVENT_MODIFY_STATE;
1614 HANDLE client = NULL;
1616 if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
1618 termios_printf ("ReadFile, %E");
1621 /* This function is only available since Vista, unfortunately.
1622 In earlier OSes we simply have to believe that the client
1623 has no malicious intent (== sends arbitrary PIDs). */
1624 if (!GetNamedPipeClientProcessId (master_ctl, &pid))
1626 if (get_object_sd (input_available_event, sd))
1628 termios_printf ("get_object_sd, %E");
1631 cygheap->user.deimpersonate ();
1633 if (!ImpersonateNamedPipeClient (master_ctl))
1635 termios_printf ("ImpersonateNamedPipeClient, %E");
1638 if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &token))
1640 termios_printf ("OpenThreadToken, %E");
1644 ret = AccessCheck (sd, token, access, &map, &ps, &len, &access, &allow);
1645 CloseHandle (token);
1648 termios_printf ("AccessCheck, %E");
1651 if (!RevertToSelf ())
1653 termios_printf ("RevertToSelf, %E");
1656 if (req.pid == (DWORD) -1) /* Request to finish thread. */
1658 /* Pre-Vista: Just believe in the good of the client process.
1659 Post-Vista: Check if the requesting process is the master
1661 if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
1667 client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
1670 termios_printf ("OpenProcess, %E");
1673 if (!DuplicateHandle (GetCurrentProcess (), from_master,
1674 client, &repl.from_master,
1675 0, TRUE, DUPLICATE_SAME_ACCESS))
1677 termios_printf ("DuplicateHandle (from_master), %E");
1680 if (!DuplicateHandle (GetCurrentProcess (), to_master,
1681 client, &repl.to_master,
1682 0, TRUE, DUPLICATE_SAME_ACCESS))
1684 termios_printf ("DuplicateHandle (to_master), %E");
1689 repl.error = GetLastError ();
1691 CloseHandle (client);
1693 cygheap->user.reimpersonate ();
1695 termios_printf ("Reply: from %p, to %p, error %lu",
1696 repl.from_master, repl.to_master, repl.error );
1697 if (!WriteFile (master_ctl, &repl, sizeof repl, &len, NULL))
1698 termios_printf ("WriteFile, %E");
1699 if (!DisconnectNamedPipe (master_ctl))
1700 termios_printf ("DisconnectNamedPipe, %E");
1702 termios_printf ("Leaving");
1707 pty_master_thread (VOID *arg)
1709 return ((fhandler_pty_master *) arg)->pty_master_thread ();
1713 fhandler_pty_master::setup (bool ispty)
1716 security_descriptor sd;
1717 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
1719 tty& t = *cygwin_shared->tty[get_unit ()];
1721 tcinit (&t, true); /* Set termios information. Force initialization. */
1723 const char *errstr = NULL;
1724 DWORD pipe_mode = PIPE_NOWAIT;
1726 /* Create communication pipes */
1727 char pipename[sizeof("ttyNNNN-from-master")];
1728 __small_sprintf (pipename, "tty%d-from-master", get_unit ());
1729 res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1730 from_master, get_output_handle (),
1731 128 * 1024, pipename);
1734 errstr = "input pipe";
1738 if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
1739 termios_printf ("can't set output_handle(%p) to non-blocking mode",
1740 get_output_handle ());
1742 __small_sprintf (pipename, "tty%d-to-master", get_unit ());
1743 res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1744 get_io_handle (), to_master,
1745 128 * 1024, pipename);
1748 errstr = "output pipe";
1754 /* Create security attribute. Default permissions are 0620. */
1755 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1756 InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1757 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
1758 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
1760 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
1762 /* Create synchronisation events */
1766 if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT, &sa)))
1768 if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT, &sa)))
1770 if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT,
1775 /* Carefully check that the input_available_event didn't already exist.
1776 This is a measure to make sure that the event security descriptor
1777 isn't occupied by a malicious process. We must make sure that the
1778 event's security descriptor is what we expect it to be. */
1779 if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT,
1781 || GetLastError () == ERROR_ALREADY_EXISTS)
1785 errstr = shared_name (buf, OUTPUT_MUTEX, t.ntty);
1786 if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
1789 errstr = shared_name (buf, INPUT_MUTEX, t.ntty);
1790 if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
1795 /* Create master control pipe which allows the master to duplicate
1796 the pty pipe handles to processes which deserve it. */
1797 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1798 &installation_key, get_unit ());
1799 master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX,
1800 PIPE_WAIT | PIPE_TYPE_MESSAGE
1801 | PIPE_READMODE_MESSAGE, 1, 4096, 4096,
1803 if (master_ctl == INVALID_HANDLE_VALUE)
1805 errstr = "pty master control pipe";
1808 master_thread = new cygthread (::pty_master_thread, this, "pty_master");
1811 errstr = "pty master control thread";
1816 t.from_master = from_master;
1817 t.to_master = to_master;
1818 // /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
1819 // /* screws up tty master */ ProtectHandle1INH (input_mutex, input_mutex);
1820 t.winsize.ws_col = 80;
1821 t.winsize.ws_row = 25;
1822 t.master_pid = myself->pid;
1824 termios_printf ("tty%d opened - from_slave %p, to_slave %p", t.ntty,
1825 get_io_handle (), get_output_handle ());
1830 close_maybe (get_io_handle ());
1831 close_maybe (get_output_handle ());
1832 close_maybe (output_done_event);
1833 close_maybe (ioctl_done_event);
1834 close_maybe (ioctl_request_event);
1835 close_maybe (input_available_event);
1836 close_maybe (output_mutex);
1837 close_maybe (input_mutex);
1838 close_maybe (from_master);
1839 close_maybe (to_master);
1840 close_maybe (master_ctl);
1841 termios_printf ("tty%d open failed - failed to create %s", errstr);
1846 fhandler_pty_master::fixup_after_fork (HANDLE parent)
1848 DWORD wpid = GetCurrentProcessId ();
1849 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1850 if (arch->dwProcessId != wpid)
1852 tty& t = *get_ttyp ();
1853 if (!DuplicateHandle (parent, arch->from_master, GetCurrentProcess (),
1854 &arch->from_master, 0, false, DUPLICATE_SAME_ACCESS))
1855 system_printf ("couldn't duplicate from_parent(%p), %E", arch->from_master);
1856 if (!DuplicateHandle (parent, arch->to_master, GetCurrentProcess (),
1857 &arch->to_master, 0, false, DUPLICATE_SAME_ACCESS))
1858 system_printf ("couldn't duplicate to_parent(%p), %E", arch->from_master);
1859 if (myself->pid == t.master_pid)
1861 t.from_master = arch->from_master;
1862 t.to_master = arch->to_master;
1864 arch->dwProcessId = wpid;
1866 from_master = arch->from_master;
1867 to_master = arch->to_master;
1868 report_tty_counts (this, "inherited master", "");
1872 fhandler_pty_master::fixup_after_exec ()
1874 if (!close_on_exec ())
1875 fixup_after_fork (spawn_info->parent);
1877 from_master = to_master = NULL;