OSDN Git Service

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