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 ()], false);
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
);
714 if (ret
&& !cygwin_finished_initializing
&& !being_debugged ())
716 /* This only occurs when called from dtable::init_std_file_from_handle
717 We have been started from a non-Cygwin process. So we should become
718 tty process group leader.
719 TODO: Investigate how SIGTTIN should be handled with pure-windows
721 pinfo
p (tc
->getpgid ());
722 /* We should only grab this when the process group owner for this
723 tty is a non-cygwin process or we've been started directly
724 from a non-Cygwin process with no Cygwin ancestry. */
725 if (!p
|| ISSTATE (p
, PID_NOTCYGWIN
))
727 termios_printf ("Setting process group leader to %d since %W(%d) is not a cygwin process",
728 myself
->pgid
, p
->progname
, p
->pid
);
729 tc
->setpgid (myself
->pgid
);
733 if (f
!= INVALID_HANDLE_VALUE
)
734 CloseHandle (f
); /* Reopened by open */
740 fhandler_tty_slave::write (const void *ptr
, size_t len
)
742 DWORD n
, towrite
= len
;
744 termios_printf ("tty%d, write(%x, %d)", get_unit (), ptr
, len
);
746 acquire_output_mutex (INFINITE
);
750 n
= min (OUT_BUFFER_SIZE
, len
);
751 char *buf
= (char *)ptr
;
752 ptr
= (char *) ptr
+ n
;
755 /* Previous write may have set write_error to != 0. Check it here.
756 This is less than optimal, but the alternative slows down tty
757 writes enormously. */
758 if (get_ttyp ()->write_error
)
760 set_errno (get_ttyp ()->write_error
);
761 towrite
= (DWORD
) -1;
765 if (WriteFile (get_output_handle (), buf
, n
, &n
, NULL
) == FALSE
)
767 DWORD err
= GetLastError ();
768 termios_printf ("WriteFile failed, %E");
772 err
= ERROR_IO_DEVICE
;
774 __seterrno_from_win_error (err
);
776 raise (SIGHUP
); /* FIXME: Should this be SIGTTOU? */
777 towrite
= (DWORD
) -1;
781 if (output_done_event
!= NULL
)
785 rc
= WaitForSingleObject (output_done_event
, x
);
786 termios_printf ("waited %d ms for output_done_event, WFSO %d", x
, rc
);
789 release_output_mutex ();
794 fhandler_tty_slave::read (void *ptr
, size_t& len
)
798 int vtime
= 0; /* Initialized to prevent -Wuninitialized warning */
801 char buf
[INP_BUFFER_SIZE
];
802 char peek_buf
[INP_BUFFER_SIZE
];
807 termios_printf ("read(%x, %d) handle %p", ptr
, len
, get_handle ());
809 if (!ptr
) /* Indicating tcflush(). */
811 else if ((get_ttyp ()->ti
.c_lflag
& ICANON
))
812 time_to_wait
= INFINITE
;
815 vmin
= get_ttyp ()->ti
.c_cc
[VMIN
];
816 if (vmin
> INP_BUFFER_SIZE
)
817 vmin
= INP_BUFFER_SIZE
;
818 vtime
= get_ttyp ()->ti
.c_cc
[VTIME
];
826 time_to_wait
= !vtime
? INFINITE
: 100 * vtime
;
829 w4
[0] = signal_arrived
;
830 w4
[1] = input_available_event
;
832 DWORD waiter
= time_to_wait
;
835 rc
= WaitForMultipleObjects (2, w4
, FALSE
, waiter
);
837 if (rc
== WAIT_TIMEOUT
)
839 termios_printf ("wait timed out, waiter %u", waiter
);
843 if (rc
== WAIT_FAILED
)
845 termios_printf ("wait for input event failed, %E");
849 if (rc
== WAIT_OBJECT_0
)
851 /* if we've received signal after successfully reading some data,
852 just return all data successfully read */
855 set_sig_errno (EINTR
);
860 rc
= WaitForSingleObject (input_mutex
, 1000);
861 if (rc
== WAIT_FAILED
)
863 termios_printf ("wait for input mutex failed, %E");
866 else if (rc
== WAIT_TIMEOUT
)
868 termios_printf ("failed to acquire input mutex after input event arrived");
871 if (!PeekNamedPipe (get_handle (), peek_buf
, sizeof (peek_buf
), &bytes_in_pipe
, NULL
, NULL
))
873 termios_printf ("PeekNamedPipe failed, %E");
878 /* On first peek determine no. of bytes to flush. */
879 if (!ptr
&& len
== UINT_MAX
)
880 len
= (size_t) bytes_in_pipe
;
882 if (ptr
&& !bytes_in_pipe
&& !vmin
&& !time_to_wait
)
884 ReleaseMutex (input_mutex
);
885 len
= (size_t) bytes_in_pipe
;
889 readlen
= min (bytes_in_pipe
, min (len
, sizeof (buf
)));
891 if (ptr
&& vmin
&& readlen
> (unsigned) vmin
)
897 termios_printf ("reading %d bytes (vtime %d)", readlen
, vtime
);
898 if (ReadFile (get_handle (), buf
, readlen
, &n
, NULL
) == FALSE
)
900 termios_printf ("read failed, %E");
903 /* MSDN states that 5th prameter can be used to determine total
904 number of bytes in pipe, but for some reason this number doesn't
905 change after successful read. So we have to peek into the pipe
906 again to see if input is still available */
907 if (!PeekNamedPipe (get_handle (), peek_buf
, 1, &bytes_in_pipe
, NULL
, NULL
))
909 termios_printf ("PeekNamedPipe failed, %E");
919 memcpy (ptr
, buf
, n
);
920 ptr
= (char *) ptr
+ n
;
926 ResetEvent (input_available_event
);
928 ReleaseMutex (input_mutex
);
937 if (get_ttyp ()->read_retval
< 0) // read error
939 set_errno (-get_ttyp ()->read_retval
);
943 if (get_ttyp ()->read_retval
== 0) //EOF
945 termios_printf ("saw EOF");
948 if (get_ttyp ()->ti
.c_lflag
& ICANON
|| is_nonblocking ())
950 if (vmin
&& totalread
>= vmin
)
953 /* vmin == 0 && vtime == 0:
954 * we've already read all input, if any, so return immediately
955 * vmin == 0 && vtime > 0:
956 * we've waited for input 10*vtime ms in WFSO(input_available_event),
957 * no matter whether any input arrived, we shouldn't wait any longer,
958 * so return immediately
959 * vmin > 0 && vtime == 0:
960 * here, totalread < vmin, so continue waiting until more data
962 * vmin > 0 && vtime > 0:
963 * similar to the previous here, totalread < vmin, and timer
964 * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
965 * so "restart timer" and wait until more data arrive
972 waiter
= time_to_wait
;
974 termios_printf ("%d=read(%x, %d)", totalread
, ptr
, len
);
975 len
= (size_t) totalread
;
979 fhandler_tty_slave::dup (fhandler_base
*child
)
981 fhandler_tty_slave
*arch
= (fhandler_tty_slave
*) archetype
;
982 *(fhandler_tty_slave
*) child
= *arch
;
983 child
->set_flags (get_flags ());
986 cygheap
->manage_console_count ("fhandler_tty_slave::dup", 1);
987 report_tty_counts (child
, "duped", "");
992 fhandler_pty_master::dup (fhandler_base
*child
)
994 fhandler_tty_master
*arch
= (fhandler_tty_master
*) archetype
;
995 *(fhandler_tty_master
*) child
= *arch
;
996 child
->set_flags (get_flags ());
999 report_tty_counts (child
, "duped master", "");
1004 fhandler_tty_slave::tcgetattr (struct termios
*t
)
1006 *t
= get_ttyp ()->ti
;
1011 fhandler_tty_slave::tcsetattr (int, const struct termios
*t
)
1013 acquire_output_mutex (INFINITE
);
1014 get_ttyp ()->ti
= *t
;
1015 release_output_mutex ();
1020 fhandler_tty_slave::tcflush (int queue
)
1024 termios_printf ("tcflush(%d) handle %p", queue
, get_handle ());
1026 if (queue
== TCIFLUSH
|| queue
== TCIOFLUSH
)
1028 size_t len
= UINT_MAX
;
1030 ret
= ((int) len
) >= 0 ? 0 : -1;
1032 if (queue
== TCOFLUSH
|| queue
== TCIOFLUSH
)
1034 /* do nothing for now. */
1037 termios_printf ("%d=tcflush(%d)", ret
, queue
);
1042 fhandler_tty_slave::ioctl (unsigned int cmd
, void *arg
)
1044 termios_printf ("ioctl (%x)", cmd
);
1046 if (myself
->pgid
&& get_ttyp ()->getpgid () != myself
->pgid
1047 && myself
->ctty
== get_unit () && (get_ttyp ()->ti
.c_lflag
& TOSTOP
))
1049 /* background process */
1050 termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself
->pgid
,
1051 get_ttyp ()->getpgid (), myctty ());
1065 set_nonblocking (*(int *) arg
);
1070 pid_t pid
= this->tcgetpgrp ();
1075 *((pid_t
*) arg
) = pid
;
1081 retval
= this->tcsetpgrp ((pid_t
) arg
);
1088 acquire_output_mutex (INFINITE
);
1090 get_ttyp ()->cmd
= cmd
;
1091 get_ttyp ()->ioctl_retval
= 0;
1096 get_ttyp ()->arg
.winsize
= get_ttyp ()->winsize
;
1097 if (ioctl_request_event
)
1098 SetEvent (ioctl_request_event
);
1099 *(struct winsize
*) arg
= get_ttyp ()->arg
.winsize
;
1100 if (ioctl_done_event
)
1101 WaitForSingleObject (ioctl_done_event
, INFINITE
);
1102 get_ttyp ()->winsize
= get_ttyp ()->arg
.winsize
;
1105 if (get_ttyp ()->winsize
.ws_row
!= ((struct winsize
*) arg
)->ws_row
1106 || get_ttyp ()->winsize
.ws_col
!= ((struct winsize
*) arg
)->ws_col
)
1108 get_ttyp ()->arg
.winsize
= *(struct winsize
*) arg
;
1109 if (ioctl_request_event
)
1111 get_ttyp ()->ioctl_retval
= -EINVAL
;
1112 SetEvent (ioctl_request_event
);
1116 get_ttyp ()->winsize
= *(struct winsize
*) arg
;
1117 killsys (-get_ttyp ()->getpgid (), SIGWINCH
);
1119 if (ioctl_done_event
)
1120 WaitForSingleObject (ioctl_done_event
, INFINITE
);
1124 val
= *(unsigned char *) arg
;
1125 if (val
!= 6 || !ioctl_request_event
|| !ioctl_done_event
)
1126 get_ttyp ()->ioctl_retval
= -EINVAL
;
1129 get_ttyp ()->arg
.value
= val
;
1130 SetEvent (ioctl_request_event
);
1131 WaitForSingleObject (ioctl_done_event
, INFINITE
);
1132 *(unsigned char *) arg
= (unsigned char) (get_ttyp ()->arg
.value
);
1136 if (ioctl_request_event
)
1138 SetEvent (ioctl_request_event
);
1139 if (ioctl_done_event
)
1140 WaitForSingleObject (ioctl_done_event
, INFINITE
);
1141 *(int *) arg
= get_ttyp ()->arg
.value
;
1144 get_ttyp ()->ioctl_retval
= -EINVAL
;
1147 if (ioctl_request_event
)
1149 get_ttyp ()->arg
.value
= (int) arg
;
1150 SetEvent (ioctl_request_event
);
1151 if (ioctl_done_event
)
1152 WaitForSingleObject (ioctl_done_event
, INFINITE
);
1155 get_ttyp ()->ioctl_retval
= -EINVAL
;
1159 release_output_mutex ();
1160 retval
= get_ttyp ()->ioctl_retval
;
1163 set_errno (-retval
);
1168 termios_printf ("%d = ioctl (%x)", retval
, cmd
);
1173 fhandler_tty_slave::fstat (struct __stat64
*st
)
1175 fhandler_base::fstat (st
);
1177 bool to_close
= false;
1178 if (!input_available_event
)
1181 shared_name (buf
, INPUT_AVAILABLE_EVENT
, get_unit ());
1182 input_available_event
= OpenEvent (READ_CONTROL
, TRUE
, buf
);
1183 if (input_available_event
)
1186 if (!input_available_event
1187 || get_object_attribute (input_available_event
, &st
->st_uid
, &st
->st_gid
,
1190 /* If we can't access the ACL, or if the tty doesn't actually exist,
1191 then fake uid and gid to strict, system-like values. */
1192 st
->st_mode
= S_IFCHR
| S_IRUSR
| S_IWUSR
;
1197 CloseHandle (input_available_event
);
1201 /* Helper function for fchmod and fchown, which just opens all handles
1202 and signals success via bool return. */
1204 fhandler_tty_slave::fch_open_handles ()
1208 tc
= cygwin_shared
->tty
[get_unit ()];
1209 shared_name (buf
, INPUT_AVAILABLE_EVENT
, get_unit ());
1210 input_available_event
= OpenEvent (READ_CONTROL
| WRITE_DAC
| WRITE_OWNER
,
1212 output_mutex
= get_ttyp ()->open_output_mutex (WRITE_DAC
| WRITE_OWNER
);
1213 input_mutex
= get_ttyp ()->open_input_mutex (WRITE_DAC
| WRITE_OWNER
);
1214 inuse
= get_ttyp ()->open_inuse (WRITE_DAC
| WRITE_OWNER
);
1215 if (!input_available_event
|| !output_mutex
|| !input_mutex
|| !inuse
)
1220 /* These members are optional, no error checking */
1221 shared_name (buf
, OUTPUT_DONE_EVENT
, get_unit ());
1222 output_done_event
= OpenEvent (WRITE_DAC
| WRITE_OWNER
, TRUE
, buf
);
1223 shared_name (buf
, IOCTL_REQUEST_EVENT
, get_unit ());
1224 ioctl_request_event
= OpenEvent (WRITE_DAC
| WRITE_OWNER
, TRUE
, buf
);
1225 shared_name (buf
, IOCTL_DONE_EVENT
, get_unit ());
1226 ioctl_done_event
= OpenEvent (WRITE_DAC
| WRITE_OWNER
, TRUE
, buf
);
1230 /* Helper function for fchmod and fchown, which sets the new security
1231 descriptor on all objects representing the tty. */
1233 fhandler_tty_slave::fch_set_sd (security_descriptor
&sd
, bool chown
)
1235 security_descriptor sd_old
;
1237 get_object_sd (input_available_event
, sd_old
);
1238 if (!set_object_sd (input_available_event
, sd
, chown
)
1239 && !set_object_sd (output_mutex
, sd
, chown
)
1240 && !set_object_sd (input_mutex
, sd
, chown
)
1241 && !set_object_sd (inuse
, sd
, chown
)
1242 && (!output_done_event
1243 || !set_object_sd (output_done_event
, sd
, chown
))
1244 && (!ioctl_request_event
1245 || !set_object_sd (ioctl_request_event
, sd
, chown
))
1246 && (!ioctl_done_event
1247 || !set_object_sd (ioctl_done_event
, sd
, chown
)))
1249 set_object_sd (input_available_event
, sd_old
, chown
);
1250 set_object_sd (output_mutex
, sd_old
, chown
);
1251 set_object_sd (input_mutex
, sd_old
, chown
);
1252 set_object_sd (inuse
, sd_old
, chown
);
1253 if (!output_done_event
)
1254 set_object_sd (output_done_event
, sd_old
, chown
);
1255 if (!ioctl_request_event
)
1256 set_object_sd (ioctl_request_event
, sd_old
, chown
);
1257 if (!ioctl_done_event
)
1258 set_object_sd (ioctl_done_event
, sd_old
, chown
);
1262 /* Helper function for fchmod and fchown, which closes all object handles in
1265 fhandler_tty_slave::fch_close_handles ()
1267 close_maybe (get_io_handle ());
1268 close_maybe (get_output_handle ());
1269 close_maybe (output_done_event
);
1270 close_maybe (ioctl_done_event
);
1271 close_maybe (ioctl_request_event
);
1272 close_maybe (input_available_event
);
1273 close_maybe (output_mutex
);
1274 close_maybe (input_mutex
);
1275 close_maybe (inuse
);
1279 fhandler_tty_slave::fchmod (mode_t mode
)
1282 bool to_close
= false;
1283 security_descriptor sd
;
1287 if (!input_available_event
)
1290 if (!fch_open_handles ())
1293 sd
.malloc (sizeof (SECURITY_DESCRIPTOR
));
1294 InitializeSecurityDescriptor (sd
, SECURITY_DESCRIPTOR_REVISION
);
1295 if (!get_object_attribute (input_available_event
, &uid
, &gid
, NULL
)
1296 && !create_object_sd_from_attribute (NULL
, uid
, gid
, S_IFCHR
| mode
, sd
))
1297 ret
= fch_set_sd (sd
, false);
1300 fch_close_handles ();
1305 fhandler_tty_slave::fchown (__uid32_t uid
, __gid32_t gid
)
1308 bool to_close
= false;
1312 security_descriptor sd
;
1314 if (uid
== ILLEGAL_UID
&& gid
== ILLEGAL_GID
)
1316 if (!input_available_event
)
1319 if (!fch_open_handles ())
1322 sd
.malloc (sizeof (SECURITY_DESCRIPTOR
));
1323 InitializeSecurityDescriptor (sd
, SECURITY_DESCRIPTOR_REVISION
);
1324 if (!get_object_attribute (input_available_event
, &o_uid
, &o_gid
, &mode
))
1326 if ((uid
== ILLEGAL_UID
|| uid
== o_uid
)
1327 && (gid
== ILLEGAL_GID
|| gid
== o_gid
))
1329 else if (!create_object_sd_from_attribute (input_available_event
,
1330 uid
, gid
, S_IFCHR
| mode
, sd
))
1331 ret
= fch_set_sd (sd
, true);
1335 fch_close_handles ();
1339 /*******************************************************
1342 fhandler_pty_master::fhandler_pty_master ()
1343 : fhandler_tty_common (), pktmode (0), need_nl (0), dwProcessId (0)
1348 fhandler_pty_master::open (int flags
, mode_t
)
1351 ntty
= cygwin_shared
->tty
.allocate (false);
1355 dev().devn
= FHDEV (DEV_TTYM_MAJOR
, ntty
);
1358 lock_ttys::release ();
1361 lock_ttys::release ();
1362 set_flags ((flags
& ~O_TEXT
) | O_BINARY
);
1365 // FIXME: Do this better someday
1366 fhandler_pty_master
*arch
= (fhandler_tty_master
*) cmalloc_abort (HEAP_ARCHETYPES
, sizeof (*this));
1367 *((fhandler_pty_master
**) cygheap
->fdtab
.add_archetype ()) = arch
;
1370 arch
->dwProcessId
= GetCurrentProcessId ();
1374 char buf
[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
1375 __small_sprintf (buf
, "opened pty master for tty%d", get_unit ());
1376 report_tty_counts (this, buf
, "");
1381 fhandler_tty_common::lseek (_off64_t
, int)
1388 fhandler_tty_common::close ()
1390 termios_printf ("tty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1391 if (output_done_event
&& !CloseHandle (output_done_event
))
1392 termios_printf ("CloseHandle (output_done_event), %E");
1393 if (ioctl_done_event
&& !CloseHandle (ioctl_done_event
))
1394 termios_printf ("CloseHandle (ioctl_done_event), %E");
1395 if (ioctl_request_event
&& !CloseHandle (ioctl_request_event
))
1396 termios_printf ("CloseHandle (ioctl_request_event), %E");
1397 if (!ForceCloseHandle (input_mutex
))
1398 termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex
);
1399 if (!ForceCloseHandle (output_mutex
))
1400 termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex
);
1401 if (!ForceCloseHandle1 (get_handle (), from_pty
))
1402 termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1403 if (!ForceCloseHandle1 (get_output_handle (), to_pty
))
1404 termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
1406 if (!ForceCloseHandle (input_available_event
))
1407 termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event
);
1413 fhandler_pty_master::close ()
1416 while (accept_input () > 0)
1419 archetype
->usecount
--;
1420 report_tty_counts (this, "closing master", "");
1422 if (archetype
->usecount
)
1425 if (archetype
->usecount
< 0)
1426 system_printf ("error: usecount %d", archetype
->usecount
);
1428 termios_printf ("just returning because archetype usecount is != 0");
1432 fhandler_tty_master
*arch
= (fhandler_tty_master
*) archetype
;
1433 termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1434 arch
->from_master
, arch
->to_master
, arch
->dwProcessId
);
1435 if (cygwin_finished_initializing
)
1437 if (arch
->master_ctl
&& get_ttyp ()->master_pid
== myself
->pid
)
1440 pipe_request req
= { (DWORD
) -1 };
1444 __small_sprintf (buf
, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1445 &installation_key
, get_unit ());
1446 CallNamedPipe (buf
, &req
, sizeof req
, &repl
, sizeof repl
, &len
, 500);
1447 CloseHandle (arch
->master_ctl
);
1448 arch
->master_thread
->detach ();
1450 if (!ForceCloseHandle (arch
->from_master
))
1451 termios_printf ("error closing from_master %p, %E", arch
->from_master
);
1452 if (!ForceCloseHandle (arch
->to_master
))
1453 termios_printf ("error closing from_master %p, %E", arch
->to_master
);
1455 fhandler_tty_common::close ();
1457 if (hExeced
|| get_ttyp ()->master_pid
!= myself
->pid
)
1458 termios_printf ("not clearing: %d, master_pid %d", hExeced
, get_ttyp ()->master_pid
);
1460 get_ttyp ()->set_master_closed ();
1466 fhandler_pty_master::write (const void *ptr
, size_t len
)
1469 char *p
= (char *) ptr
;
1470 termios ti
= tc
->ti
;
1472 for (i
= 0; i
< (int) len
; i
++)
1474 line_edit_status status
= line_edit (p
++, 1, ti
);
1475 if (status
> line_edit_signalled
)
1477 if (status
!= line_edit_pipe_full
)
1486 fhandler_pty_master::read (void *ptr
, size_t& len
)
1488 len
= (size_t) process_slave_output ((char *) ptr
, len
, pktmode
);
1492 fhandler_pty_master::tcgetattr (struct termios
*t
)
1494 *t
= cygwin_shared
->tty
[get_unit ()]->ti
;
1499 fhandler_pty_master::tcsetattr (int, const struct termios
*t
)
1501 cygwin_shared
->tty
[get_unit ()]->ti
= *t
;
1506 fhandler_pty_master::tcflush (int queue
)
1510 termios_printf ("tcflush(%d) handle %p", queue
, get_handle ());
1512 if (queue
== TCIFLUSH
|| queue
== TCIOFLUSH
)
1513 ret
= process_slave_output (NULL
, OUT_BUFFER_SIZE
, 0);
1514 else if (queue
== TCIFLUSH
|| queue
== TCIOFLUSH
)
1516 /* do nothing for now. */
1519 termios_printf ("%d=tcflush(%d)", ret
, queue
);
1524 fhandler_pty_master::ioctl (unsigned int cmd
, void *arg
)
1529 pktmode
= *(int *) arg
;
1532 *(struct winsize
*) arg
= get_ttyp ()->winsize
;
1535 if (get_ttyp ()->winsize
.ws_row
!= ((struct winsize
*) arg
)->ws_row
1536 || get_ttyp ()->winsize
.ws_col
!= ((struct winsize
*) arg
)->ws_col
)
1538 get_ttyp ()->winsize
= *(struct winsize
*) arg
;
1539 killsys (-get_ttyp ()->getpgid (), SIGWINCH
);
1543 *((pid_t
*) arg
) = this->tcgetpgrp ();
1546 return this->tcsetpgrp ((pid_t
) arg
);
1548 set_nonblocking (*(int *) arg
);
1558 fhandler_pty_master::ptsname ()
1560 static char buf
[TTY_NAME_MAX
];
1562 __small_sprintf (buf
, "/dev/tty%d", get_unit ());
1567 fhandler_tty_common::set_close_on_exec (bool val
)
1569 // Cygwin processes will handle this specially on exec.
1570 close_on_exec (val
);
1574 fhandler_tty_slave::fixup_after_fork (HANDLE parent
)
1576 // fork_fixup (parent, inuse, "inuse");
1577 // fhandler_tty_common::fixup_after_fork (parent);
1578 report_tty_counts (this, "inherited", "");
1582 fhandler_tty_slave::fixup_after_exec ()
1584 if (!close_on_exec ())
1585 fixup_after_fork (NULL
);
1589 fhandler_tty_master::init_console ()
1591 console
= (fhandler_console
*) build_fh_dev (*console_dev
, "/dev/ttym");
1592 if (console
== NULL
)
1595 console
->init (INVALID_HANDLE_VALUE
, GENERIC_READ
| GENERIC_WRITE
, O_BINARY
);
1596 cygheap
->manage_console_count ("fhandler_tty_master::init_console", -1, true);
1597 console
->uninterruptible_io (true);
1601 extern "C" BOOL WINAPI
GetNamedPipeClientProcessId (HANDLE
, PULONG
);
1603 /* This thread function handles the master control pipe. It waits for a
1604 client to connect. Then it checks if the client process has permissions
1605 to access the tty handles. If so, it opens the client process and
1606 duplicates the handles into that process. If that fails, it sends a reply
1607 with at least one handle set to NULL and an error code. Last but not
1608 least, the client is disconnected and the thread waits for the next client.
1610 A special case is when the master side of the tty is about to be closed.
1611 The client side is the fhandler_pty_master::close function and it sends
1612 a PID -1 in that case. On Vista and later a check is performed that the
1613 request to leave really comes from the master process itself. On earlier
1614 OSes there's no function to check for the PID of the client process so
1615 we have to trust the client side.
1618 always only one pipe instance, there's a chance that clients have to
1619 wait to connect to the master control pipe. Therefore the client calls
1620 to CallNamedPipe should have a big enough timeout value. For now this
1621 is 500ms. Hope that's enough. */
1624 fhandler_pty_master::pty_master_thread ()
1627 GENERIC_MAPPING map
= { EVENT_QUERY_STATE
, EVENT_MODIFY_STATE
, 0,
1628 EVENT_QUERY_STATE
| EVENT_MODIFY_STATE
};
1631 security_descriptor sd
;
1637 termios_printf ("Entered");
1638 while (!exit
&& ConnectNamedPipe (master_ctl
, NULL
))
1640 pipe_reply repl
= { NULL
, NULL
, 0 };
1643 ACCESS_MASK access
= EVENT_MODIFY_STATE
;
1644 HANDLE client
= NULL
;
1646 if (!ReadFile (master_ctl
, &req
, sizeof req
, &len
, NULL
))
1648 termios_printf ("ReadFile, %E");
1651 /* This function is only available since Vista, unfortunately.
1652 In earlier OSes we simply have to believe that the client
1653 has no malicious intent (== sends arbitrary PIDs). */
1654 if (!GetNamedPipeClientProcessId (master_ctl
, &pid
))
1656 if (get_object_sd (input_available_event
, sd
))
1658 termios_printf ("get_object_sd, %E");
1661 cygheap
->user
.deimpersonate ();
1663 if (!ImpersonateNamedPipeClient (master_ctl
))
1665 termios_printf ("ImpersonateNamedPipeClient, %E");
1668 if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY
, TRUE
, &token
))
1670 termios_printf ("OpenThreadToken, %E");
1674 ret
= AccessCheck (sd
, token
, access
, &map
, &ps
, &len
, &access
, &allow
);
1675 CloseHandle (token
);
1678 termios_printf ("AccessCheck, %E");
1681 if (!RevertToSelf ())
1683 termios_printf ("RevertToSelf, %E");
1686 if (req
.pid
== (DWORD
) -1) /* Request to finish thread. */
1688 /* Pre-Vista: Just believe in the good of the client process.
1689 Post-Vista: Check if the requesting process is the master
1691 if (pid
== (DWORD
) -1 || pid
== GetCurrentProcessId ())
1697 client
= OpenProcess (PROCESS_DUP_HANDLE
, FALSE
, pid
);
1700 termios_printf ("OpenProcess, %E");
1703 if (!DuplicateHandle (GetCurrentProcess (), from_master
,
1704 client
, &repl
.from_master
,
1705 0, TRUE
, DUPLICATE_SAME_ACCESS
))
1707 termios_printf ("DuplicateHandle (from_master), %E");
1710 if (!DuplicateHandle (GetCurrentProcess (), to_master
,
1711 client
, &repl
.to_master
,
1712 0, TRUE
, DUPLICATE_SAME_ACCESS
))
1714 termios_printf ("DuplicateHandle (to_master), %E");
1719 repl
.error
= GetLastError ();
1721 CloseHandle (client
);
1723 cygheap
->user
.reimpersonate ();
1725 termios_printf ("Reply: from %p, to %p, error %lu",
1726 repl
.from_master
, repl
.to_master
, repl
.error
);
1727 if (!WriteFile (master_ctl
, &repl
, sizeof repl
, &len
, NULL
))
1728 termios_printf ("WriteFile, %E");
1729 if (!DisconnectNamedPipe (master_ctl
))
1730 termios_printf ("DisconnectNamedPipe, %E");
1732 termios_printf ("Leaving");
1737 pty_master_thread (VOID
*arg
)
1739 return ((fhandler_pty_master
*) arg
)->pty_master_thread ();
1743 fhandler_pty_master::setup (bool ispty
)
1746 security_descriptor sd
;
1747 SECURITY_ATTRIBUTES sa
= { sizeof (SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1749 tty
& t
= *cygwin_shared
->tty
[get_unit ()];
1751 tcinit (&t
, true); /* Set termios information. Force initialization. */
1753 const char *errstr
= NULL
;
1754 DWORD pipe_mode
= PIPE_NOWAIT
;
1756 /* Create communication pipes */
1757 char pipename
[sizeof("ttyNNNN-from-master")];
1758 __small_sprintf (pipename
, "tty%d-from-master", get_unit ());
1759 res
= fhandler_pipe::create_selectable (ispty
? &sec_none
: &sec_none_nih
,
1760 from_master
, get_output_handle (),
1761 128 * 1024, pipename
);
1764 errstr
= "input pipe";
1768 if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode
, NULL
, NULL
))
1769 termios_printf ("can't set output_handle(%p) to non-blocking mode",
1770 get_output_handle ());
1772 __small_sprintf (pipename
, "tty%d-to-master", get_unit ());
1773 res
= fhandler_pipe::create_selectable (ispty
? &sec_none
: &sec_none_nih
,
1774 get_io_handle (), to_master
,
1775 128 * 1024, pipename
);
1778 errstr
= "output pipe";
1784 /* Create security attribute. Default permissions are 0620. */
1785 sd
.malloc (sizeof (SECURITY_DESCRIPTOR
));
1786 InitializeSecurityDescriptor (sd
, SECURITY_DESCRIPTOR_REVISION
);
1787 if (!create_object_sd_from_attribute (NULL
, myself
->uid
, myself
->gid
,
1788 S_IFCHR
| S_IRUSR
| S_IWUSR
| S_IWGRP
,
1790 sa
.lpSecurityDescriptor
= (PSECURITY_DESCRIPTOR
) sd
;
1792 /* Create synchronisation events */
1796 if (!(output_done_event
= t
.get_event (errstr
= OUTPUT_DONE_EVENT
, &sa
)))
1798 if (!(ioctl_done_event
= t
.get_event (errstr
= IOCTL_DONE_EVENT
, &sa
)))
1800 if (!(ioctl_request_event
= t
.get_event (errstr
= IOCTL_REQUEST_EVENT
,
1805 /* Carefully check that the input_available_event didn't already exist.
1806 This is a measure to make sure that the event security descriptor
1807 isn't occupied by a malicious process. We must make sure that the
1808 event's security descriptor is what we expect it to be. */
1809 if (!(input_available_event
= t
.get_event (errstr
= INPUT_AVAILABLE_EVENT
,
1811 || GetLastError () == ERROR_ALREADY_EXISTS
)
1815 errstr
= shared_name (buf
, OUTPUT_MUTEX
, t
.ntty
);
1816 if (!(output_mutex
= CreateMutex (&sa
, FALSE
, buf
)))
1819 errstr
= shared_name (buf
, INPUT_MUTEX
, t
.ntty
);
1820 if (!(input_mutex
= CreateMutex (&sa
, FALSE
, buf
)))
1823 /* Create master control pipe which allows the master to duplicate
1824 the pty pipe handles to processes which deserve it. */
1825 __small_sprintf (buf
, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1826 &installation_key
, get_unit ());
1827 master_ctl
= CreateNamedPipe (buf
, PIPE_ACCESS_DUPLEX
,
1828 PIPE_WAIT
| PIPE_TYPE_MESSAGE
1829 | PIPE_READMODE_MESSAGE
, 1, 4096, 4096,
1831 if (master_ctl
== INVALID_HANDLE_VALUE
)
1833 errstr
= "pty master control pipe";
1836 master_thread
= new cygthread (::pty_master_thread
, this, "pty_master");
1839 errstr
= "pty master control thread";
1843 t
.from_master
= from_master
;
1844 t
.to_master
= to_master
;
1845 // /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
1846 // /* screws up tty master */ ProtectHandle1INH (input_mutex, input_mutex);
1847 t
.winsize
.ws_col
= 80;
1848 t
.winsize
.ws_row
= 25;
1849 t
.master_pid
= myself
->pid
;
1851 termios_printf ("tty%d opened - from_slave %p, to_slave %p", t
.ntty
,
1852 get_io_handle (), get_output_handle ());
1857 close_maybe (get_io_handle ());
1858 close_maybe (get_output_handle ());
1859 close_maybe (output_done_event
);
1860 close_maybe (ioctl_done_event
);
1861 close_maybe (ioctl_request_event
);
1862 close_maybe (input_available_event
);
1863 close_maybe (output_mutex
);
1864 close_maybe (input_mutex
);
1865 close_maybe (from_master
);
1866 close_maybe (to_master
);
1867 close_maybe (master_ctl
);
1868 termios_printf ("tty%d open failed - failed to create %s", errstr
);
1873 fhandler_pty_master::fixup_after_fork (HANDLE parent
)
1875 DWORD wpid
= GetCurrentProcessId ();
1876 fhandler_tty_master
*arch
= (fhandler_tty_master
*) archetype
;
1877 if (arch
->dwProcessId
!= wpid
)
1879 tty
& t
= *get_ttyp ();
1880 if (!DuplicateHandle (parent
, arch
->from_master
, GetCurrentProcess (),
1881 &arch
->from_master
, 0, false, DUPLICATE_SAME_ACCESS
))
1882 system_printf ("couldn't duplicate from_parent(%p), %E", arch
->from_master
);
1883 if (!DuplicateHandle (parent
, arch
->to_master
, GetCurrentProcess (),
1884 &arch
->to_master
, 0, false, DUPLICATE_SAME_ACCESS
))
1885 system_printf ("couldn't duplicate to_parent(%p), %E", arch
->from_master
);
1886 if (myself
->pid
== t
.master_pid
)
1888 t
.from_master
= arch
->from_master
;
1889 t
.to_master
= arch
->to_master
;
1891 arch
->dwProcessId
= wpid
;
1893 from_master
= arch
->from_master
;
1894 to_master
= arch
->to_master
;
1895 report_tty_counts (this, "inherited master", "");
1899 fhandler_pty_master::fixup_after_exec ()
1901 if (!close_on_exec ())
1902 fixup_after_fork (spawn_info
->parent
);
1904 from_master
= to_master
= NULL
;