OSDN Git Service

* environ.cc (regopt): Change the first argument to wide char string.
[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 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
28 #define close_maybe(h) \
29   do { \
30     if (h && h != INVALID_HANDLE_VALUE) \
31       CloseHandle (h); \
32   } while (0)
33
34 /* pty master control pipe messages */
35 struct pipe_request {
36   DWORD pid;
37 };
38
39 struct pipe_reply {
40   HANDLE from_master;
41   HANDLE to_master;
42   DWORD error;
43 };
44
45 /* tty master stuff */
46
47 fhandler_tty_master NO_COPY *tty_master;
48
49 static DWORD WINAPI process_input (void *);             // Input queue thread
50 static DWORD WINAPI process_output (void *);            // Output queue thread
51 static DWORD WINAPI process_ioctl (void *);             // Ioctl requests thread
52
53 fhandler_tty_master::fhandler_tty_master ()
54   : fhandler_pty_master (), console (NULL)
55 {
56 }
57
58 int
59 fhandler_tty_slave::get_unit ()
60 {
61   return dev () == FH_TTY ? myself->ctty : dev ().minor;
62 }
63
64 void
65 fhandler_tty_master::set_winsize (bool sendSIGWINCH)
66 {
67   winsize w;
68   console->ioctl (TIOCGWINSZ, &w);
69   get_ttyp ()->winsize = w;
70   if (sendSIGWINCH)
71     tc->kill_pgrp (SIGWINCH);
72 }
73
74 int
75 fhandler_tty_master::init ()
76 {
77   termios_printf ("Creating master for tty%d", get_unit ());
78
79   if (init_console ())
80     {
81       termios_printf ("can't create fhandler");
82       return -1;
83     }
84
85   if (!setup (false))
86     return 1;
87
88   set_winsize (false);
89
90   set_close_on_exec (true);
91
92   cygthread *h;
93   h = new cygthread (process_input, 0, cygself, "ttyin");
94   h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
95   h->zap_h ();
96
97   h = new cygthread (process_ioctl, 0, cygself, "ttyioctl");
98   h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
99   h->zap_h ();
100
101   h = new cygthread (process_output, 0, cygself, "ttyout");
102   h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
103   h->zap_h ();
104
105   return 0;
106 }
107
108 #ifdef DEBUGGING
109 static class mutex_stack
110 {
111 public:
112   const char *fn;
113   int ln;
114   const char *tname;
115 } ostack[100];
116
117 static int osi;
118 #endif /*DEBUGGING*/
119
120 DWORD
121 fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
122                                            DWORD ms)
123 {
124   if (strace.active ())
125     strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms);
126   DWORD res = WaitForSingleObject (output_mutex, ms);
127   if (res == WAIT_OBJECT_0)
128     {
129 #ifndef DEBUGGING
130       if (strace.active ())
131         strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: acquired", ln, res);
132 #else
133       ostack[osi].fn = fn;
134       ostack[osi].ln = ln;
135       ostack[osi].tname = cygthread::name ();
136       termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
137       osi++;
138 #endif
139     }
140   return res;
141 }
142
143 void
144 fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
145 {
146   if (ReleaseMutex (output_mutex))
147     {
148 #ifndef DEBUGGING
149       if (strace.active ())
150         strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln);
151 #else
152       if (osi > 0)
153         osi--;
154       termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
155       termios_printf ("  for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
156       ostack[osi].ln = -ln;
157 #endif
158     }
159 #ifdef DEBUGGING
160   else if (osi > 0)
161     {
162       system_printf ("couldn't release output mutex but we seem to own it, %E");
163       try_to_debug ();
164     }
165 #endif
166 }
167
168 /* Process tty input. */
169
170 void
171 fhandler_pty_master::doecho (const void *str, DWORD len)
172 {
173   acquire_output_mutex (INFINITE);
174   if (!WriteFile (to_master, str, len, &len, NULL))
175     termios_printf ("Write to %p failed, %E", to_master);
176 //  WaitForSingleObject (output_done_event, INFINITE);
177   release_output_mutex ();
178 }
179
180 int
181 fhandler_pty_master::accept_input ()
182 {
183   DWORD bytes_left;
184   int ret = 1;
185
186   WaitForSingleObject (input_mutex, INFINITE);
187
188   bytes_left = eat_readahead (-1);
189
190   if (!bytes_left)
191     {
192       termios_printf ("sending EOF to slave");
193       get_ttyp ()->read_retval = 0;
194     }
195   else
196     {
197       char *p = rabuf;
198       DWORD rc;
199       DWORD written = 0;
200
201       termios_printf ("about to write %d chars to slave", bytes_left);
202       rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
203       if (!rc)
204         {
205           debug_printf ("error writing to pipe %E");
206           get_ttyp ()->read_retval = -1;
207           ret = -1;
208         }
209       else
210         {
211           get_ttyp ()->read_retval = 1;
212           p += written;
213           bytes_left -= written;
214           if (bytes_left > 0)
215             {
216               debug_printf ("to_slave pipe is full");
217               puts_readahead (p, bytes_left);
218               ret = 0;
219             }
220         }
221     }
222
223   SetEvent (input_available_event);
224   ReleaseMutex (input_mutex);
225   return ret;
226 }
227
228 static DWORD WINAPI
229 process_input (void *)
230 {
231   char rawbuf[INP_BUFFER_SIZE];
232
233   while (1)
234     {
235       size_t nraw = INP_BUFFER_SIZE;
236       tty_master->console->read ((void *) rawbuf, nraw);
237       if (tty_master->line_edit (rawbuf, nraw, tty_master->get_ttyp ()->ti)
238           == line_edit_signalled)
239         tty_master->console->eat_readahead (-1);
240     }
241 }
242
243 bool
244 fhandler_pty_master::hit_eof ()
245 {
246   if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
247     {
248       /* We have the only remaining open handle to this pty, and
249          the slave pty has been opened at least once.  We treat
250          this as EOF.  */
251       termios_printf ("all other handles closed");
252       return 1;
253     }
254   return 0;
255 }
256
257 /* Process tty output requests */
258
259 int
260 fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
261 {
262   size_t rlen;
263   char outbuf[OUT_BUFFER_SIZE + 1];
264   DWORD n;
265   int column = 0;
266   int rc = 0;
267
268   if (len == 0)
269     goto out;
270
271   if (need_nl)
272     {
273       /* We need to return a left over \n character, resulting from
274          \r\n conversion.  Note that we already checked for FLUSHO and
275          output_stopped at the time that we read the character, so we
276          don't check again here.  */
277       if (buf)
278         buf[0] = '\n';
279       need_nl = 0;
280       rc = 1;
281       goto out;
282     }
283
284
285   for (;;)
286     {
287       /* Set RLEN to the number of bytes to read from the pipe.  */
288       rlen = len;
289       if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
290         {
291           /* We are going to expand \n to \r\n, so don't read more than
292              half of the number of bytes requested.  */
293           rlen /= 2;
294           if (rlen == 0)
295             rlen = 1;
296         }
297       if (rlen > sizeof outbuf)
298         rlen = sizeof outbuf;
299
300       HANDLE handle = get_io_handle ();
301
302       n = 0; // get_readahead_into_buffer (outbuf, len);
303       if (!n)
304         {
305           /* Doing a busy wait like this is quite inefficient, but nothing
306              else seems to work completely.  Windows should provide some sort
307              of overlapped I/O for pipes, or something, but it doesn't.  */
308           while (1)
309             {
310               if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
311                 goto err;
312               if (n > 0)
313                 break;
314               if (hit_eof ())
315                 goto out;
316               /* DISCARD (FLUSHO) and tcflush can finish here. */
317               if (n == 0 && (get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
318                 goto out;
319               if (n == 0 && is_nonblocking ())
320                 {
321                   set_errno (EAGAIN);
322                   rc = -1;
323                   break;
324                 }
325
326               Sleep (10);
327             }
328
329           if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE)
330             goto err;
331         }
332
333       termios_printf ("bytes read %u", n);
334       get_ttyp ()->write_error = 0;
335       if (output_done_event != NULL)
336         SetEvent (output_done_event);
337
338       if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
339         continue;
340
341       char *optr;
342       optr = buf;
343       if (pktmode_on)
344         *optr++ = TIOCPKT_DATA;
345
346       if (!(get_ttyp ()->ti.c_oflag & OPOST))   // post-process output
347         {
348           memcpy (optr, outbuf, n);
349           optr += n;
350         }
351       else                                      // raw output mode
352         {
353           char *iptr = outbuf;
354
355           while (n--)
356             {
357               switch (*iptr)
358                 {
359                 case '\r':
360                   if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
361                     {
362                       iptr++;
363                       continue;
364                     }
365                   if (get_ttyp ()->ti.c_oflag & OCRNL)
366                     *iptr = '\n';
367                   else
368                     column = 0;
369                   break;
370                 case '\n':
371                   if (get_ttyp ()->ti.c_oflag & ONLCR)
372                     {
373                       *optr++ = '\r';
374                       column = 0;
375                     }
376                   if (get_ttyp ()->ti.c_oflag & ONLRET)
377                     column = 0;
378                   break;
379                 default:
380                   column++;
381                   break;
382                 }
383
384               /* Don't store data past the end of the user's buffer.  This
385                  can happen if the user requests a read of 1 byte when
386                  doing \r\n expansion.  */
387               if (optr - buf >= (int) len)
388                 {
389                   if (*iptr != '\n' || n != 0)
390                     system_printf ("internal error: %d unexpected characters", n);
391                   need_nl = 1;
392                   break;
393                 }
394
395               *optr++ = *iptr++;
396             }
397         }
398       rc = optr - buf;
399       break;
400
401     err:
402       if (GetLastError () == ERROR_BROKEN_PIPE)
403         rc = 0;
404       else
405         {
406           __seterrno ();
407           rc = -1;
408         }
409       break;
410     }
411
412 out:
413   termios_printf ("returning %d", rc);
414   return rc;
415 }
416
417 static DWORD WINAPI
418 process_output (void *)
419 {
420   char buf[OUT_BUFFER_SIZE * 2];
421
422   for (;;)
423     {
424       int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
425       if (n <= 0)
426         {
427           if (n < 0)
428             termios_printf ("ReadFile %E");
429           ExitThread (0);
430         }
431       n = tty_master->console->write ((void *) buf, (size_t) n);
432       tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
433     }
434 }
435
436
437 /* Process tty ioctl requests */
438
439 static DWORD WINAPI
440 process_ioctl (void *)
441 {
442   while (1)
443     {
444       WaitForSingleObject (tty_master->ioctl_request_event, INFINITE);
445       termios_printf ("ioctl() request");
446       tty *ttyp = tty_master->get_ttyp ();
447       ttyp->ioctl_retval =
448       tty_master->console->ioctl (ttyp->cmd,
449                                   (ttyp->cmd == KDSKBMETA)
450                                   ? (void *) ttyp->arg.value
451                                   : (void *) &ttyp->arg);
452       SetEvent (tty_master->ioctl_done_event);
453     }
454 }
455
456 /**********************************************************************/
457 /* Tty slave stuff */
458
459 fhandler_tty_slave::fhandler_tty_slave ()
460   : fhandler_tty_common (), inuse (NULL)
461 {
462   uninterruptible_io (true);
463 }
464
465 /* FIXME: This function needs to close handles when it has
466    a failing condition. */
467 int
468 fhandler_tty_slave::open (int flags, mode_t)
469 {
470   HANDLE tty_owner, from_master_local, to_master_local;
471   HANDLE *handles[] =
472   {
473     &from_master_local, &input_available_event, &input_mutex, &inuse,
474     &ioctl_done_event, &ioctl_request_event, &output_done_event,
475     &output_mutex, &to_master_local, &tty_owner,
476     NULL
477   };
478
479   const char *errmsg = NULL;
480
481   for (HANDLE **h = handles; *h; h++)
482     **h = NULL;
483
484   if (get_device () == FH_TTY)
485     dev().tty_to_real_device ();
486   fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev);
487   if (arch)
488     {
489       *this = *(fhandler_tty_slave *) arch;
490       termios_printf ("copied fhandler_tty_slave archetype");
491       set_flags ((flags & ~O_TEXT) | O_BINARY);
492       cygheap->manage_console_count ("fhandler_tty_slave::open<arch>", 1);
493       goto out;
494     }
495
496   tcinit (cygwin_shared->tty[get_unit ()]);
497
498   cygwin_shared->tty.attach (get_unit ());
499
500   set_flags ((flags & ~O_TEXT) | O_BINARY);
501   /* Create synchronisation events */
502   char buf[MAX_PATH];
503
504   /* output_done_event may or may not exist.  It will exist if the tty
505      was opened by fhandler_tty_master::init, normally called at
506      startup if use_tty is non-zero.  It will not exist if this is a
507      pty opened by fhandler_pty_master::open.  In the former case, tty
508      output is handled by a separate thread which controls output.  */
509   shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
510   output_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
511
512   if (!(output_mutex = get_ttyp ()->open_output_mutex (MAXIMUM_ALLOWED)))
513     {
514       errmsg = "open output mutex failed, %E";
515       goto err;
516     }
517   if (!(input_mutex = get_ttyp ()->open_input_mutex (MAXIMUM_ALLOWED)))
518     {
519       errmsg = "open input mutex failed, %E";
520       goto err;
521     }
522   shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
523   if (!(input_available_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf)))
524     {
525       errmsg = "open input event failed, %E";
526       goto err;
527     }
528
529   /* The ioctl events may or may not exist.  See output_done_event,
530      above.  */
531   shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
532   ioctl_request_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
533   shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
534   ioctl_done_event = OpenEvent (MAXIMUM_ALLOWED, TRUE, buf);
535
536   /* FIXME: Needs a method to eliminate tty races */
537   {
538     /* Create security attribute.  Default permissions are 0620. */
539     security_descriptor sd;
540     sd.malloc (sizeof (SECURITY_DESCRIPTOR));
541     InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
542     SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
543     if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
544                                           S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
545                                           sd))
546       sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
547     acquire_output_mutex (500);
548     inuse = get_ttyp ()->create_inuse (&sa);
549     get_ttyp ()->was_opened = true;
550     release_output_mutex ();
551   }
552
553   if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
554     {
555       errmsg = "tty handles have been closed";
556       set_errno (EACCES);
557       goto err_no_errno;
558     }
559
560   if (get_ttyp ()->master_pid < 0)
561     {
562       errmsg = "*** master is closed";
563       set_errno (EAGAIN);
564       goto err_no_errno;
565     }
566   /* Three case for duplicating the pipe handles:
567      - Either we're the master.  In this case, just duplicate the handles.
568      - Or, we have the right to open the master process for handle duplication.
569        In this case, just duplicate the handles.
570      - Or, we have to ask the master process itself.  In this case, send our
571        pid to the master process and check the reply.  The reply contains
572        either the handles, or an error code which tells us why we didn't
573        get the handles. */
574   if (myself->pid == get_ttyp ()->master_pid)
575     {
576       /* This is the most common case, just calling openpty. */
577       termios_printf ("dup handles within myself.");
578       tty_owner = GetCurrentProcess ();
579     }
580   else
581     {
582       pinfo p (get_ttyp ()->master_pid);
583       if (!p)
584         termios_printf ("*** couldn't find tty master");
585       else
586         {
587           tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE, p->dwProcessId);
588           if (tty_owner)
589             termios_printf ("dup handles directly since I'm allmighty.");
590         }
591     }
592   if (tty_owner)
593     {
594       if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
595                             GetCurrentProcess (), &from_master_local, 0, TRUE,
596                             DUPLICATE_SAME_ACCESS))
597         {
598           termios_printf ("can't duplicate input from %u/%p, %E",
599                           get_ttyp ()->master_pid, get_ttyp ()->from_master);
600           __seterrno ();
601           goto err_no_msg;
602         }
603       if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
604                           GetCurrentProcess (), &to_master_local, 0, TRUE,
605                           DUPLICATE_SAME_ACCESS))
606         {
607           errmsg = "can't duplicate output, %E";
608           goto err;
609         }
610       if (tty_owner != GetCurrentProcess ())
611         CloseHandle (tty_owner);
612     }
613   else
614     {
615       pipe_request req = { GetCurrentProcessId () };
616       pipe_reply repl;
617       DWORD len;
618
619       __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
620                        &installation_key, get_unit ());
621       termios_printf ("dup handles via master control pipe %s", buf);
622       if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl,
623                           &len, 500))
624         {
625           errmsg = "can't call master, %E";
626           goto err;
627         }
628       from_master_local = repl.from_master;
629       to_master_local = repl.to_master;
630       if (!from_master_local || !to_master_local)
631         {
632           SetLastError (repl.error);
633           errmsg = "error duplicating pipes, %E";
634           goto err;
635         }
636     }
637   VerifyHandle (from_master_local);
638   VerifyHandle (to_master_local);
639
640   termios_printf ("duplicated from_master %p->%p from tty_owner",
641                   get_ttyp ()->from_master, from_master_local);
642   termios_printf ("duplicated to_master %p->%p from tty_owner",
643                   get_ttyp ()->to_master, to_master_local);
644
645   set_io_handle (from_master_local);
646   set_output_handle (to_master_local);
647   set_close_on_exec (!!(flags & O_CLOEXEC));
648
649   set_open_status ();
650   if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1
651       && !output_done_event)
652     fhandler_console::need_invisible ();
653
654   // FIXME: Do this better someday
655   arch = (fhandler_tty_slave *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
656   *((fhandler_tty_slave **) cygheap->fdtab.add_archetype ()) = arch;
657   archetype = arch;
658   *arch = *this;
659
660 out:
661   usecount = 0;
662   arch->usecount++;
663   report_tty_counts (this, "opened", "");
664   myself->set_ctty (get_ttyp (), flags, arch);
665
666   return 1;
667
668 err:
669   __seterrno ();
670 err_no_errno:
671   termios_printf (errmsg);
672 err_no_msg:
673   for (HANDLE **h = handles; *h; h++)
674     if (**h && **h != INVALID_HANDLE_VALUE)
675       CloseHandle (**h);
676   return 0;
677 }
678
679 int
680 fhandler_tty_slave::close ()
681 {
682   /* This used to always call fhandler_tty_common::close when hExeced but that
683      caused multiple closes of the handles associated with this tty.  Since
684      close_all_files is not called until after the cygwin process has synced
685      or before a non-cygwin process has exited, it should be safe to just
686      close this normally.  cgf 2006-05-20 */
687   cygheap->manage_console_count ("fhandler_tty_slave::close", -1);
688
689   archetype->usecount--;
690   report_tty_counts (this, "closed", "");
691
692   if (archetype->usecount)
693     {
694 #ifdef DEBUGGING
695       if (archetype->usecount < 0)
696         system_printf ("error: usecount %d", archetype->usecount);
697 #endif
698       termios_printf ("just returning because archetype usecount is != 0");
699       return 0;
700     }
701
702   termios_printf ("closing last open %s handle", ttyname ());
703   if (inuse && !CloseHandle (inuse))
704     termios_printf ("CloseHandle (inuse), %E");
705   return fhandler_tty_common::close ();
706 }
707
708 int
709 fhandler_tty_slave::init (HANDLE f, DWORD a, mode_t)
710 {
711   int flags = 0;
712
713   a &= GENERIC_READ | GENERIC_WRITE;
714   if (a == GENERIC_READ)
715     flags = O_RDONLY;
716   if (a == GENERIC_WRITE)
717     flags = O_WRONLY;
718   if (a == (GENERIC_READ | GENERIC_WRITE))
719     flags = O_RDWR;
720
721   int ret = open (flags);
722   if (ret && !cygwin_finished_initializing && !IsDebuggerPresent ())
723     {
724       /* This only occurs when called from dtable::init_std_file_from_handle
725          We have been started from a non-Cygwin process.  So we should become
726          tty process group leader.
727          TODO: Investigate how SIGTTIN should be handled with pure-windows
728          programs. */
729       tc->pgid = myself->pgid;
730     }
731
732   if (f != INVALID_HANDLE_VALUE)
733     CloseHandle (f);    /* Reopened by open */
734
735   return ret;
736 }
737
738 ssize_t __stdcall
739 fhandler_tty_slave::write (const void *ptr, size_t len)
740 {
741   DWORD n, towrite = len;
742
743   termios_printf ("tty%d, write(%x, %d)", get_unit (), ptr, len);
744
745   acquire_output_mutex (INFINITE);
746
747   while (len)
748     {
749       n = min (OUT_BUFFER_SIZE, len);
750       char *buf = (char *)ptr;
751       ptr = (char *) ptr + n;
752       len -= n;
753
754       /* Previous write may have set write_error to != 0.  Check it here.
755          This is less than optimal, but the alternative slows down tty
756          writes enormously. */
757       if (get_ttyp ()->write_error)
758         {
759           set_errno (get_ttyp ()->write_error);
760           towrite = (DWORD) -1;
761           break;
762         }
763
764       if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
765         {
766           DWORD err = GetLastError ();
767           termios_printf ("WriteFile failed, %E");
768           switch (err)
769             {
770             case ERROR_NO_DATA:
771               err = ERROR_IO_DEVICE;
772             default:
773               __seterrno_from_win_error (err);
774             }
775           raise (SIGHUP);               /* FIXME: Should this be SIGTTOU? */
776           towrite = (DWORD) -1;
777           break;
778         }
779
780       if (output_done_event != NULL)
781         {
782           DWORD rc;
783           DWORD x = n * 1000;
784           rc = WaitForSingleObject (output_done_event, x);
785           termios_printf ("waited %d ms for output_done_event, WFSO %d", x, rc);
786         }
787     }
788   release_output_mutex ();
789   return towrite;
790 }
791
792 void __stdcall
793 fhandler_tty_slave::read (void *ptr, size_t& len)
794 {
795   int totalread = 0;
796   int vmin = 0;
797   int vtime = 0;        /* Initialized to prevent -Wuninitialized warning */
798   size_t readlen;
799   DWORD bytes_in_pipe;
800   char buf[INP_BUFFER_SIZE];
801   char peek_buf[INP_BUFFER_SIZE];
802   DWORD time_to_wait;
803   DWORD rc;
804   HANDLE w4[2];
805
806   termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
807
808   if (!ptr) /* Indicating tcflush(). */
809     time_to_wait = 0;
810   else if ((get_ttyp ()->ti.c_lflag & ICANON))
811     time_to_wait = INFINITE;
812   else
813     {
814       vmin = get_ttyp ()->ti.c_cc[VMIN];
815       if (vmin > INP_BUFFER_SIZE)
816         vmin = INP_BUFFER_SIZE;
817       vtime = get_ttyp ()->ti.c_cc[VTIME];
818       if (vmin < 0)
819         vmin = 0;
820       if (vtime < 0)
821         vtime = 0;
822       if (!vmin && !vtime)
823         time_to_wait = 0;
824       else
825         time_to_wait = !vtime ? INFINITE : 100 * vtime;
826     }
827
828   w4[0] = signal_arrived;
829   w4[1] = input_available_event;
830
831   DWORD waiter = time_to_wait;
832   while (len)
833     {
834       rc = WaitForMultipleObjects (2, w4, FALSE, waiter);
835
836       if (rc == WAIT_TIMEOUT)
837         {
838           termios_printf ("wait timed out, waiter %u", waiter);
839           break;
840         }
841
842       if (rc == WAIT_FAILED)
843         {
844           termios_printf ("wait for input event failed, %E");
845           break;
846         }
847
848       if (rc == WAIT_OBJECT_0)
849         {
850           /* if we've received signal after successfully reading some data,
851              just return all data successfully read */
852           if (totalread > 0)
853             break;
854           set_sig_errno (EINTR);
855           len = (size_t) -1;
856           return;
857         }
858
859       rc = WaitForSingleObject (input_mutex, 1000);
860       if (rc == WAIT_FAILED)
861         {
862           termios_printf ("wait for input mutex failed, %E");
863           break;
864         }
865       else if (rc == WAIT_TIMEOUT)
866         {
867           termios_printf ("failed to acquire input mutex after input event arrived");
868           break;
869         }
870       if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
871         {
872           termios_printf ("PeekNamedPipe failed, %E");
873           raise (SIGHUP);
874           bytes_in_pipe = 0;
875         }
876
877       /* On first peek determine no. of bytes to flush. */
878       if (!ptr && len == UINT_MAX)
879         len = (size_t) bytes_in_pipe;
880
881       if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
882         {
883           ReleaseMutex (input_mutex);
884           len = (size_t) bytes_in_pipe;
885           return;
886         }
887
888       readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
889
890       if (ptr && vmin && readlen > (unsigned) vmin)
891         readlen = vmin;
892
893       DWORD n = 0;
894       if (readlen)
895         {
896           termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
897           if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
898             {
899               termios_printf ("read failed, %E");
900               raise (SIGHUP);
901             }
902           /* MSDN states that 5th prameter can be used to determine total
903              number of bytes in pipe, but for some reason this number doesn't
904              change after successful read. So we have to peek into the pipe
905              again to see if input is still available */
906           if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
907             {
908               termios_printf ("PeekNamedPipe failed, %E");
909               raise (SIGHUP);
910               bytes_in_pipe = 0;
911             }
912           if (n)
913             {
914               len -= n;
915               totalread += n;
916               if (ptr)
917                 {
918                   memcpy (ptr, buf, n);
919                   ptr = (char *) ptr + n;
920                 }
921             }
922         }
923
924       if (!bytes_in_pipe)
925         ResetEvent (input_available_event);
926
927       ReleaseMutex (input_mutex);
928
929       if (!ptr)
930         {
931           if (!bytes_in_pipe)
932             break;
933           continue;
934         }
935
936       if (get_ttyp ()->read_retval < 0) // read error
937         {
938           set_errno (-get_ttyp ()->read_retval);
939           totalread = -1;
940           break;
941         }
942       if (get_ttyp ()->read_retval == 0)        //EOF
943         {
944           termios_printf ("saw EOF");
945           break;
946         }
947       if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
948         break;
949       if (vmin && totalread >= vmin)
950         break;
951
952       /* vmin == 0 && vtime == 0:
953        *   we've already read all input, if any, so return immediately
954        * vmin == 0 && vtime > 0:
955        *   we've waited for input 10*vtime ms in WFSO(input_available_event),
956        *   no matter whether any input arrived, we shouldn't wait any longer,
957        *   so return immediately
958        * vmin > 0 && vtime == 0:
959        *   here, totalread < vmin, so continue waiting until more data
960        *   arrive
961        * vmin > 0 && vtime > 0:
962        *   similar to the previous here, totalread < vmin, and timer
963        *   hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
964        *   so "restart timer" and wait until more data arrive
965        */
966
967       if (vmin == 0)
968         break;
969
970       if (n)
971         waiter = time_to_wait;
972     }
973   termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
974   len = (size_t) totalread;
975 }
976
977 int
978 fhandler_tty_slave::dup (fhandler_base *child)
979 {
980   fhandler_tty_slave *arch = (fhandler_tty_slave *) archetype;
981   *(fhandler_tty_slave *) child = *arch;
982   child->set_flags (get_flags ());
983   child->usecount = 0;
984   arch->usecount++;
985   cygheap->manage_console_count ("fhandler_tty_slave::dup", 1);
986   report_tty_counts (child, "duped", "");
987   return 0;
988 }
989
990 int
991 fhandler_pty_master::dup (fhandler_base *child)
992 {
993   fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
994   *(fhandler_tty_master *) child = *arch;
995   child->set_flags (get_flags ());
996   child->usecount = 0;
997   arch->usecount++;
998   report_tty_counts (child, "duped master", "");
999   return 0;
1000 }
1001
1002 int
1003 fhandler_tty_slave::tcgetattr (struct termios *t)
1004 {
1005   *t = get_ttyp ()->ti;
1006   return 0;
1007 }
1008
1009 int
1010 fhandler_tty_slave::tcsetattr (int, const struct termios *t)
1011 {
1012   acquire_output_mutex (INFINITE);
1013   get_ttyp ()->ti = *t;
1014   release_output_mutex ();
1015   return 0;
1016 }
1017
1018 int
1019 fhandler_tty_slave::tcflush (int queue)
1020 {
1021   int ret = 0;
1022
1023   termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1024
1025   if (queue == TCIFLUSH || queue == TCIOFLUSH)
1026     {
1027       size_t len = UINT_MAX;
1028       read (NULL, len);
1029       ret = ((int) len) >= 0 ? 0 : -1;
1030     }
1031   if (queue == TCOFLUSH || queue == TCIOFLUSH)
1032     {
1033       /* do nothing for now. */
1034     }
1035
1036   termios_printf ("%d=tcflush(%d)", ret, queue);
1037   return ret;
1038 }
1039
1040 int
1041 fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
1042 {
1043   termios_printf ("ioctl (%x)", cmd);
1044
1045   if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid
1046       && myself->ctty == get_unit () && (get_ttyp ()->ti.c_lflag & TOSTOP))
1047     {
1048       /* background process */
1049       termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
1050                       get_ttyp ()->getpgid (), myctty ());
1051       raise (SIGTTOU);
1052     }
1053
1054   int retval;
1055   switch (cmd)
1056     {
1057     case TIOCGWINSZ:
1058     case TIOCSWINSZ:
1059     case TIOCLINUX:
1060     case KDGKBMETA:
1061     case KDSKBMETA:
1062       break;
1063     case FIONBIO:
1064       set_nonblocking (*(int *) arg);
1065       retval = 0;
1066       goto out;
1067     default:
1068       set_errno (EINVAL);
1069       return -1;
1070     }
1071
1072   acquire_output_mutex (INFINITE);
1073
1074   get_ttyp ()->cmd = cmd;
1075   get_ttyp ()->ioctl_retval = 0;
1076   int val;
1077   switch (cmd)
1078     {
1079     case TIOCGWINSZ:
1080       get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1081       if (ioctl_request_event)
1082         SetEvent (ioctl_request_event);
1083       *(struct winsize *) arg = get_ttyp ()->arg.winsize;
1084       if (ioctl_done_event)
1085         WaitForSingleObject (ioctl_done_event, INFINITE);
1086       get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1087       break;
1088     case TIOCSWINSZ:
1089       if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1090           || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1091         {
1092           get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1093           if (ioctl_request_event)
1094             {
1095               get_ttyp ()->ioctl_retval = -EINVAL;
1096               SetEvent (ioctl_request_event);
1097             }
1098           else
1099             {
1100               get_ttyp ()->winsize = *(struct winsize *) arg;
1101               killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1102             }
1103           if (ioctl_done_event)
1104             WaitForSingleObject (ioctl_done_event, INFINITE);
1105         }
1106       break;
1107     case TIOCLINUX:
1108       val = *(unsigned char *) arg;
1109       if (val != 6 || !ioctl_request_event || !ioctl_done_event)
1110           get_ttyp ()->ioctl_retval = -EINVAL;
1111       else
1112         {
1113           get_ttyp ()->arg.value = val;
1114           SetEvent (ioctl_request_event);
1115           WaitForSingleObject (ioctl_done_event, INFINITE);
1116           *(unsigned char *) arg = (unsigned char) (get_ttyp ()->arg.value);
1117         }
1118       break;
1119     case KDGKBMETA:
1120       if (ioctl_request_event)
1121         {
1122           SetEvent (ioctl_request_event);
1123           if (ioctl_done_event)
1124             WaitForSingleObject (ioctl_done_event, INFINITE);
1125           *(int *) arg = get_ttyp ()->arg.value;
1126         }
1127       else
1128         get_ttyp ()->ioctl_retval = -EINVAL;
1129       break;
1130     case KDSKBMETA:
1131       if (ioctl_request_event)
1132         {
1133           get_ttyp ()->arg.value = (int) arg;
1134           SetEvent (ioctl_request_event);
1135           if (ioctl_done_event)
1136             WaitForSingleObject (ioctl_done_event, INFINITE);
1137         }
1138       else
1139         get_ttyp ()->ioctl_retval = -EINVAL;
1140       break;
1141     }
1142
1143   release_output_mutex ();
1144   retval = get_ttyp ()->ioctl_retval;
1145   if (retval < 0)
1146     {
1147       set_errno (-retval);
1148       retval = -1;
1149     }
1150
1151 out:
1152   termios_printf ("%d = ioctl (%x)", retval, cmd);
1153   return retval;
1154 }
1155
1156 int __stdcall
1157 fhandler_tty_slave::fstat (struct __stat64 *st)
1158 {
1159   fhandler_base::fstat (st);
1160
1161   bool to_close = false;
1162   if (!input_available_event)
1163     {
1164       char buf[MAX_PATH];
1165       shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1166       input_available_event = OpenEvent (READ_CONTROL, TRUE, buf);
1167       if (input_available_event)
1168         to_close = true;
1169     }
1170   if (!input_available_event
1171       || get_object_attribute (input_available_event, &st->st_uid, &st->st_gid,
1172                                &st->st_mode))
1173     {
1174       /* If we can't access the ACL, or if the tty doesn't actually exist,
1175          then fake uid and gid to strict, system-like values. */
1176       st->st_mode = S_IFCHR | S_IRUSR | S_IWUSR;
1177       st->st_uid = 18;
1178       st->st_gid = 544;
1179     }
1180   if (to_close)
1181     CloseHandle (input_available_event);
1182   return 0;
1183 }
1184
1185 /* Helper function for fchmod and fchown, which just opens all handles
1186    and signals success via bool return. */
1187 bool
1188 fhandler_tty_slave::fch_open_handles ()
1189 {
1190   char buf[MAX_PATH];
1191
1192   tc = cygwin_shared->tty[get_unit ()];
1193   shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
1194   input_available_event = OpenEvent (READ_CONTROL | WRITE_DAC | WRITE_OWNER,
1195                                      TRUE, buf);
1196   output_mutex = get_ttyp ()->open_output_mutex (WRITE_DAC | WRITE_OWNER);
1197   input_mutex = get_ttyp ()->open_input_mutex (WRITE_DAC | WRITE_OWNER);
1198   inuse = get_ttyp ()->open_inuse (WRITE_DAC | WRITE_OWNER);
1199   if (!input_available_event || !output_mutex || !input_mutex || !inuse)
1200     {
1201       __seterrno ();
1202       return false;
1203     }
1204   /* These members are optional, no error checking */
1205   shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
1206   output_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1207   shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
1208   ioctl_request_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1209   shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
1210   ioctl_done_event = OpenEvent (WRITE_DAC | WRITE_OWNER, TRUE, buf);
1211   return true;
1212 }
1213
1214 /* Helper function for fchmod and fchown, which sets the new security
1215    descriptor on all objects representing the tty. */
1216 int
1217 fhandler_tty_slave::fch_set_sd (security_descriptor &sd, bool chown)
1218 {
1219   security_descriptor sd_old;
1220
1221   get_object_sd (input_available_event, sd_old);
1222   if (!set_object_sd (input_available_event, sd, chown)
1223       && !set_object_sd (output_mutex, sd, chown)
1224       && !set_object_sd (input_mutex, sd, chown)
1225       && !set_object_sd (inuse, sd, chown)
1226       && (!output_done_event
1227           || !set_object_sd (output_done_event, sd, chown))
1228       && (!ioctl_request_event
1229           || !set_object_sd (ioctl_request_event, sd, chown))
1230       && (!ioctl_done_event
1231           || !set_object_sd (ioctl_done_event, sd, chown)))
1232     return 0;
1233   set_object_sd (input_available_event, sd_old, chown);
1234   set_object_sd (output_mutex, sd_old, chown);
1235   set_object_sd (input_mutex, sd_old, chown);
1236   set_object_sd (inuse, sd_old, chown);
1237   if (!output_done_event)
1238       set_object_sd (output_done_event, sd_old, chown);
1239   if (!ioctl_request_event)
1240       set_object_sd (ioctl_request_event, sd_old, chown);
1241   if (!ioctl_done_event)
1242       set_object_sd (ioctl_done_event, sd_old, chown);
1243   return -1;
1244 }
1245
1246 /* Helper function for fchmod and fchown, which closes all object handles in
1247    the tty. */
1248 void
1249 fhandler_tty_slave::fch_close_handles ()
1250 {
1251   close_maybe (get_io_handle ());
1252   close_maybe (get_output_handle ());
1253   close_maybe (output_done_event);
1254   close_maybe (ioctl_done_event);
1255   close_maybe (ioctl_request_event);
1256   close_maybe (input_available_event);
1257   close_maybe (output_mutex);
1258   close_maybe (input_mutex);
1259   close_maybe (inuse);
1260 }
1261
1262 int __stdcall
1263 fhandler_tty_slave::fchmod (mode_t mode)
1264 {
1265   int ret = -1;
1266   bool to_close = false;
1267   security_descriptor sd;
1268   __uid32_t uid;
1269   __gid32_t gid;
1270
1271   if (!input_available_event)
1272     {
1273       to_close = true;
1274       if (!fch_open_handles ())
1275         goto errout;
1276     }
1277   sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1278   InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1279   if (!get_object_attribute (input_available_event, &uid, &gid, NULL)
1280       && !create_object_sd_from_attribute (NULL, uid, gid, S_IFCHR | mode, sd))
1281     ret = fch_set_sd (sd, false);
1282 errout:
1283   if (to_close)
1284     fch_close_handles ();
1285   return ret;
1286 }
1287
1288 int __stdcall
1289 fhandler_tty_slave::fchown (__uid32_t uid, __gid32_t gid)
1290 {
1291   int ret = -1;
1292   bool to_close = false;
1293   mode_t mode;
1294   __uid32_t o_uid;
1295   __gid32_t o_gid;
1296   security_descriptor sd;
1297
1298   if (uid == ILLEGAL_UID && gid == ILLEGAL_GID)
1299     return 0;
1300   if (!input_available_event)
1301     {
1302       to_close = true;
1303       if (!fch_open_handles ())
1304         goto errout;
1305     }
1306   sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1307   InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1308   if (!get_object_attribute (input_available_event, &o_uid, &o_gid, &mode))
1309     {
1310       if ((uid == ILLEGAL_UID || uid == o_uid)
1311           && (gid == ILLEGAL_GID || gid == o_gid))
1312         ret = 0;
1313       else if (!create_object_sd_from_attribute (input_available_event,
1314                                                  uid, gid, S_IFCHR | mode, sd))
1315         ret = fch_set_sd (sd, true);
1316     }
1317 errout:
1318   if (to_close)
1319     fch_close_handles ();
1320   return ret;
1321 }
1322
1323 /*******************************************************
1324  fhandler_pty_master
1325 */
1326 fhandler_pty_master::fhandler_pty_master ()
1327   : fhandler_tty_common (), pktmode (0), need_nl (0), dwProcessId (0)
1328 {
1329 }
1330
1331 int
1332 fhandler_pty_master::open (int flags, mode_t)
1333 {
1334   int ntty;
1335   ntty = cygwin_shared->tty.allocate (false);
1336   if (ntty < 0)
1337     return 0;
1338
1339   dev().devn = FHDEV (DEV_TTYM_MAJOR, ntty);
1340   if (!setup (true))
1341     {
1342       lock_ttys::release ();
1343       return 0;
1344     }
1345   lock_ttys::release ();
1346   set_flags ((flags & ~O_TEXT) | O_BINARY);
1347   set_open_status ();
1348   //
1349   // FIXME: Do this better someday
1350   fhandler_pty_master *arch = (fhandler_tty_master *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
1351   *((fhandler_pty_master **) cygheap->fdtab.add_archetype ()) = arch;
1352   archetype = arch;
1353   *arch = *this;
1354   arch->dwProcessId = GetCurrentProcessId ();
1355
1356   usecount = 0;
1357   arch->usecount++;
1358   char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
1359   __small_sprintf (buf, "opened pty master for tty%d", get_unit ());
1360   report_tty_counts (this, buf, "");
1361   return 1;
1362 }
1363
1364 _off64_t
1365 fhandler_tty_common::lseek (_off64_t, int)
1366 {
1367   set_errno (ESPIPE);
1368   return -1;
1369 }
1370
1371 int
1372 fhandler_tty_common::close ()
1373 {
1374   termios_printf ("tty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1375   if (output_done_event && !CloseHandle (output_done_event))
1376     termios_printf ("CloseHandle (output_done_event), %E");
1377   if (ioctl_done_event && !CloseHandle (ioctl_done_event))
1378     termios_printf ("CloseHandle (ioctl_done_event), %E");
1379   if (ioctl_request_event && !CloseHandle (ioctl_request_event))
1380     termios_printf ("CloseHandle (ioctl_request_event), %E");
1381   if (!ForceCloseHandle (input_mutex))
1382     termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
1383   if (!ForceCloseHandle (output_mutex))
1384     termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
1385   if (!ForceCloseHandle1 (get_handle (), from_pty))
1386     termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1387   if (!ForceCloseHandle1 (get_output_handle (), to_pty))
1388     termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
1389
1390   if (!ForceCloseHandle (input_available_event))
1391     termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1392
1393   return 0;
1394 }
1395
1396 int
1397 fhandler_pty_master::close ()
1398 {
1399 #if 0
1400   while (accept_input () > 0)
1401     continue;
1402 #endif
1403   archetype->usecount--;
1404   report_tty_counts (this, "closing master", "");
1405
1406   if (archetype->usecount)
1407     {
1408 #ifdef DEBUGGING
1409       if (archetype->usecount < 0)
1410         system_printf ("error: usecount %d", archetype->usecount);
1411 #endif
1412       termios_printf ("just returning because archetype usecount is != 0");
1413       return 0;
1414     }
1415
1416   fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1417   termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1418                   arch->from_master, arch->to_master, arch->dwProcessId);
1419   if (cygwin_finished_initializing)
1420     {
1421       if (arch->master_ctl && get_ttyp ()->master_pid == myself->pid)
1422         {
1423           char buf[MAX_PATH];
1424           pipe_request req = { (DWORD) -1 };
1425           pipe_reply repl;
1426           DWORD len;
1427
1428           __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1429                            &installation_key, get_unit ());
1430           CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500);
1431           CloseHandle (arch->master_ctl);
1432         }
1433       if (!ForceCloseHandle (arch->from_master))
1434         termios_printf ("error closing from_master %p, %E", arch->from_master);
1435       if (!ForceCloseHandle (arch->to_master))
1436         termios_printf ("error closing from_master %p, %E", arch->to_master);
1437     }
1438   fhandler_tty_common::close ();
1439
1440   if (hExeced || get_ttyp ()->master_pid != myself->pid)
1441     termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid);
1442   else
1443     get_ttyp ()->set_master_closed ();
1444
1445   return 0;
1446 }
1447
1448 ssize_t __stdcall
1449 fhandler_pty_master::write (const void *ptr, size_t len)
1450 {
1451   int i;
1452   char *p = (char *) ptr;
1453   termios ti = tc->ti;
1454
1455   for (i = 0; i < (int) len; i++)
1456     {
1457       line_edit_status status = line_edit (p++, 1, ti);
1458       if (status > line_edit_signalled)
1459         {
1460           if (status != line_edit_pipe_full)
1461             i = -1;
1462           break;
1463         }
1464     }
1465   return i;
1466 }
1467
1468 void __stdcall
1469 fhandler_pty_master::read (void *ptr, size_t& len)
1470 {
1471   len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1472 }
1473
1474 int
1475 fhandler_pty_master::tcgetattr (struct termios *t)
1476 {
1477   *t = cygwin_shared->tty[get_unit ()]->ti;
1478   return 0;
1479 }
1480
1481 int
1482 fhandler_pty_master::tcsetattr (int, const struct termios *t)
1483 {
1484   cygwin_shared->tty[get_unit ()]->ti = *t;
1485   return 0;
1486 }
1487
1488 int
1489 fhandler_pty_master::tcflush (int queue)
1490 {
1491   int ret = 0;
1492
1493   termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1494
1495   if (queue == TCIFLUSH || queue == TCIOFLUSH)
1496     ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1497   else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1498     {
1499       /* do nothing for now. */
1500     }
1501
1502   termios_printf ("%d=tcflush(%d)", ret, queue);
1503   return ret;
1504 }
1505
1506 int
1507 fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1508 {
1509   switch (cmd)
1510     {
1511       case TIOCPKT:
1512         pktmode = *(int *) arg;
1513         break;
1514       case TIOCGWINSZ:
1515         *(struct winsize *) arg = get_ttyp ()->winsize;
1516         break;
1517       case TIOCSWINSZ:
1518         if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1519             || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1520           {
1521             get_ttyp ()->winsize = *(struct winsize *) arg;
1522             killsys (-get_ttyp ()->getpgid (), SIGWINCH);
1523           }
1524         break;
1525       case FIONBIO:
1526         set_nonblocking (*(int *) arg);
1527         break;
1528       default:
1529         set_errno (EINVAL);
1530         return -1;
1531     }
1532   return 0;
1533 }
1534
1535 char *
1536 fhandler_pty_master::ptsname ()
1537 {
1538   static char buf[TTY_NAME_MAX];
1539
1540   __small_sprintf (buf, "/dev/tty%d", get_unit ());
1541   return buf;
1542 }
1543
1544 void
1545 fhandler_tty_common::set_close_on_exec (bool val)
1546 {
1547   // Cygwin processes will handle this specially on exec.
1548   close_on_exec (val);
1549 }
1550
1551 void
1552 fhandler_tty_slave::fixup_after_fork (HANDLE parent)
1553 {
1554   // fork_fixup (parent, inuse, "inuse");
1555   // fhandler_tty_common::fixup_after_fork (parent);
1556   report_tty_counts (this, "inherited", "");
1557 }
1558
1559 void
1560 fhandler_tty_slave::fixup_after_exec ()
1561 {
1562   if (!close_on_exec ())
1563     fixup_after_fork (NULL);
1564 }
1565
1566 int
1567 fhandler_tty_master::init_console ()
1568 {
1569   console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym");
1570   if (console == NULL)
1571     return -1;
1572
1573   console->init (INVALID_HANDLE_VALUE, GENERIC_READ | GENERIC_WRITE, O_BINARY);
1574   cygheap->manage_console_count ("fhandler_tty_master::init_console", -1, true);
1575   console->uninterruptible_io (true);
1576   return 0;
1577 }
1578
1579 extern "C" BOOL WINAPI GetNamedPipeClientProcessId (HANDLE, PULONG);
1580
1581 /* This thread function handles the master control pipe.  It waits for a
1582    client to connect.  Then it checks if the client process has permissions
1583    to access the tty handles.  If so, it opens the client process and
1584    duplicates the handles into that process.  If that fails, it sends a reply
1585    with at least one handle set to NULL and an error code.  Last but not
1586    least, the client is disconnected and the thread waits for the next client.
1587
1588    A special case is when the master side of the tty is about to be closed.
1589    The client side is the fhandler_pty_master::close function and it sends
1590    a PID -1 in that case.  On Vista and later a check is performed that the
1591    request to leave really comes from the master process itself.  On earlier
1592    OSes there's no function to check for the PID of the client process so
1593    we have to trust the client side.
1594
1595    Since there's
1596    always only one pipe instance, there's a chance that clients have to
1597    wait to connect to the master control pipe.  Therefore the client calls
1598    to CallNamedPipe should have a big enough timeout value.  For now this
1599    is 500ms.  Hope that's enough. */
1600
1601 DWORD
1602 fhandler_pty_master::pty_master_thread ()
1603 {
1604   bool exit = false;
1605   GENERIC_MAPPING map = { EVENT_QUERY_STATE, EVENT_MODIFY_STATE, 0,
1606                           EVENT_QUERY_STATE | EVENT_MODIFY_STATE };
1607   pipe_request req;
1608   DWORD len;
1609   security_descriptor sd;
1610   HANDLE token;
1611   PRIVILEGE_SET ps;
1612   BOOL ret;
1613   DWORD pid;
1614
1615   termios_printf ("Entered");
1616   while (!exit && ConnectNamedPipe (master_ctl, NULL))
1617     {
1618       pipe_reply repl = { NULL, NULL, 0 };
1619       bool deimp = false;
1620       BOOL allow = FALSE;
1621       ACCESS_MASK access = EVENT_MODIFY_STATE;
1622       HANDLE client = NULL;
1623
1624       if (!ReadFile (master_ctl, &req, sizeof req, &len, NULL))
1625         {
1626           termios_printf ("ReadFile, %E");
1627           goto reply;
1628         }
1629       /* This function is only available since Vista, unfortunately.
1630          In earlier OSes we simply have to believe that the client
1631          has no malicious intent (== sends arbitrary PIDs). */
1632       if (!GetNamedPipeClientProcessId (master_ctl, &pid))
1633         pid = req.pid;
1634       if (get_object_sd (input_available_event, sd))
1635         {
1636           termios_printf ("get_object_sd, %E");
1637           goto reply;
1638         }
1639       cygheap->user.deimpersonate ();
1640       deimp = true;
1641       if (!ImpersonateNamedPipeClient (master_ctl))
1642         {
1643           termios_printf ("ImpersonateNamedPipeClient, %E");
1644           goto reply;
1645         }
1646       if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &token))
1647         {
1648           termios_printf ("OpenThreadToken, %E");
1649           goto reply;
1650         }
1651       len = sizeof ps;
1652       ret = AccessCheck (sd, token, access, &map, &ps, &len, &access, &allow);
1653       CloseHandle (token);
1654       if (!ret)
1655         {
1656           termios_printf ("AccessCheck, %E");
1657           goto reply;
1658         }
1659       if (!RevertToSelf ())
1660         {
1661           termios_printf ("RevertToSelf, %E");
1662           goto reply;
1663         }
1664       if (req.pid == (DWORD) -1)        /* Request to finish thread. */
1665         {
1666           /* Pre-Vista: Just believe in the good of the client process.
1667              Post-Vista: Check if the requesting process is the master
1668              process itself. */
1669           if (pid == (DWORD) -1 || pid == GetCurrentProcessId ())
1670             exit = true;
1671           goto reply;
1672         }
1673       if (allow)
1674         {
1675           client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
1676           if (!client)
1677             {
1678               termios_printf ("OpenProcess, %E");
1679               goto reply;
1680             }
1681           if (!DuplicateHandle (GetCurrentProcess (), from_master,
1682                                client, &repl.from_master,
1683                                0, TRUE, DUPLICATE_SAME_ACCESS))
1684             {
1685               termios_printf ("DuplicateHandle (from_master), %E");
1686               goto reply;
1687             }
1688           if (!DuplicateHandle (GetCurrentProcess (), to_master,
1689                                 client, &repl.to_master,
1690                                 0, TRUE, DUPLICATE_SAME_ACCESS))
1691             {
1692               termios_printf ("DuplicateHandle (to_master), %E");
1693               goto reply;
1694             }
1695         }
1696 reply:
1697       repl.error = GetLastError ();
1698       if (client)
1699         CloseHandle (client);
1700       if (deimp)
1701         cygheap->user.reimpersonate ();
1702       sd.free ();
1703       termios_printf ("Reply: from %p, to %p, error %lu",
1704                       repl.from_master, repl.to_master, repl.error );
1705       if (!WriteFile (master_ctl, &repl, sizeof repl, &len, NULL))
1706         termios_printf ("WriteFile, %E");
1707       if (!DisconnectNamedPipe (master_ctl))
1708         termios_printf ("DisconnectNamedPipe, %E");
1709     }
1710   termios_printf ("Leaving");
1711   return 0;
1712 }
1713
1714 static DWORD WINAPI
1715 pty_master_thread (VOID *arg)           
1716
1717   return ((fhandler_pty_master *) arg)->pty_master_thread ();
1718
1719
1720 bool
1721 fhandler_pty_master::setup (bool ispty)
1722 {
1723   int res;
1724   security_descriptor sd;
1725   SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
1726
1727   tty& t = *cygwin_shared->tty[get_unit ()];
1728
1729   tcinit (&t, true);            /* Set termios information.  Force initialization. */
1730
1731   const char *errstr = NULL;
1732   DWORD pipe_mode = PIPE_NOWAIT;
1733
1734   /* Create communication pipes */
1735   char pipename[sizeof("ttyNNNN-from-master")];
1736   __small_sprintf (pipename, "tty%d-from-master", get_unit ());
1737   res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1738                                           from_master, get_output_handle (),
1739                                           128 * 1024, pipename);
1740   if (res)
1741     {
1742       errstr = "input pipe";
1743       goto err;
1744     }
1745
1746   if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
1747     termios_printf ("can't set output_handle(%p) to non-blocking mode",
1748                     get_output_handle ());
1749
1750   __small_sprintf (pipename, "tty%d-to-master", get_unit ());
1751   res = fhandler_pipe::create_selectable (ispty ? &sec_none : &sec_none_nih,
1752                                           get_io_handle (), to_master,
1753                                           128 * 1024, pipename);
1754   if (res)
1755     {
1756       errstr = "output pipe";
1757       goto err;
1758     }
1759
1760   need_nl = 0;
1761
1762   /* Create security attribute.  Default permissions are 0620. */
1763   sd.malloc (sizeof (SECURITY_DESCRIPTOR));
1764   InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION);
1765   if (!create_object_sd_from_attribute (NULL, myself->uid, myself->gid,
1766                                         S_IFCHR | S_IRUSR | S_IWUSR | S_IWGRP,
1767                                         sd))
1768     sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) sd;
1769
1770   /* Create synchronisation events */
1771
1772   if (!ispty)
1773     {
1774       if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT, &sa)))
1775         goto err;
1776       if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT, &sa)))
1777         goto err;
1778       if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT,
1779                                                &sa)))
1780         goto err;
1781     }
1782
1783   /* Carefully check that the input_available_event didn't already exist.
1784      This is a measure to make sure that the event security descriptor
1785      isn't occupied by a malicious process.  We must make sure that the
1786      event's security descriptor is what we expect it to be. */
1787   if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT,
1788                                              &sa, TRUE))
1789       || GetLastError () == ERROR_ALREADY_EXISTS)
1790     goto err;
1791
1792   char buf[MAX_PATH];
1793   errstr = shared_name (buf, OUTPUT_MUTEX, t.ntty);
1794   if (!(output_mutex = CreateMutex (&sa, FALSE, buf)))
1795     goto err;
1796
1797   errstr = shared_name (buf, INPUT_MUTEX, t.ntty);
1798   if (!(input_mutex = CreateMutex (&sa, FALSE, buf)))
1799     goto err;
1800
1801   if (ispty)
1802     {
1803       /* Create master control pipe which allows the master to duplicate
1804          the pty pipe handles to processes which deserve it. */
1805       cygthread *h;
1806       __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-tty%d-master-ctl",
1807                        &installation_key, get_unit ());
1808       master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX,
1809                                     PIPE_WAIT | PIPE_TYPE_MESSAGE
1810                                     | PIPE_READMODE_MESSAGE, 1, 4096, 4096,
1811                                     0, &sec_all_nih);
1812       if (master_ctl == INVALID_HANDLE_VALUE)
1813         {
1814           errstr = "pty master control pipe";
1815           goto err;
1816         }
1817       h = new cygthread (::pty_master_thread, 0, this, "pty_master");
1818       if (!h)
1819         {
1820           errstr = "pty master control thread";
1821           goto err;
1822         }
1823       h->zap_h ();
1824     }
1825
1826   t.from_master = from_master;
1827   t.to_master = to_master;
1828   // /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
1829   // /* screws up tty master */ ProtectHandle1INH (input_mutex, input_mutex);
1830   t.winsize.ws_col = 80;
1831   t.winsize.ws_row = 25;
1832   t.master_pid = myself->pid;
1833
1834   termios_printf ("tty%d opened - from_slave %p, to_slave %p", t.ntty,
1835                   get_io_handle (), get_output_handle ());
1836   return true;
1837
1838 err:
1839   __seterrno ();
1840   close_maybe (get_io_handle ());
1841   close_maybe (get_output_handle ());
1842   close_maybe (output_done_event);
1843   close_maybe (ioctl_done_event);
1844   close_maybe (ioctl_request_event);
1845   close_maybe (input_available_event);
1846   close_maybe (output_mutex);
1847   close_maybe (input_mutex);
1848   close_maybe (from_master);
1849   close_maybe (to_master);
1850   close_maybe (master_ctl);
1851   termios_printf ("tty%d open failed - failed to create %s", errstr);
1852   return false;
1853 }
1854
1855 void
1856 fhandler_pty_master::fixup_after_fork (HANDLE parent)
1857 {
1858   DWORD wpid = GetCurrentProcessId ();
1859   fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1860   if (arch->dwProcessId != wpid)
1861     {
1862       tty& t = *get_ttyp ();
1863       if (!DuplicateHandle (parent, arch->from_master, GetCurrentProcess (),
1864                             &arch->from_master, 0, false, DUPLICATE_SAME_ACCESS))
1865         system_printf ("couldn't duplicate from_parent(%p), %E", arch->from_master);
1866       if (!DuplicateHandle (parent, arch->to_master, GetCurrentProcess (),
1867                             &arch->to_master, 0, false, DUPLICATE_SAME_ACCESS))
1868         system_printf ("couldn't duplicate to_parent(%p), %E", arch->from_master);
1869       if (myself->pid == t.master_pid)
1870         {
1871           t.from_master = arch->from_master;
1872           t.to_master = arch->to_master;
1873         }
1874       arch->dwProcessId = wpid;
1875     }
1876   from_master = arch->from_master;
1877   to_master = arch->to_master;
1878   report_tty_counts (this, "inherited master", "");
1879 }
1880
1881 void
1882 fhandler_pty_master::fixup_after_exec ()
1883 {
1884   if (!close_on_exec ())
1885     fixup_after_fork (spawn_info->parent);
1886   else
1887     from_master = to_master = NULL;
1888 }