OSDN Git Service

* path.cc (conv_path_list): Take cygwin_conv_path_t as third parameter.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler_tty.cc
1 /* fhandler_tty.cc
2
3    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4    2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <stdlib.h>
14 #include <cygwin/kd.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "path.h"
18 #include "fhandler.h"
19 #include "dtable.h"
20 #include "sigproc.h"
21 #include "pinfo.h"
22 #include "ntdll.h"
23 #include "cygheap.h"
24 #include "shared_info.h"
25 #include "cygthread.h"
26 #include "child_info.h"
27 #include <asm/socket.h>
28
29 #define close_maybe(h) \
30   do { \
31     if (h && h != INVALID_HANDLE_VALUE) \
32       CloseHandle (h); \
33   } while (0)
34
35 /* pty master control pipe messages */
36 struct pipe_request {
37   DWORD pid;
38 };
39
40 struct pipe_reply {
41   HANDLE from_master;
42   HANDLE to_master;
43   DWORD error;
44 };
45
46 int
47 fhandler_pty_slave::get_unit ()
48 {
49   return dev ().get_minor ();
50 }
51
52 #ifdef DEBUGGING
53 static class mutex_stack
54 {
55 public:
56   const char *fn;
57   int ln;
58   const char *tname;
59 } ostack[100];
60
61 static int osi;
62 #endif /*DEBUGGING*/
63
64 DWORD
65 fhandler_pty_common::__acquire_output_mutex (const char *fn, int ln,
66                                            DWORD ms)
67 {
68   if (strace.active ())
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)
72     {
73 #ifndef DEBUGGING
74       if (strace.active ())
75         strace.prntf (_STRACE_TERMIOS, fn, "(%d): pty output_mutex: acquired", ln, res);
76 #else
77       ostack[osi].fn = fn;
78       ostack[osi].ln = ln;
79       ostack[osi].tname = cygthread::name ();
80       termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
81       osi++;
82 #endif
83     }
84   return res;
85 }
86
87 void
88 fhandler_pty_common::__release_output_mutex (const char *fn, int ln)
89 {
90   if (ReleaseMutex (output_mutex))
91     {
92 #ifndef DEBUGGING
93       if (strace.active ())
94         strace.prntf (_STRACE_TERMIOS, fn, "(%d): pty output_mutex(%p) released", ln, output_mutex);
95 #else
96       if (osi > 0)
97         osi--;
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;
101 #endif
102     }
103 #ifdef DEBUGGING
104   else if (osi > 0)
105     {
106       system_printf ("couldn't release output mutex but we seem to own it, %E");
107       try_to_debug ();
108     }
109 #endif
110 }
111
112 /* Process pty input. */
113
114 void
115 fhandler_pty_master::doecho (const void *str, DWORD len)
116 {
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 ();
121 }
122
123 int
124 fhandler_pty_master::accept_input ()
125 {
126   DWORD bytes_left;
127   int ret = 1;
128
129   WaitForSingleObject (input_mutex, INFINITE);
130
131   bytes_left = eat_readahead (-1);
132
133   if (!bytes_left)
134     {
135       termios_printf ("sending EOF to slave");
136       get_ttyp ()->read_retval = 0;
137     }
138   else
139     {
140       char *p = rabuf;
141       DWORD rc;
142       DWORD written = 0;
143
144       termios_printf ("about to write %d chars to slave", bytes_left);
145       rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
146       if (!rc)
147         {
148           debug_printf ("error writing to pipe %p %E", get_output_handle ());
149           get_ttyp ()->read_retval = -1;
150           ret = -1;
151         }
152       else
153         {
154           get_ttyp ()->read_retval = 1;
155           p += written;
156           bytes_left -= written;
157           if (bytes_left > 0)
158             {
159               debug_printf ("to_slave pipe is full");
160               puts_readahead (p, bytes_left);
161               ret = 0;
162             }
163         }
164     }
165
166   SetEvent (input_available_event);
167   ReleaseMutex (input_mutex);
168   return ret;
169 }
170
171 bool
172 fhandler_pty_master::hit_eof ()
173 {
174   if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
175     {
176       /* We have the only remaining open handle to this pty, and
177          the slave pty has been opened at least once.  We treat
178          this as EOF.  */
179       termios_printf ("all other handles closed");
180       return 1;
181     }
182   return 0;
183 }
184
185 /* Process pty output requests */
186
187 int
188 fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
189 {
190   size_t rlen;
191   char outbuf[OUT_BUFFER_SIZE + 1];
192   DWORD n;
193   int column = 0;
194   int rc = 0;
195
196   if (len == 0)
197     goto out;
198
199   if (need_nl)
200     {
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.  */
205       if (buf)
206         buf[0] = '\n';
207       need_nl = 0;
208       rc = 1;
209       goto out;
210     }
211
212
213   for (;;)
214     {
215       /* Set RLEN to the number of bytes to read from the pipe.  */
216       rlen = len;
217       if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
218         {
219           /* We are going to expand \n to \r\n, so don't read more than
220              half of the number of bytes requested.  */
221           rlen /= 2;
222           if (rlen == 0)
223             rlen = 1;
224         }
225       if (rlen > sizeof outbuf)
226         rlen = sizeof outbuf;
227
228       HANDLE handle = get_io_handle ();
229
230       n = 0; // get_readahead_into_buffer (outbuf, len);
231       if (!n)
232         {
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.  */
236           while (1)
237             {
238               if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
239                 {
240                   termios_printf ("PeekNamedPipe(%p) failed, %E", handle);
241                   goto err;
242                 }
243               if (n > 0)
244                 break;
245               if (hit_eof ())
246                 goto out;
247               /* DISCARD (FLUSHO) and tcflush can finish here. */
248               if ((get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
249                 goto out;
250
251               if (is_nonblocking ())
252                 {
253                   set_errno (EAGAIN);
254                   rc = -1;
255                   goto out;
256                 }
257               pthread_testcancel ();
258               if (WaitForSingleObject (signal_arrived, 10) == WAIT_OBJECT_0
259                   && !_my_tls.call_signal_handler ())
260                 {
261                   set_errno (EINTR);
262                   rc = -1;
263                   goto out;
264                 }
265             }
266
267           if (!ReadFile (handle, outbuf, rlen, &n, NULL))
268             {
269               termios_printf ("ReadFile failed, %E");
270               goto err;
271             }
272         }
273
274       termios_printf ("bytes read %u", n);
275       get_ttyp ()->write_error = 0;
276
277       if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
278         continue;
279
280       char *optr;
281       optr = buf;
282       if (pktmode_on)
283         *optr++ = TIOCPKT_DATA;
284
285       if (!(get_ttyp ()->ti.c_oflag & OPOST))   // post-process output
286         {
287           memcpy (optr, outbuf, n);
288           optr += n;
289         }
290       else                                      // raw output mode
291         {
292           char *iptr = outbuf;
293
294           while (n--)
295             {
296               switch (*iptr)
297                 {
298                 case '\r':
299                   if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
300                     {
301                       iptr++;
302                       continue;
303                     }
304                   if (get_ttyp ()->ti.c_oflag & OCRNL)
305                     *iptr = '\n';
306                   else
307                     column = 0;
308                   break;
309                 case '\n':
310                   if (get_ttyp ()->ti.c_oflag & ONLCR)
311                     {
312                       *optr++ = '\r';
313                       column = 0;
314                     }
315                   if (get_ttyp ()->ti.c_oflag & ONLRET)
316                     column = 0;
317                   break;
318                 default:
319                   column++;
320                   break;
321                 }
322
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)
327                 {
328                   if (*iptr != '\n' || n != 0)
329                     system_printf ("internal error: %d unexpected characters", n);
330                   need_nl = 1;
331                   break;
332                 }
333
334               *optr++ = *iptr++;
335             }
336         }
337       rc = optr - buf;
338       break;
339
340     err:
341       if (GetLastError () == ERROR_BROKEN_PIPE)
342         rc = 0;
343       else
344         {
345           __seterrno ();
346           rc = -1;
347         }
348       break;
349     }
350
351 out:
352   termios_printf ("returning %d", rc);
353   return rc;
354 }
355
356 /* pty slave stuff */
357
358 fhandler_pty_slave::fhandler_pty_slave (int unit)
359   : fhandler_pty_common (), inuse (NULL)
360 {
361   if (unit >= 0)
362     dev ().parse (DEV_PTYS_MAJOR, unit);
363 }
364
365 int
366 fhandler_pty_slave::open (int flags, mode_t)
367 {
368   HANDLE pty_owner, from_master_local, to_master_local;
369   HANDLE *handles[] =
370   {
371     &from_master_local, &input_available_event, &input_mutex, &inuse,
372     &output_mutex, &to_master_local, &pty_owner,
373     NULL
374   };
375
376   for (HANDLE **h = handles; *h; h++)
377     **h = NULL;
378
379   _tc = cygwin_shared->tty[get_unit ()];
380
381   tcinit (false);
382
383   cygwin_shared->tty.attach (get_unit ());
384
385   /* Create synchronisation events */
386   char buf[MAX_PATH];
387
388   const char *errmsg = NULL;
389
390   if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
391     {
392       errmsg = "open output mutex failed, %E";
393       goto err;
394     }
395   if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
396     {
397       errmsg = "open input mutex failed, %E";
398       goto err;
399     }
400   shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
401   if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
402     {
403       errmsg = "open input event failed, %E";
404       goto err;
405     }
406
407   /* FIXME: Needs a method to eliminate tty races */
408   {
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,
416                                           sd))
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 ();
422   }
423
424   if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
425     {
426       errmsg = "pty handles have been closed";
427       set_errno (EACCES);
428       goto err_no_errno;
429     }
430
431   if (get_ttyp ()->master_pid < 0)
432     {
433       errmsg = "*** master is closed";
434       set_errno (EAGAIN);
435       goto err_no_errno;
436     }
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
444        get the handles. */
445   if (myself->pid == get_ttyp ()->master_pid)
446     {
447       /* This is the most common case, just calling openpty. */
448       termios_printf ("dup handles within myself.");
449       pty_owner = GetCurrentProcess ();
450     }
451   else
452     {
453       pinfo p (get_ttyp ()->master_pid);
454       if (!p)
455         termios_printf ("*** couldn't find pty master");
456       else
457         {
458           pty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
459           if (pty_owner)
460             termios_printf ("dup handles directly since I'm the owner");
461         }
462     }
463   if (pty_owner)
464     {
465       if (!DuplicateHandle (pty_owner, get_ttyp ()->from_master,
466                             GetCurrentProcess (), &from_master_local, 0, TRUE,
467                             DUPLICATE_SAME_ACCESS))
468         {
469           termios_printf ("can't duplicate input from %u/%p, %E",
470                           get_ttyp ()->master_pid, get_ttyp ()->from_master);
471           __seterrno ();
472           goto err_no_msg;
473         }
474       if (!DuplicateHandle (pty_owner, get_ttyp ()->to_master,
475                           GetCurrentProcess (), &to_master_local, 0, TRUE,
476                           DUPLICATE_SAME_ACCESS))
477         {
478           errmsg = "can't duplicate output, %E";
479           goto err;
480         }
481       if (pty_owner != GetCurrentProcess ())
482         CloseHandle (pty_owner);
483     }
484   else
485     {
486       pipe_request req = { GetCurrentProcessId () };
487       pipe_reply repl;
488       DWORD len;
489
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,
494                           &len, 500))
495         {
496           errmsg = "can't call master, %E";
497           goto err;
498         }
499       from_master_local = repl.from_master;
500       to_master_local = repl.to_master;
501       if (!from_master_local || !to_master_local)
502         {
503           SetLastError (repl.error);
504           errmsg = "error duplicating pipes, %E";
505           goto err;
506         }
507     }
508   VerifyHandle (from_master_local);
509   VerifyHandle (to_master_local);
510
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);
515
516   set_io_handle (from_master_local);
517   set_output_handle (to_master_local);
518
519   set_open_status ();
520   if (cygheap->manage_console_count ("fhandler_pty_slave::open", 1) == 1)
521     fhandler_console::need_invisible ();
522   return 1;
523
524 err:
525   if (GetLastError () == ERROR_FILE_NOT_FOUND)
526     set_errno (ENXIO);
527   else
528     __seterrno ();
529 err_no_errno:
530   termios_printf (errmsg);
531 err_no_msg:
532   for (HANDLE **h = handles; *h; h++)
533     if (**h && **h != INVALID_HANDLE_VALUE)
534       CloseHandle (**h);
535   return 0;
536 }
537
538 void
539 fhandler_pty_slave::open_setup (int flags)
540 {
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", "");
545 }
546
547 void
548 fhandler_pty_slave::cleanup ()
549 {
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", "");
557 }
558
559 int
560 fhandler_pty_slave::close ()
561 {
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 ();
566 }
567
568 int
569 fhandler_pty_slave::init (HANDLE h, DWORD a, mode_t)
570 {
571   int flags = 0;
572
573   a &= GENERIC_READ | GENERIC_WRITE;
574   if (a == GENERIC_READ)
575     flags = O_RDONLY;
576   if (a == GENERIC_WRITE)
577     flags = O_WRONLY;
578   if (a == (GENERIC_READ | GENERIC_WRITE))
579     flags = O_RDWR;
580
581   int ret = open_with_arch (flags);
582
583   if (ret && !cygwin_finished_initializing && !being_debugged ())
584     {
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
589          programs. */
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))
595         {
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);
599         }
600     }
601
602   if (h != INVALID_HANDLE_VALUE)
603     CloseHandle (h);    /* Reopened by open */
604
605   return ret;
606 }
607
608 ssize_t __stdcall
609 fhandler_pty_slave::write (const void *ptr, size_t len)
610 {
611   DWORD n, towrite = len;
612
613   bg_check_types bg = bg_check (SIGTTOU);
614   if (bg <= bg_eof)
615     return (ssize_t) bg;
616
617   termios_printf ("pty%d, write(%x, %d)", get_unit (), ptr, len);
618
619   push_process_state process_state (PID_TTYOU);
620
621   acquire_output_mutex (INFINITE);
622
623   while (len)
624     {
625       n = min (OUT_BUFFER_SIZE, len);
626       char *buf = (char *)ptr;
627       ptr = (char *) ptr + n;
628       len -= n;
629
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)
634         {
635           set_errno (get_ttyp ()->write_error);
636           towrite = (DWORD) -1;
637           break;
638         }
639
640       if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
641         {
642           DWORD err = GetLastError ();
643           termios_printf ("WriteFile failed, %E");
644           switch (err)
645             {
646             case ERROR_NO_DATA:
647               err = ERROR_IO_DEVICE;
648             default:
649               __seterrno_from_win_error (err);
650             }
651           raise (SIGHUP);               /* FIXME: Should this be SIGTTOU? */
652           towrite = (DWORD) -1;
653           break;
654         }
655     }
656   release_output_mutex ();
657   return towrite;
658 }
659
660 void __stdcall
661 fhandler_pty_slave::read (void *ptr, size_t& len)
662 {
663   int totalread = 0;
664   int vmin = 0;
665   int vtime = 0;        /* Initialized to prevent -Wuninitialized warning */
666   size_t readlen;
667   DWORD bytes_in_pipe;
668   char buf[INP_BUFFER_SIZE];
669   char peek_buf[INP_BUFFER_SIZE];
670   DWORD time_to_wait;
671
672   bg_check_types bg = bg_check (SIGTTIN);
673   if (bg <= bg_eof)
674     {
675       len = (size_t) bg;
676       return;
677     }
678
679   termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
680
681   push_process_state process_state (PID_TTYIN);
682
683   if (is_nonblocking () || !ptr) /* Indicating tcflush(). */
684     time_to_wait = 0;
685   else if ((get_ttyp ()->ti.c_lflag & ICANON))
686     time_to_wait = INFINITE;
687   else
688     {
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];
693       if (vmin < 0)
694         vmin = 0;
695       if (vtime < 0)
696         vtime = 0;
697       if (!vmin && !vtime)
698         time_to_wait = 0;
699       else
700         time_to_wait = !vtime ? INFINITE : 100 * vtime;
701     }
702
703   while (len)
704     {
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))
709         {
710         case WAIT_OBJECT_0:
711           break;
712         case WAIT_OBJECT_0 + 1:
713           if (totalread > 0)
714             goto out;
715           if (_my_tls.call_signal_handler ())
716             continue;
717           termios_printf ("wait catched signal");
718           set_sig_errno (EINTR);
719           totalread = -1;
720           goto out;
721         case WAIT_OBJECT_0 + 2:
722           process_state.pop ();
723           pthread::static_cancel_self ();
724           /*NOTREACHED*/
725         case WAIT_TIMEOUT:
726           termios_printf ("wait timed out, time_to_wait %u", time_to_wait);
727           if (!totalread)
728             {
729               set_sig_errno (EAGAIN);
730               totalread = -1;
731             }
732           goto out;
733         default:
734           termios_printf ("wait for input event failed, %E");
735           if (!totalread)
736             {
737               __seterrno ();
738               totalread = -1;
739             }
740           goto out;
741         }
742       /* Now that we know that input is available we have to grab the
743          input mutex. */
744       w4[0] = input_mutex;
745       switch (WaitForMultipleObjects (cnt, w4, FALSE, 1000))
746         {
747         case WAIT_OBJECT_0:
748         case WAIT_ABANDONED_0:
749           break;
750         case WAIT_OBJECT_0 + 1:
751           if (totalread > 0)
752             goto out;
753           if (_my_tls.call_signal_handler ())
754             continue;
755           termios_printf ("wait for mutex catched signal");
756           set_sig_errno (EINTR);
757           totalread = -1;
758           goto out;
759         case WAIT_OBJECT_0 + 2:
760           process_state.pop ();
761           pthread::static_cancel_self ();
762           /*NOTREACHED*/
763         case WAIT_TIMEOUT:
764           termios_printf ("failed to acquire input mutex after input event "
765                           "arrived");
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)
770             {
771               if (!totalread)
772                 {
773                   set_sig_errno (EAGAIN);
774                   totalread = -1;
775                 }
776               goto out;
777             }
778           continue;
779         default:
780           termios_printf ("wait for input mutex failed, %E");
781           if (!totalread)
782             {
783               __seterrno ();
784               totalread = -1;
785             }
786           goto out;
787         }
788       if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
789         {
790           termios_printf ("PeekNamedPipe failed, %E");
791           raise (SIGHUP);
792           bytes_in_pipe = 0;
793         }
794
795       /* On first peek determine no. of bytes to flush. */
796       if (!ptr && len == UINT_MAX)
797         len = (size_t) bytes_in_pipe;
798
799       if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
800         {
801           ReleaseMutex (input_mutex);
802           len = (size_t) bytes_in_pipe;
803           return;
804         }
805
806       readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
807
808       if (ptr && vmin && readlen > (unsigned) vmin)
809         readlen = vmin;
810
811       DWORD n = 0;
812       if (readlen)
813         {
814           termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
815           if (!ReadFile (get_handle (), buf, readlen, &n, NULL))
816             {
817               termios_printf ("read failed, %E");
818               raise (SIGHUP);
819             }
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))
825             {
826               termios_printf ("PeekNamedPipe failed, %E");
827               raise (SIGHUP);
828               bytes_in_pipe = 0;
829             }
830           if (n)
831             {
832               len -= n;
833               totalread += n;
834               if (ptr)
835                 {
836                   memcpy (ptr, buf, n);
837                   ptr = (char *) ptr + n;
838                 }
839             }
840         }
841
842       if (!bytes_in_pipe)
843         ResetEvent (input_available_event);
844
845       ReleaseMutex (input_mutex);
846
847       if (!ptr)
848         {
849           if (!bytes_in_pipe)
850             break;
851           continue;
852         }
853
854       if (get_ttyp ()->read_retval < 0) // read error
855         {
856           set_errno (-get_ttyp ()->read_retval);
857           totalread = -1;
858           break;
859         }
860       if (get_ttyp ()->read_retval == 0)        //EOF
861         {
862           termios_printf ("saw EOF");
863           break;
864         }
865       if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
866         break;
867       if (vmin && totalread >= vmin)
868         break;
869
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
878        *   arrive
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
883        */
884
885       if (vmin == 0)
886         break;
887     }
888 out:
889   termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
890   len = (size_t) totalread;
891 }
892
893 int
894 fhandler_pty_slave::dup (fhandler_base *child, int flags)
895 {
896   myself->set_ctty (this, flags);
897   cygheap->manage_console_count ("fhandler_pty_slave::dup", 1);
898   report_tty_counts (child, "duped slave", "");
899   return 0;
900 }
901
902 int
903 fhandler_pty_master::dup (fhandler_base *child, int)
904 {
905   report_tty_counts (child, "duped master", "");
906   return 0;
907 }
908
909 int
910 fhandler_pty_slave::tcgetattr (struct termios *t)
911 {
912   *t = get_ttyp ()->ti;
913   return 0;
914 }
915
916 int
917 fhandler_pty_slave::tcsetattr (int, const struct termios *t)
918 {
919   acquire_output_mutex (INFINITE);
920   get_ttyp ()->ti = *t;
921   release_output_mutex ();
922   return 0;
923 }
924
925 int
926 fhandler_pty_slave::tcflush (int queue)
927 {
928   int ret = 0;
929
930   termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
931
932   if (queue == TCIFLUSH || queue == TCIOFLUSH)
933     {
934       size_t len = UINT_MAX;
935       read (NULL, len);
936       ret = ((int) len) >= 0 ? 0 : -1;
937     }
938   if (queue == TCOFLUSH || queue == TCIOFLUSH)
939     {
940       /* do nothing for now. */
941     }
942
943   termios_printf ("%d=tcflush(%d)", ret, queue);
944   return ret;
945 }
946
947 int
948 fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
949 {
950   termios_printf ("ioctl (%x)", cmd);
951   int res = fhandler_termios::ioctl (cmd, arg);
952   if (res <= 0)
953     return res;
954
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))
958     {
959       /* background process */
960       termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
961                       get_ttyp ()->getpgid (), myctty ());
962       raise (SIGTTOU);
963     }
964
965   int retval;
966   switch (cmd)
967     {
968     case TIOCGWINSZ:
969     case TIOCSWINSZ:
970       break;
971     case TIOCGPGRP:
972       {
973         pid_t pid = this->tcgetpgrp ();
974         if (pid < 0)
975           retval = -1;
976         else
977           {
978             *((pid_t *) arg) = pid;
979             retval = 0;
980           }
981       }
982       goto out;
983     case TIOCSPGRP:
984       retval = this->tcsetpgrp ((pid_t) arg);
985       goto out;
986     case FIONREAD:
987       {
988         int n;
989         if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL))
990           {
991             set_errno (EINVAL);
992             retval = -1;
993           }
994         else
995           {
996             *(int *) arg = n;
997             retval = 0;
998           }
999       }
1000       goto out;
1001     default:
1002       return fhandler_base::ioctl (cmd, arg);
1003     }
1004
1005   acquire_output_mutex (INFINITE);
1006
1007   get_ttyp ()->cmd = cmd;
1008   get_ttyp ()->ioctl_retval = 0;
1009   switch (cmd)
1010     {
1011     case TIOCGWINSZ:
1012       get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1013       *(struct winsize *) arg = get_ttyp ()->arg.winsize;
1014       get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1015       break;
1016     case TIOCSWINSZ:
1017       if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1018           || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1019         {
1020           get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1021           get_ttyp ()->winsize = *(struct winsize *) arg;
1022           killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1023         }
1024       break;
1025     }
1026
1027   release_output_mutex ();
1028   retval = get_ttyp ()->ioctl_retval;
1029   if (retval < 0)
1030     {
1031       set_errno (-retval);
1032       retval = -1;
1033     }
1034
1035 out:
1036   termios_printf ("%d = ioctl (%x)", retval, cmd);
1037   return retval;
1038 }
1039
1040 int __stdcall
1041 fhandler_pty_slave::fstat (struct __stat64 *st)
1042 {
1043   fhandler_base::fstat (st);
1044
1045   bool to_close = false;
1046   if (!input_available_event)
1047     {
1048       char buf[MAX_PATH];
1049       shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1050       input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
1051       if (input_available_event)
1052         to_close = true;
1053     }
1054   if (!input_available_event
1055       || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
1056                                &st->st_mode))
1057     {
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;
1061       st->st_uid = 18;
1062       st->st_gid = 544;
1063     }
1064   if (to_close)
1065     CloseHandle (input_available_event);
1066   return 0;
1067 }
1068
1069 /* Helper function for fchmod and fchown, which just opens all handles
1070    and signals success via bool return. */
1071 bool
1072 fhandler_pty_slave::fch_open_handles ()
1073 {
1074   char buf[MAX_PATH];
1075
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,
1079                                      TRUE, buf);
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)
1084     {
1085       __seterrno ();
1086       return false;
1087     }
1088   return true;
1089 }
1090
1091 /* Helper function for fchmod and fchown, which sets the new security
1092    descriptor on all objects representing the pty. */
1093 int
1094 fhandler_pty_slave::fch_set_sd (security_descriptor &sd, bool chown)
1095 {
1096   security_descriptor sd_old;
1097
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))
1103     return 0;
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);
1108   return -1;
1109 }
1110
1111 /* Helper function for fchmod and fchown, which closes all object handles in
1112    the pty. */
1113 void
1114 fhandler_pty_slave::fch_close_handles ()
1115 {
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);
1122 }
1123
1124 int __stdcall
1125 fhandler_pty_slave::fchmod (mode_t mode)
1126 {
1127   int ret = -1;
1128   bool to_close = false;
1129   security_descriptor sd;
1130   __uid32_t uid;
1131   __gid32_t gid;
1132
1133   if (!input_available_event)
1134     {
1135       to_close = true;
1136       if (!fch_open_handles ())
1137         goto errout;
1138     }
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);
1144 errout:
1145   if (to_close)
1146     fch_close_handles ();
1147   return ret;
1148 }
1149
1150 int __stdcall
1151 fhandler_pty_slave::fchown (__uid32_t uid, __gid32_t gid)
1152 {
1153   int ret = -1;
1154   bool to_close = false;
1155   mode_t mode = 0;
1156   __uid32_t o_uid;
1157   __gid32_t o_gid;
1158   security_descriptor sd;
1159
1160   if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
1161     return 0;
1162   if (!input_available_event)
1163     {
1164       to_close = true;
1165       if (!fch_open_handles ())
1166         goto errout;
1167     }
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))
1171     {
1172       if ((uid == ILLEGAL_UID || uid == o_uid)
1173           && (gid == ILLEGAL_GID || gid == o_gid))
1174         ret = 0;
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);
1178     }
1179 errout:
1180   if (to_close)
1181     fch_close_handles ();
1182   return ret;
1183 }
1184
1185 /*******************************************************
1186  fhandler_pty_master
1187 */
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)
1192 {
1193   if (unit >= 0)
1194     dev ().parse (DEV_PTYM_MAJOR, unit);
1195   else if (!setup ())
1196     {
1197       dev ().parse (FH_ERROR);
1198       return; 
1199     }
1200   set_name ("/dev/ptmx");
1201 }
1202
1203 int
1204 fhandler_pty_master::open (int flags, mode_t)
1205 {
1206   set_open_status ();
1207   dwProcessId = GetCurrentProcessId ();
1208   return 1;
1209 }
1210
1211 void
1212 fhandler_pty_master::open_setup (int flags)
1213 {
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, "");
1218 }
1219
1220 _off64_t
1221 fhandler_pty_common::lseek (_off64_t, int)
1222 {
1223   set_errno (ESPIPE);
1224   return -1;
1225 }
1226
1227 int
1228 fhandler_pty_common::close ()
1229 {
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 ());
1239
1240   if (!ForceCloseHandle (input_available_event))
1241     termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1242
1243   return 0;
1244 }
1245
1246 void
1247 fhandler_pty_master::cleanup ()
1248 {
1249   report_tty_counts (this, "closing master", "");
1250   if (archetype)
1251     from_master = to_master = NULL;
1252 }
1253
1254 int
1255 fhandler_pty_master::close ()
1256 {
1257 #if 0
1258   while (accept_input () > 0)
1259     continue;
1260 #endif
1261
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)
1265     {
1266       if (master_ctl && get_ttyp ()->master_pid == myself->pid)
1267         {
1268           char buf[MAX_PATH];
1269           pipe_request req = { (DWORD) -1 };
1270           pipe_reply repl;
1271           DWORD len;
1272
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 ();
1278         }
1279     }
1280
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;
1286
1287   fhandler_pty_common::close ();
1288
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);
1291   else
1292     get_ttyp ()->set_master_closed ();
1293
1294   return 0;
1295 }
1296
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 ()
1301 {
1302   if (from_master && to_master)
1303     close_with_arch ();
1304 }
1305
1306 ssize_t __stdcall
1307 fhandler_pty_master::write (const void *ptr, size_t len)
1308 {
1309   int i;
1310   char *p = (char *) ptr;
1311   termios ti = tc ()->ti;
1312
1313   bg_check_types bg = bg_check (SIGTTOU);
1314   if (bg <= bg_eof)
1315     return (ssize_t) bg;
1316
1317   push_process_state process_state (PID_TTYOU);
1318
1319   for (i = 0; i < (int) len; i++)
1320     {
1321       line_edit_status status = line_edit (p++, 1, ti);
1322       if (status > line_edit_signalled)
1323         {
1324           if (status != line_edit_pipe_full)
1325             i = -1;
1326           break;
1327         }
1328     }
1329   return i;
1330 }
1331
1332 void __stdcall
1333 fhandler_pty_master::read (void *ptr, size_t& len)
1334 {
1335   bg_check_types bg = bg_check (SIGTTIN);
1336   if (bg <= bg_eof)
1337     {
1338       len = (size_t) bg;
1339       return;
1340     }
1341   push_process_state process_state (PID_TTYIN);
1342   len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1343 }
1344
1345 int
1346 fhandler_pty_master::tcgetattr (struct termios *t)
1347 {
1348   *t = cygwin_shared->tty[get_unit ()]->ti;
1349   return 0;
1350 }
1351
1352 int
1353 fhandler_pty_master::tcsetattr (int, const struct termios *t)
1354 {
1355   cygwin_shared->tty[get_unit ()]->ti = *t;
1356   return 0;
1357 }
1358
1359 int
1360 fhandler_pty_master::tcflush (int queue)
1361 {
1362   int ret = 0;
1363
1364   termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1365
1366   if (queue == TCIFLUSH || queue == TCIOFLUSH)
1367     ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1368   else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1369     {
1370       /* do nothing for now. */
1371     }
1372
1373   termios_printf ("%d=tcflush(%d)", ret, queue);
1374   return ret;
1375 }
1376
1377 int
1378 fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1379 {
1380   int res = fhandler_termios::ioctl (cmd, arg);
1381   if (res <= 0)
1382     return res;
1383
1384   switch (cmd)
1385     {
1386     case TIOCPKT:
1387       pktmode = *(int *) arg;
1388       break;
1389     case TIOCGWINSZ:
1390       *(struct winsize *) arg = get_ttyp ()->winsize;
1391       break;
1392     case TIOCSWINSZ:
1393       if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1394           || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1395         {
1396           get_ttyp ()->winsize = *(struct winsize *) arg;
1397           killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1398         }
1399       break;
1400     case TIOCGPGRP:
1401       *((pid_t *) arg) = this->tcgetpgrp ();
1402       break;
1403     case TIOCSPGRP:
1404       return this->tcsetpgrp ((pid_t) arg);
1405     case FIONREAD:
1406       {
1407         int n;
1408         if (!PeekNamedPipe (to_master, NULL, 0, NULL, (DWORD *) &n, NULL))
1409           {
1410             set_errno (EINVAL);
1411             return -1;
1412           }
1413         *(int *) arg = n;
1414       }
1415       break;
1416     default:
1417       return fhandler_base::ioctl (cmd, arg);
1418     }
1419   return 0;
1420 }
1421
1422 int
1423 fhandler_pty_master::ptsname_r (char *buf, size_t buflen)
1424 {
1425   char tmpbuf[TTY_NAME_MAX];
1426
1427   __ptsname (tmpbuf, get_unit ());
1428   if (buflen <= strlen (tmpbuf))
1429     {
1430       set_errno (ERANGE);
1431       return ERANGE;
1432     }
1433   strcpy (buf, tmpbuf);
1434   return 0;
1435 }
1436
1437 void
1438 fhandler_pty_common::set_close_on_exec (bool val)
1439 {
1440   // Cygwin processes will handle this specially on exec.
1441   close_on_exec (val);
1442 }
1443
1444 void
1445 fhandler_pty_slave::fixup_after_fork (HANDLE parent)
1446 {
1447   // fork_fixup (parent, inuse, "inuse");
1448   // fhandler_pty_common::fixup_after_fork (parent);
1449   report_tty_counts (this, "inherited", "");
1450 }
1451
1452 void
1453 fhandler_pty_slave::fixup_after_exec ()
1454 {
1455   if (!close_on_exec ())
1456     fixup_after_fork (NULL);
1457 }
1458
1459 extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
1460
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.
1467
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.
1474
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. */
1479
1480 DWORD
1481 fhandler_pty_master::pty_master_thread ()
1482 {
1483   bool exit = false;
1484   GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
1485                           EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
1486   pipe_request req;
1487   DWORD len;
1488   security_descriptor sd;
1489   HANDLE token;
1490   PRIVILEGE_SET ps;
1491   DWORD pid;
1492   NTSTATUS status;
1493
1494   termios_printf ("Entered");
1495   while (!exit && (ConnectNamedPipe (master_ctl, NULL)
1496                    || GetLastError () == ERROR_PIPE_CONNECTED))
1497     {
1498       pipe_reply repl = { NULL, NULL, 0 };
1499       bool deimp = false;
1500       NTSTATUS allow = STATUS_ACCESS_DENIED;
1501       ACCESS_MASK access = EVENT_MODIFY_STATE;
1502       HANDLE client = NULL;
1503
1504       if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
1505         {
1506           termios_printf ("ReadFile, %E");
1507           goto reply;
1508         }
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))
1513         pid = req.pid;
1514       if (get_object_sd (input_available_event, sd))
1515         {
1516           termios_printf ("get_object_sd, %E");
1517           goto reply;
1518         }
1519       cygheap->user.deimpersonate ();
1520       deimp = true;
1521       if (!ImpersonateNamedPipeClient (master_ctl))
1522         {
1523           termios_printf ("ImpersonateNamedPipeClient, %E");
1524           goto reply;
1525         }
1526       status = NtOpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE,
1527                                   &token);
1528       if (!NT_SUCCESS (status))
1529         {
1530           termios_printf ("NtOpenThreadToken, %p", status);
1531           SetLastError (RtlNtStatusToDosError (status));
1532           goto reply;
1533         }
1534       len = sizeof ps;
1535       status = NtAccessCheck (sd, token, access, &map, &ps, &len, &access,
1536                               &allow);
1537       NtClose (token);
1538       if (!NT_SUCCESS (status))
1539         {
1540           termios_printf ("NtAccessCheck, %p", status);
1541           SetLastError (RtlNtStatusToDosError (status));
1542           goto reply;
1543         }
1544       if (!RevertToSelf ())
1545         {
1546           termios_printf ("RevertToSelf, %E");
1547           goto reply;
1548         }
1549       if (req.pid == (DWORD) -1)        /* Request to finish thread. */
1550         {
1551           /* Pre-Vista: Just believe in the good of the client process.
1552              Post-Vista: Check if the requesting process is the master
1553              process itself. */
1554           if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
1555             exit = true;
1556           goto reply;
1557         }
1558       if (NT_SUCCESS (allow))
1559         {
1560           client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
1561           if (!client)
1562             {
1563               termios_printf ("OpenProcess, %E");
1564               goto reply;
1565             }
1566           if (!DuplicateHandle (GetCurrentProcess (), from_master,
1567                                client, &repl.from_master,
1568                                0, TRUE, DUPLICATE_SAME_ACCESS))
1569             {
1570               termios_printf ("DuplicateHandle (from_master), %E");
1571               goto reply;
1572             }
1573           if (!DuplicateHandle (GetCurrentProcess (), to_master,
1574                                 client, &repl.to_master,
1575                                 0, TRUE, DUPLICATE_SAME_ACCESS))
1576             {
1577               termios_printf ("DuplicateHandle (to_master), %E");
1578               goto reply;
1579             }
1580         }
1581 reply:
1582       repl.error = GetLastError ();
1583       if (client)
1584         CloseHandle (client);
1585       if (deimp)
1586         cygheap->user.reimpersonate ();
1587       sd.free ();
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");
1594     }
1595   termios_printf ("Leaving");
1596   return 0;
1597 }
1598
1599 static DWORD WINAPI
1600 pty_master_thread (VOID *arg)
1601 {
1602   return ((fhandler_pty_master *) arg)->pty_master_thread ();
1603 }
1604
1605 bool
1606 fhandler_pty_master::setup ()
1607 {
1608   int res;
1609   security_descriptor sd;
1610   SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
1611
1612   /* Find an unallocated pty to use. */
1613   int unit = cygwin_shared->tty.allocate (from_master, get_output_handle ());
1614   if (unit < 0)
1615     return false;
1616
1617   ProtectHandle1 (get_output_handle (), to_pty);
1618
1619   tty& t = *cygwin_shared->tty[unit];
1620   _tc = (tty_min *) &t;
1621
1622   tcinit (true);                /* Set termios information.  Force initialization. */
1623
1624   const char *errstr = NULL;
1625   DWORD pipe_mode = PIPE_NOWAIT;
1626
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 ());
1630
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);
1635   if (res)
1636     {
1637       errstr = "output pipe";
1638       goto err;
1639     }
1640
1641   ProtectHandle1 (get_io_handle (), from_pty);
1642
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,
1648                                         sd))
1649     sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
1650
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,
1656                                              &sa, TRUE))
1657       || GetLastError () == ERROR_ALREADY_EXISTS)
1658     goto err;
1659
1660   char buf[MAX_PATH];
1661   errstr = shared_name (buf, OUTPUT_MUTEX, unit);
1662   if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
1663     goto err;
1664
1665   errstr = shared_name (buf, INPUT_MUTEX, unit);
1666   if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
1667     goto err;
1668
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,
1676                                 0, &sec_all_nih);
1677   if (master_ctl == INVALID_HANDLE_VALUE)
1678     {
1679       errstr = "pty master control pipe";
1680       goto err;
1681     }
1682   master_thread = new cygthread (::pty_master_thread, this, "pty_master");
1683   if (!master_thread)
1684     {
1685       errstr = "pty master control thread";
1686       goto err;
1687     }
1688
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;
1694
1695   dev ().parse (DEV_PTYM_MAJOR, unit);
1696
1697   termios_printf ("this %p, pty%d opened - from_pty %p, to_pty %p", this, unit,
1698                   get_io_handle (), get_output_handle ());
1699   return true;
1700
1701 err:
1702   __seterrno ();
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);
1712   return false;
1713 }
1714
1715 void
1716 fhandler_pty_master::fixup_after_fork (HANDLE parent)
1717 {
1718   DWORD wpid = GetCurrentProcessId ();
1719   fhandler_pty_master *arch = (fhandler_pty_master *) archetype;
1720   if (arch->dwProcessId != wpid)
1721     {
1722       tty& t = *get_ttyp ();
1723       if (myself->pid == t.master_pid)
1724         {
1725           t.from_master = arch->from_master;
1726           t.to_master = arch->to_master;
1727         }
1728       arch->dwProcessId = wpid;
1729     }
1730   from_master = arch->from_master;
1731   to_master = arch->to_master;
1732   report_tty_counts (this, "inherited master", "");
1733 }
1734
1735 void
1736 fhandler_pty_master::fixup_after_exec ()
1737 {
1738   if (!close_on_exec ())
1739     fixup_after_fork (spawn_info->parent);
1740   else
1741     from_master = to_master = NULL;
1742 }