3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009, 2010, 2011 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"
27 #include <asm/socket.h>
29 #define close_maybe(h) \
31 if (h && h != INVALID_HANDLE_VALUE) \
35 /* pty master control pipe messages */
47 fhandler_pty_slave::get_unit ()
49 return dev ().get_minor ();
53 static class mutex_stack
65 fhandler_pty_common::__acquire_output_mutex (const char *fn, int ln,
69 strace.prntf (_STRACE_TERMIOS, fn, "(%d): pty output_mutex (%p): waiting %d ms", ln, output_mutex, ms);
70 DWORD res = WaitForSingleObject (output_mutex, ms);
71 if (res == WAIT_OBJECT_0)
75 strace.prntf (_STRACE_TERMIOS, fn, "(%d): pty output_mutex: acquired", ln, res);
79 ostack[osi].tname = cygthread::name ();
80 termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
88 fhandler_pty_common::__release_output_mutex (const char *fn, int ln)
90 if (ReleaseMutex (output_mutex))
94 strace.prntf (_STRACE_TERMIOS, fn, "(%d): pty output_mutex(%p) released", ln, output_mutex);
98 termios_printf ("released(%p) at %s:%d, osi %d", output_mutex, fn, ln, osi);
99 termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
100 ostack[osi].ln = -ln;
106 system_printf ("couldn't release output mutex but we seem to own it, %E");
112 /* Process pty input. */
115 fhandler_pty_master::doecho (const void *str, DWORD len)
117 acquire_output_mutex (INFINITE);
118 if (!WriteFile (to_master, str, len, &len, NULL))
119 termios_printf ("Write to %p failed, %E", to_master);
120 release_output_mutex ();
124 fhandler_pty_master::accept_input ()
129 WaitForSingleObject (input_mutex, INFINITE);
131 bytes_left = eat_readahead (-1);
135 termios_printf ("sending EOF to slave");
136 get_ttyp ()->read_retval = 0;
144 termios_printf ("about to write %d chars to slave", bytes_left);
145 rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
148 debug_printf ("error writing to pipe %p %E", get_output_handle ());
149 get_ttyp ()->read_retval = -1;
154 get_ttyp ()->read_retval = 1;
156 bytes_left -= written;
159 debug_printf ("to_slave pipe is full");
160 puts_readahead (p, bytes_left);
166 SetEvent (input_available_event);
167 ReleaseMutex (input_mutex);
172 fhandler_pty_master::hit_eof ()
174 if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
176 /* We have the only remaining open handle to this pty, and
177 the slave pty has been opened at least once. We treat
179 termios_printf ("all other handles closed");
185 /* Process pty output requests */
188 fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
191 char outbuf[OUT_BUFFER_SIZE + 1];
201 /* We need to return a left over \n character, resulting from
202 \r\n conversion. Note that we already checked for FLUSHO and
203 output_stopped at the time that we read the character, so we
204 don't check again here. */
215 /* Set RLEN to the number of bytes to read from the pipe. */
217 if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
219 /* We are going to expand \n to \r\n, so don't read more than
220 half of the number of bytes requested. */
225 if (rlen > sizeof outbuf)
226 rlen = sizeof outbuf;
228 HANDLE handle = get_io_handle ();
230 n = 0; // get_readahead_into_buffer (outbuf, len);
233 /* Doing a busy wait like this is quite inefficient, but nothing
234 else seems to work completely. Windows should provide some sort
235 of overlapped I/O for pipes, or something, but it doesn't. */
238 if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
240 termios_printf ("PeekNamedPipe(%p) failed, %E", handle);
247 /* DISCARD (FLUSHO) and tcflush can finish here. */
248 if ((get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
251 if (is_nonblocking ())
257 pthread_testcancel ();
258 if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0
259 && !_my_tls.call_signal_handler ())
267 if (!ReadFile (handle, outbuf, rlen, &n, NULL))
269 termios_printf ("ReadFile failed, %E");
274 termios_printf ("bytes read %u", n);
275 get_ttyp ()->write_error = 0;
277 if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
283 *optr++ = TIOCPKT_DATA;
285 if (!(get_ttyp ()->ti.c_oflag & OPOST)) // post-process output
287 memcpy (optr, outbuf, n);
290 else // raw output mode
299 if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
304 if (get_ttyp ()->ti.c_oflag & OCRNL)
310 if (get_ttyp ()->ti.c_oflag & ONLCR)
315 if (get_ttyp ()->ti.c_oflag & ONLRET)
323 /* Don't store data past the end of the user's buffer. This
324 can happen if the user requests a read of 1 byte when
325 doing \r\n expansion. */
326 if (optr - buf >= (int) len)
328 if (*iptr != '\n' || n != 0)
329 system_printf ("internal error: %d unexpected characters", n);
341 if (GetLastError () == ERROR_BROKEN_PIPE)
352 termios_printf ("returning %d", rc);
356 /* pty slave stuff */
358 fhandler_pty_slave::fhandler_pty_slave (int unit)
359 : fhandler_pty_common (), inuse (NULL)
362 dev ().parse (DEV_PTYS_MAJOR, unit);
366 fhandler_pty_slave::open (int flags, mode_t)
368 HANDLE pty_owner, from_master_local, to_master_local;
371 &from_master_local, &input_available_event, &input_mutex, &inuse,
372 &output_mutex, &to_master_local, &pty_owner,
376 for (HANDLE **h = handles; *h; h++)
379 _tc = cygwin_shared->tty[get_unit ()];
383 cygwin_shared->tty.attach (get_unit ());
385 /* Create synchronisation events */
388 const char *errmsg = NULL;
390 if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
392 errmsg = "open output mutex failed, %E";
395 if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
397 errmsg = "open input mutex failed, %E";
400 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
401 if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
403 errmsg = "open input event failed, %E";
407 /* FIXME: Needs a method to eliminate tty races */
409 /* Create security attribute. Default permissions are 0620. */
410 security_descriptor sd;
411 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
412 RtlCreateSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
413 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
414 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
415 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
417 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
418 acquire_output_mutex (500);
419 inuse = get_ttyp ()->create_inuse (&sa);
420 get_ttyp ()->was_opened = true;
421 release_output_mutex ();
424 if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
426 errmsg = "pty handles have been closed";
431 if (get_ttyp ()->master_pid < 0)
433 errmsg = "*** master is closed";
437 /* Three case for duplicating the pipe handles:
438 - Either we're the master. In this case, just duplicate the handles.
439 - Or, we have the right to open the master process for handle duplication.
440 In this case, just duplicate the handles.
441 - Or, we have to ask the master process itself. In this case, send our
442 pid to the master process and check the reply. The reply contains
443 either the handles, or an error code which tells us why we didn't
445 if (myself->pid == get_ttyp ()->master_pid)
447 /* This is the most common case, just calling openpty. */
448 termios_printf ("dup handles within myself.");
449 pty_owner = GetCurrentProcess ();
453 pinfo p (get_ttyp ()->master_pid);
455 termios_printf ("*** couldn't find pty master");
458 pty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
460 termios_printf ("dup handles directly since I'm the owner");
465 if (!DuplicateHandle (pty_owner, get_ttyp ()->from_master,
466 GetCurrentProcess (), &from_master_local, 0, TRUE,
467 DUPLICATE_SAME_ACCESS))
469 termios_printf ("can't duplicate input from %u/%p, %E",
470 get_ttyp ()->master_pid, get_ttyp ()->from_master);
474 if (!DuplicateHandle (pty_owner, get_ttyp ()->to_master,
475 GetCurrentProcess (), &to_master_local, 0, TRUE,
476 DUPLICATE_SAME_ACCESS))
478 errmsg = "can't duplicate output, %E";
481 if (pty_owner != GetCurrentProcess ())
482 CloseHandle (pty_owner);
486 pipe_request req = { GetCurrentProcessId () };
490 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
491 &installation_key, get_unit ());
492 termios_printf ("dup handles via master control pipe %s", buf);
493 if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl,
496 errmsg = "can't call master, %E";
499 from_master_local = repl.from_master;
500 to_master_local = repl.to_master;
501 if (!from_master_local || !to_master_local)
503 SetLastError (repl.error);
504 errmsg = "error duplicating pipes, %E";
508 VerifyHandle (from_master_local);
509 VerifyHandle (to_master_local);
511 termios_printf ("duplicated from_master %p->%p from pty_owner",
512 get_ttyp ()->from_master, from_master_local);
513 termios_printf ("duplicated to_master %p->%p from pty_owner",
514 get_ttyp ()->to_master, to_master_local);
516 set_io_handle (from_master_local);
517 set_output_handle (to_master_local);
520 if (cygheap->manage_console_count ("fhandler_pty_slave::open", 1) == 1)
521 fhandler_console::need_invisible ();
525 if (GetLastError () == ERROR_FILE_NOT_FOUND)
530 termios_printf (errmsg);
532 for (HANDLE **h = handles; *h; h++)
533 if (**h && **h != INVALID_HANDLE_VALUE)
539 fhandler_pty_slave::open_setup (int flags)
541 set_flags ((flags & ~O_TEXT) | O_BINARY);
542 myself->set_ctty (this, flags);
543 cygheap->manage_console_count ("fhandler_pty_slave::open_setup", 1);
544 report_tty_counts (this, "opened", "");
548 fhandler_pty_slave::cleanup ()
550 /* This used to always call fhandler_pty_common::close when we were execing
551 but that caused multiple closes of the handles associated with this pty.
552 Since close_all_files is not called until after the cygwin process has
553 synced or before a non-cygwin process has exited, it should be safe to
554 just close this normally. cgf 2006-05-20 */
555 cygheap->manage_console_count ("fhandler_pty_slave::close", -1);
556 report_tty_counts (this, "closed", "");
560 fhandler_pty_slave::close ()
562 termios_printf ("closing last open %s handle", ttyname ());
563 if (inuse && !CloseHandle (inuse))
564 termios_printf ("CloseHandle (inuse), %E");
565 return fhandler_pty_common::close ();
569 fhandler_pty_slave::init (HANDLE h, DWORD a, mode_t)
573 a &= GENERIC_READ | GENERIC_WRITE;
574 if (a == GENERIC_READ)
576 if (a == GENERIC_WRITE)
578 if (a == (GENERIC_READ | GENERIC_WRITE))
581 int ret = open_with_arch (flags);
583 if (ret && !cygwin_finished_initializing && !being_debugged ())
585 /* This only occurs when called from dtable::init_std_file_from_handle
586 We have been started from a non-Cygwin process. So we should become
587 pty process group leader.
588 TODO: Investigate how SIGTTIN should be handled with pure-windows
590 pinfo p (tc ()->getpgid ());
591 /* We should only grab this when the process group owner for this
592 pty is a non-cygwin process or we've been started directly
593 from a non-Cygwin process with no Cygwin ancestry. */
594 if (!p || ISSTATE (p, PID_NOTCYGWIN))
596 termios_printf ("Setting process group leader to %d since %W(%d) is not a cygwin process",
597 myself->pgid, p->progname, p->pid);
598 tc ()->setpgid (myself->pgid);
602 if (h != INVALID_HANDLE_VALUE)
603 CloseHandle (h); /* Reopened by open */
609 fhandler_pty_slave::write (const void *ptr, size_t len)
611 DWORD n, towrite = len;
613 bg_check_types bg = bg_check (SIGTTOU);
617 termios_printf ("pty%d, write(%x, %d)", get_unit (), ptr, len);
619 push_process_state process_state (PID_TTYOU);
621 acquire_output_mutex (INFINITE);
625 n = min (OUT_BUFFER_SIZE, len);
626 char *buf = (char *)ptr;
627 ptr = (char *) ptr + n;
630 /* Previous write may have set write_error to != 0. Check it here.
631 This is less than optimal, but the alternative slows down pty
632 writes enormously. */
633 if (get_ttyp ()->write_error)
635 set_errno (get_ttyp ()->write_error);
636 towrite = (DWORD) -1;
640 if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
642 DWORD err = GetLastError ();
643 termios_printf ("WriteFile failed, %E");
647 err = ERROR_IO_DEVICE;
649 __seterrno_from_win_error (err);
651 raise (SIGHUP); /* FIXME: Should this be SIGTTOU? */
652 towrite = (DWORD) -1;
656 release_output_mutex ();
661 fhandler_pty_slave::read (void *ptr, size_t& len)
665 int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
668 char buf[INP_BUFFER_SIZE];
669 char peek_buf[INP_BUFFER_SIZE];
672 bg_check_types bg = bg_check (SIGTTIN);
679 termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
681 push_process_state process_state (PID_TTYIN);
683 if (is_nonblocking () || !ptr) /* Indicating tcflush(). */
685 else if ((get_ttyp ()->ti.c_lflag & ICANON))
686 time_to_wait = INFINITE;
689 vmin = get_ttyp ()->ti.c_cc[VMIN];
690 if (vmin > INP_BUFFER_SIZE)
691 vmin = INP_BUFFER_SIZE;
692 vtime = get_ttyp ()->ti.c_cc[VTIME];
700 time_to_wait = !vtime ? INFINITE : 100 * vtime;
705 HANDLE w4[3] = { input_available_event, signal_arrived,
706 pthread::get_cancel_event () };
707 DWORD cnt = w4[2] ? 3 : 2;
708 switch (WaitForMultipleObjects (cnt, w4, FALSE, time_to_wait))
712 case WAIT_OBJECT_0 + 1:
715 if (_my_tls.call_signal_handler ())
717 termios_printf ("wait catched signal");
718 set_sig_errno (EINTR);
721 case WAIT_OBJECT_0 + 2:
722 process_state.pop ();
723 pthread::static_cancel_self ();
726 termios_printf ("wait timed out, time_to_wait %u", time_to_wait);
729 set_sig_errno (EAGAIN);
734 termios_printf ("wait for input event failed, %E");
742 /* Now that we know that input is available we have to grab the
745 switch (WaitForMultipleObjects (cnt, w4, FALSE, 1000))
748 case WAIT_ABANDONED_0:
750 case WAIT_OBJECT_0 + 1:
753 if (_my_tls.call_signal_handler ())
755 termios_printf ("wait for mutex catched signal");
756 set_sig_errno (EINTR);
759 case WAIT_OBJECT_0 + 2:
760 process_state.pop ();
761 pthread::static_cancel_self ();
764 termios_printf ("failed to acquire input mutex after input event "
766 /* If we have a timeout, we can simply handle this failure to
767 grab the mutex as an EAGAIN situation. Otherwise, if this
768 is an infinitely blocking read, restart the loop. */
769 if (time_to_wait != INFINITE)
773 set_sig_errno (EAGAIN);
780 termios_printf ("wait for input mutex failed, %E");
788 if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
790 termios_printf ("PeekNamedPipe failed, %E");
795 /* On first peek determine no. of bytes to flush. */
796 if (!ptr && len == UINT_MAX)
797 len = (size_t) bytes_in_pipe;
799 if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
801 ReleaseMutex (input_mutex);
802 len = (size_t) bytes_in_pipe;
806 readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
808 if (ptr && vmin && readlen > (unsigned) vmin)
814 termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
815 if (!ReadFile (get_handle (), buf, readlen, &n, NULL))
817 termios_printf ("read failed, %E");
820 /* MSDN states that 5th prameter can be used to determine total
821 number of bytes in pipe, but for some reason this number doesn't
822 change after successful read. So we have to peek into the pipe
823 again to see if input is still available */
824 if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
826 termios_printf ("PeekNamedPipe failed, %E");
836 memcpy (ptr, buf, n);
837 ptr = (char *) ptr + n;
843 ResetEvent (input_available_event);
845 ReleaseMutex (input_mutex);
854 if (get_ttyp ()->read_retval < 0) // read error
856 set_errno (-get_ttyp ()->read_retval);
860 if (get_ttyp ()->read_retval == 0) //EOF
862 termios_printf ("saw EOF");
865 if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
867 if (vmin && totalread >= vmin)
870 /* vmin == 0 && vtime == 0:
871 * we've already read all input, if any, so return immediately
872 * vmin == 0 && vtime > 0:
873 * we've waited for input 10*vtime ms in WFSO(input_available_event),
874 * no matter whether any input arrived, we shouldn't wait any longer,
875 * so return immediately
876 * vmin > 0 && vtime == 0:
877 * here, totalread < vmin, so continue waiting until more data
879 * vmin > 0 && vtime > 0:
880 * similar to the previous here, totalread < vmin, and timer
881 * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
882 * so "restart timer" and wait until more data arrive
889 termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
890 len = (size_t) totalread;
894 fhandler_pty_slave::dup (fhandler_base *child, int flags)
896 myself->set_ctty (this, flags);
897 cygheap->manage_console_count ("fhandler_pty_slave::dup", 1);
898 report_tty_counts (child, "duped slave", "");
903 fhandler_pty_master::dup (fhandler_base *child, int)
905 report_tty_counts (child, "duped master", "");
910 fhandler_pty_slave::tcgetattr (struct termios *t)
912 *t = get_ttyp ()->ti;
917 fhandler_pty_slave::tcsetattr (int, const struct termios *t)
919 acquire_output_mutex (INFINITE);
920 get_ttyp ()->ti = *t;
921 release_output_mutex ();
926 fhandler_pty_slave::tcflush (int queue)
930 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
932 if (queue == TCIFLUSH || queue == TCIOFLUSH)
934 size_t len = UINT_MAX;
936 ret = ((int) len) >= 0 ? 0 : -1;
938 if (queue == TCOFLUSH || queue == TCIOFLUSH)
940 /* do nothing for now. */
943 termios_printf ("%d=tcflush(%d)", ret, queue);
948 fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
950 termios_printf ("ioctl (%x)", cmd);
951 int res = fhandler_termios::ioctl (cmd, arg);
955 if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid
956 && (unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_unit ())
957 && (get_ttyp ()->ti.c_lflag & TOSTOP))
959 /* background process */
960 termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
961 get_ttyp ()->getpgid (), myctty ());
973 pid_t pid = this->tcgetpgrp ();
978 *((pid_t *) arg) = pid;
984 retval = this->tcsetpgrp ((pid_t) arg);
989 if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL))
1002 return fhandler_base::ioctl (cmd, arg);
1005 acquire_output_mutex (INFINITE);
1007 get_ttyp ()->cmd = cmd;
1008 get_ttyp ()->ioctl_retval = 0;
1012 get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1013 *(struct winsize *) arg = get_ttyp ()->arg.winsize;
1014 get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1017 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1018 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1020 get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1021 get_ttyp ()->winsize = *(struct winsize *) arg;
1022 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1027 release_output_mutex ();
1028 retval = get_ttyp ()->ioctl_retval;
1031 set_errno (-retval);
1036 termios_printf ("%d = ioctl (%x)", retval, cmd);
1041 fhandler_pty_slave::fstat (struct __stat64 *st)
1043 fhandler_base::fstat (st);
1045 bool to_close = false;
1046 if (!input_available_event)
1049 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1050 input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
1051 if (input_available_event)
1054 if (!input_available_event
1055 || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
1058 /* If we can't access the ACL, or if the tty doesn't actually exist,
1059 then fake uid and gid to strict, system-like values. */
1060 st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
1065 CloseHandle (input_available_event);
1069 /* Helper function for fchmod and fchown, which just opens all handles
1070 and signals success via bool return. */
1072 fhandler_pty_slave::fch_open_handles ()
1076 _tc = cygwin_shared->tty[get_unit ()];
1077 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1078 input_available_event = OpenEvent (READ_CONTROL | WRITE_DAC | WRITE_OWNER,
1080 output_mutex = get_ttyp ()->open_output_mutex (WRITE_DAC | WRITE_OWNER);
1081 input_mutex = get_ttyp ()->open_input_mutex (WRITE_DAC | WRITE_OWNER);
1082 inuse = get_ttyp ()->open_inuse (WRITE_DAC | WRITE_OWNER);
1083 if (!input_available_event || !output_mutex || !input_mutex || !inuse)
1091 /* Helper function for fchmod and fchown, which sets the new security
1092 descriptor on all objects representing the pty. */
1094 fhandler_pty_slave::fch_set_sd (security_descriptor &sd, bool chown)
1096 security_descriptor sd_old;
1098 get_object_sd (input_available_event, sd_old);
1099 if (!set_object_sd (input_available_event, sd, chown)
1100 && !set_object_sd (output_mutex, sd, chown)
1101 && !set_object_sd (input_mutex, sd, chown)
1102 && !set_object_sd (inuse, sd, chown))
1104 set_object_sd (input_available_event, sd_old, chown);
1105 set_object_sd (output_mutex, sd_old, chown);
1106 set_object_sd (input_mutex, sd_old, chown);
1107 set_object_sd (inuse, sd_old, chown);
1111 /* Helper function for fchmod and fchown, which closes all object handles in
1114 fhandler_pty_slave::fch_close_handles ()
1116 close_maybe (get_io_handle ());
1117 close_maybe (get_output_handle ());
1118 close_maybe (input_available_event);
1119 close_maybe (output_mutex);
1120 close_maybe (input_mutex);
1121 close_maybe (inuse);
1125 fhandler_pty_slave::fchmod (mode_t mode)
1128 bool to_close = false;
1129 security_descriptor sd;
1133 if (!input_available_event)
1136 if (!fch_open_handles ())
1139 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1140 RtlCreateSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1141 if (!get_object_attribute (input_available_event, &uid, &gid, NULL)
1142 && !create_object_sd_from_attribute (NULL, uid, gid, S_IFCHR | mode, sd))
1143 ret = fch_set_sd (sd, false);
1146 fch_close_handles ();
1151 fhandler_pty_slave::fchown (__uid32_t uid, __gid32_t gid)
1154 bool to_close = false;
1158 security_descriptor sd;
1160 if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
1162 if (!input_available_event)
1165 if (!fch_open_handles ())
1168 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1169 RtlCreateSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1170 if (!get_object_attribute (input_available_event, &o_uid, &o_gid, &mode))
1172 if ((uid == ILLEGAL_UID || uid == o_uid)
1173 && (gid == ILLEGAL_GID || gid == o_gid))
1175 else if (!create_object_sd_from_attribute (input_available_event,
1176 uid, gid, S_IFCHR | mode, sd))
1177 ret = fch_set_sd (sd, true);
1181 fch_close_handles ();
1185 /*******************************************************
1188 fhandler_pty_master::fhandler_pty_master (int unit)
1189 : fhandler_pty_common (), pktmode (0), master_ctl (NULL),
1190 master_thread (NULL), from_master (NULL), to_master (NULL),
1191 dwProcessId (0), need_nl (0)
1194 dev ().parse (DEV_PTYM_MAJOR, unit);
1197 dev ().parse (FH_ERROR);
1200 set_name ("/dev/ptmx");
1204 fhandler_pty_master::open (int flags, mode_t)
1207 dwProcessId = GetCurrentProcessId ();
1212 fhandler_pty_master::open_setup (int flags)
1214 set_flags ((flags & ~O_TEXT) | O_BINARY);
1215 char buf[sizeof ("opened pty master for ptyNNNNNNNNNNN")];
1216 __small_sprintf (buf, "opened pty master for pty%d", get_unit ());
1217 report_tty_counts (this, buf, "");
1221 fhandler_pty_common::lseek (_off64_t, int)
1228 fhandler_pty_common::close ()
1230 termios_printf ("pty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1231 if (!ForceCloseHandle (input_mutex))
1232 termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
1233 if (!ForceCloseHandle (output_mutex))
1234 termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
1235 if (!ForceCloseHandle1 (get_handle (), from_pty))
1236 termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1237 if (!ForceCloseHandle1 (get_output_handle (), to_pty))
1238 termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
1240 if (!ForceCloseHandle (input_available_event))
1241 termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1247 fhandler_pty_master::cleanup ()
1249 report_tty_counts (this, "closing master", "");
1251 from_master = to_master = NULL;
1255 fhandler_pty_master::close ()
1258 while (accept_input () > 0)
1262 termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1263 from_master, to_master, dwProcessId);
1264 if (cygwin_finished_initializing)
1266 if (master_ctl && get_ttyp ()->master_pid == myself->pid)
1269 pipe_request req = { (DWORD) -1 };
1273 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
1274 &installation_key, get_unit ());
1275 CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500);
1276 CloseHandle (master_ctl);
1277 master_thread->detach ();
1281 if (!ForceCloseHandle (from_master))
1282 termios_printf ("error closing from_master %p, %E", from_master);
1283 if (!ForceCloseHandle (to_master))
1284 termios_printf ("error closing from_master %p, %E", to_master);
1285 from_master = to_master = NULL;
1287 fhandler_pty_common::close ();
1289 if (have_execed || get_ttyp ()->master_pid != myself->pid)
1290 termios_printf ("not clearing: %d, master_pid %d", have_execed, get_ttyp ()->master_pid);
1292 get_ttyp ()->set_master_closed ();
1297 /* This is just to catch error conditions. Since the constructor
1298 ctually opens some handles, and stat() does not open an fd, they need
1299 to be closed when the fhandler goes away. */
1300 fhandler_pty_master::~fhandler_pty_master ()
1302 if (from_master && to_master)
1307 fhandler_pty_master::write (const void *ptr, size_t len)
1310 char *p = (char *) ptr;
1311 termios ti = tc ()->ti;
1313 bg_check_types bg = bg_check (SIGTTOU);
1315 return (ssize_t) bg;
1317 push_process_state process_state (PID_TTYOU);
1319 for (i = 0; i < (int) len; i++)
1321 line_edit_status status = line_edit (p++, 1, ti);
1322 if (status > line_edit_signalled)
1324 if (status != line_edit_pipe_full)
1333 fhandler_pty_master::read (void *ptr, size_t& len)
1335 bg_check_types bg = bg_check (SIGTTIN);
1341 push_process_state process_state (PID_TTYIN);
1342 len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1346 fhandler_pty_master::tcgetattr (struct termios *t)
1348 *t = cygwin_shared->tty[get_unit ()]->ti;
1353 fhandler_pty_master::tcsetattr (int, const struct termios *t)
1355 cygwin_shared->tty[get_unit ()]->ti = *t;
1360 fhandler_pty_master::tcflush (int queue)
1364 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1366 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1367 ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1368 else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1370 /* do nothing for now. */
1373 termios_printf ("%d=tcflush(%d)", ret, queue);
1378 fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1380 int res = fhandler_termios::ioctl (cmd, arg);
1387 pktmode = *(int *) arg;
1390 *(struct winsize *) arg = get_ttyp ()->winsize;
1393 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1394 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1396 get_ttyp ()->winsize = *(struct winsize *) arg;
1397 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1401 *((pid_t *) arg) = this->tcgetpgrp ();
1404 return this->tcsetpgrp ((pid_t) arg);
1408 if (!PeekNamedPipe (to_master, NULL, 0, NULL, (DWORD *) &n, NULL))
1417 return fhandler_base::ioctl (cmd, arg);
1423 fhandler_pty_master::ptsname_r (char *buf, size_t buflen)
1425 char tmpbuf[TTY_NAME_MAX];
1427 __ptsname (tmpbuf, get_unit ());
1428 if (buflen <= strlen (tmpbuf))
1433 strcpy (buf, tmpbuf);
1438 fhandler_pty_common::set_close_on_exec (bool val)
1440 // Cygwin processes will handle this specially on exec.
1441 close_on_exec (val);
1445 fhandler_pty_slave::fixup_after_fork (HANDLE parent)
1447 // fork_fixup (parent, inuse, "inuse");
1448 // fhandler_pty_common::fixup_after_fork (parent);
1449 report_tty_counts (this, "inherited", "");
1453 fhandler_pty_slave::fixup_after_exec ()
1455 if (!close_on_exec ())
1456 fixup_after_fork (NULL);
1459 extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
1461 /* This thread function handles the master control pipe. It waits for a
1462 client to connect. Then it checks if the client process has permissions
1463 to access the tty handles. If so, it opens the client process and
1464 duplicates the handles into that process. If that fails, it sends a reply
1465 with at least one handle set to NULL and an error code. Last but not
1466 least, the client is disconnected and the thread waits for the next client.
1468 A special case is when the master side of the tty is about to be closed.
1469 The client side is the fhandler_pty_master::close function and it sends
1470 a PID -1 in that case. On Vista and later a check is performed that the
1471 request to leave really comes from the master process itself. On earlier
1472 OSes there's no function to check for the PID of the client process so
1473 we have to trust the client side.
1475 Since there's always only one pipe instance, there's a chance that clients
1476 have to wait to connect to the master control pipe. Therefore the client
1477 calls to CallNamedPipe should have a big enough timeout value. For now this
1478 is 500ms. Hope that's enough. */
1481 fhandler_pty_master::pty_master_thread ()
1484 GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
1485 EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
1488 security_descriptor sd;
1494 termios_printf ("Entered");
1495 while (!exit && (ConnectNamedPipe (master_ctl, NULL)
1496 || GetLastError () == ERROR_PIPE_CONNECTED))
1498 pipe_reply repl = { NULL, NULL, 0 };
1500 NTSTATUS allow = STATUS_ACCESS_DENIED;
1501 ACCESS_MASK access = EVENT_MODIFY_STATE;
1502 HANDLE client = NULL;
1504 if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
1506 termios_printf ("ReadFile, %E");
1509 /* This function is only available since Vista, unfortunately.
1510 In earlier OSes we simply have to believe that the client
1511 has no malicious intent (== sends arbitrary PIDs). */
1512 if (!GetNamedPipeClientProcessId (master_ctl, &pid))
1514 if (get_object_sd (input_available_event, sd))
1516 termios_printf ("get_object_sd, %E");
1519 cygheap->user.deimpersonate ();
1521 if (!ImpersonateNamedPipeClient (master_ctl))
1523 termios_printf ("ImpersonateNamedPipeClient, %E");
1526 status = NtOpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE,
1528 if (!NT_SUCCESS (status))
1530 termios_printf ("NtOpenThreadToken, %p", status);
1531 SetLastError (RtlNtStatusToDosError (status));
1535 status = NtAccessCheck (sd, token, access, &map, &ps, &len, &access,
1538 if (!NT_SUCCESS (status))
1540 termios_printf ("NtAccessCheck, %p", status);
1541 SetLastError (RtlNtStatusToDosError (status));
1544 if (!RevertToSelf ())
1546 termios_printf ("RevertToSelf, %E");
1549 if (req.pid == (DWORD) -1) /* Request to finish thread. */
1551 /* Pre-Vista: Just believe in the good of the client process.
1552 Post-Vista: Check if the requesting process is the master
1554 if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
1558 if (NT_SUCCESS (allow))
1560 client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
1563 termios_printf ("OpenProcess, %E");
1566 if (!DuplicateHandle (GetCurrentProcess (), from_master,
1567 client, &repl.from_master,
1568 0, TRUE, DUPLICATE_SAME_ACCESS))
1570 termios_printf ("DuplicateHandle (from_master), %E");
1573 if (!DuplicateHandle (GetCurrentProcess (), to_master,
1574 client, &repl.to_master,
1575 0, TRUE, DUPLICATE_SAME_ACCESS))
1577 termios_printf ("DuplicateHandle (to_master), %E");
1582 repl.error = GetLastError ();
1584 CloseHandle (client);
1586 cygheap->user.reimpersonate ();
1588 termios_printf ("Reply: from %p, to %p, error %lu",
1589 repl.from_master, repl.to_master, repl.error );
1590 if (!WriteFile (master_ctl, &repl, sizeof repl, &len, NULL))
1591 termios_printf ("WriteFile, %E");
1592 if (!DisconnectNamedPipe (master_ctl))
1593 termios_printf ("DisconnectNamedPipe, %E");
1595 termios_printf ("Leaving");
1600 pty_master_thread (VOID *arg)
1602 return ((fhandler_pty_master *) arg)->pty_master_thread ();
1606 fhandler_pty_master::setup ()
1609 security_descriptor sd;
1610 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
1612 /* Find an unallocated pty to use. */
1613 int unit = cygwin_shared->tty.allocate (from_master, get_output_handle ());
1617 ProtectHandle1 (get_output_handle (), to_pty);
1619 tty& t = *cygwin_shared->tty[unit];
1620 _tc = (tty_min *) &t;
1622 tcinit (true); /* Set termios information. Force initialization. */
1624 const char *errstr = NULL;
1625 DWORD pipe_mode = PIPE_NOWAIT;
1627 if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
1628 termios_printf ("can't set output_handle(%p) to non-blocking mode",
1629 get_output_handle ());
1631 char pipename[sizeof("ptyNNNN-from-master")];
1632 __small_sprintf (pipename, "pty%d-to-master", unit);
1633 res = fhandler_pipe::create (&sec_none, &get_io_handle (), &to_master,
1634 fhandler_pty_common::pipesize, pipename, 0);
1637 errstr = "output pipe";
1641 ProtectHandle1 (get_io_handle (), from_pty);
1643 /* Create security attribute. Default permissions are 0620. */
1644 sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1645 RtlCreateSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1646 if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
1647 S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
1649 sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
1651 /* Carefully check that the input_available_event didn't already exist.
1652 This is a measure to make sure that the event security descriptor
1653 isn't occupied by a malicious process. We must make sure that the
1654 event's security descriptor is what we expect it to be. */
1655 if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT,
1657 || GetLastError () == ERROR_ALREADY_EXISTS)
1661 errstr = shared_name (buf, OUTPUT_MUTEX, unit);
1662 if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
1665 errstr = shared_name (buf, INPUT_MUTEX, unit);
1666 if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
1669 /* Create master control pipe which allows the master to duplicate
1670 the pty pipe handles to processes which deserve it. */
1671 __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
1672 &installation_key, unit);
1673 master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX,
1674 PIPE_WAIT | PIPE_TYPE_MESSAGE
1675 | PIPE_READMODE_MESSAGE, 1, 4096, 4096,
1677 if (master_ctl == INVALID_HANDLE_VALUE)
1679 errstr = "pty master control pipe";
1682 master_thread = new cygthread (::pty_master_thread, this, "pty_master");
1685 errstr = "pty master control thread";
1689 t.from_master = from_master;
1690 t.to_master = to_master;
1691 t.winsize.ws_col = 80;
1692 t.winsize.ws_row = 25;
1693 t.master_pid = myself->pid;
1695 dev ().parse (DEV_PTYM_MAJOR, unit);
1697 termios_printf ("this %p, pty%d opened - from_pty %p, to_pty %p", this, unit,
1698 get_io_handle (), get_output_handle ());
1703 close_maybe (get_io_handle ());
1704 close_maybe (get_output_handle ());
1705 close_maybe (input_available_event);
1706 close_maybe (output_mutex);
1707 close_maybe (input_mutex);
1708 close_maybe (from_master);
1709 close_maybe (to_master);
1710 close_maybe (master_ctl);
1711 termios_printf ("pty%d open failed - failed to create %s", unit, errstr);
1716 fhandler_pty_master::fixup_after_fork (HANDLE parent)
1718 DWORD wpid = GetCurrentProcessId ();
1719 fhandler_pty_master *arch = (fhandler_pty_master *) archetype;
1720 if (arch->dwProcessId != wpid)
1722 tty& t = *get_ttyp ();
1723 if (myself->pid == t.master_pid)
1725 t.from_master = arch->from_master;
1726 t.to_master = arch->to_master;
1728 arch->dwProcessId = wpid;
1730 from_master = arch->from_master;
1731 to_master = arch->to_master;
1732 report_tty_counts (this, "inherited master", "");
1736 fhandler_pty_master::fixup_after_exec ()
1738 if (!close_on_exec ())
1739 fixup_after_fork (spawn_info->parent);
1741 from_master = to_master = NULL;