]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/fhandler_tty.cc
Remove unneeded header files from source files throughout.
[newlib-cygwin.git] / winsup / cygwin / fhandler_tty.cc
CommitLineData
1fd5e000
CF
1/* fhandler_tty.cc
2
90430595 3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
a7d2cc16 4 2006, 2007, 2008 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
4c8d72de 12#include "winsup.h"
1fd5e000 13#include <stdlib.h>
6258d96a 14#include <cygwin/kd.h>
bccd5e0d 15#include "cygerrno.h"
6b91b8d5 16#include "security.h"
47063f00 17#include "path.h"
7ac61736 18#include "fhandler.h"
e2ebe117 19#include "dtable.h"
bccd5e0d 20#include "sigproc.h"
84cf3d22 21#include "pinfo.h"
b0e82b74 22#include "cygheap.h"
29ac7f89 23#include "shared_info.h"
e217832c 24#include "cygserver.h"
b6bd7037 25#include "cygthread.h"
3378bdfc 26#include "child_info.h"
1fd5e000 27
3378bdfc 28/* tty master stuff */
1fd5e000
CF
29
30fhandler_tty_master NO_COPY *tty_master;
31
32static DWORD WINAPI process_input (void *); // Input queue thread
33static DWORD WINAPI process_output (void *); // Output queue thread
34static DWORD WINAPI process_ioctl (void *); // Ioctl requests thread
35
7ac61736
CF
36fhandler_tty_master::fhandler_tty_master ()
37 : fhandler_pty_master (), console (NULL)
38{
39}
40
41int
42fhandler_tty_slave::get_unit ()
1fd5e000 43{
7ac61736 44 return dev () == FH_TTY ? myself->ctty : dev ().minor;
1fd5e000
CF
45}
46
66dcfc44
CF
47void
48fhandler_tty_master::set_winsize (bool sendSIGWINCH)
49{
50 winsize w;
51 console->ioctl (TIOCGWINSZ, &w);
52 get_ttyp ()->winsize = w;
53 if (sendSIGWINCH)
54 tc->kill_pgrp (SIGWINCH);
55}
56
1fd5e000 57int
7ac61736 58fhandler_tty_master::init ()
1fd5e000 59{
0e1ba888 60 termios_printf ("Creating master for tty%d", get_unit ());
1fd5e000
CF
61
62 if (init_console ())
63 {
64 termios_printf ("can't create fhandler");
65 return -1;
66 }
67
68 termios ti;
69 memset (&ti, 0, sizeof (ti));
70 console->tcsetattr (0, &ti);
71
c76ca047 72 if (!setup (false))
3378bdfc 73 return 1;
1fd5e000 74
66dcfc44
CF
75 set_winsize (false);
76
1df3fbe2 77 set_close_on_exec (true);
78ace8a7 78
b6bd7037 79 cygthread *h;
267e201d 80 h = new cygthread (process_input, 0, cygself, "ttyin");
c4ec64d7
CF
81 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
82 h->zap_h ();
1fd5e000 83
267e201d 84 h = new cygthread (process_ioctl, 0, cygself, "ttyioctl");
c4ec64d7
CF
85 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
86 h->zap_h ();
1fd5e000 87
267e201d 88 h = new cygthread (process_output, 0, cygself, "ttyout");
c4ec64d7
CF
89 h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
90 h->zap_h ();
1fd5e000
CF
91
92 return 0;
93}
94
95#ifdef DEBUGGING
96static class mutex_stack
97{
98public:
99 const char *fn;
100 int ln;
101 const char *tname;
102} ostack[100];
103
08b78edf 104static int osi;
1fd5e000
CF
105#endif /*DEBUGGING*/
106
107DWORD
108fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
109 DWORD ms)
110{
5d970405 111 if (strace.active ())
20d7f758 112 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: waiting %d ms", ln, ms);
1fd5e000
CF
113 DWORD res = WaitForSingleObject (output_mutex, ms);
114 if (res == WAIT_OBJECT_0)
115 {
af1dc7cc 116#ifndef DEBUGGING
b0cc1689 117 if (strace.active ())
20d7f758 118 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex: acquired", ln, res);
af1dc7cc 119#else
1fd5e000
CF
120 ostack[osi].fn = fn;
121 ostack[osi].ln = ln;
b6bd7037 122 ostack[osi].tname = cygthread::name ();
1fd5e000
CF
123 termios_printf ("acquired for %s:%d, osi %d", fn, ln, osi);
124 osi++;
125#endif
126 }
1fd5e000
CF
127 return res;
128}
129
130void
131fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
132{
133 if (ReleaseMutex (output_mutex))
134 {
af1dc7cc 135#ifndef DEBUGGING
b0cc1689 136 if (strace.active ())
20d7f758 137 strace.prntf (_STRACE_TERMIOS, fn, "(%d): tty output_mutex released", ln);
af1dc7cc 138#else
1fd5e000
CF
139 if (osi > 0)
140 osi--;
141 termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
2116a175 142 termios_printf (" for %s:%d (%s)", ostack[osi].fn, ostack[osi].ln, ostack[osi].tname);
1fd5e000
CF
143 ostack[osi].ln = -ln;
144#endif
145 }
6813f009
CF
146#ifdef DEBUGGING
147 else if (osi > 0)
148 {
149 system_printf ("couldn't release output mutex but we seem to own it, %E");
150 try_to_debug ();
151 }
152#endif
1fd5e000
CF
153}
154
1fd5e000
CF
155/* Process tty input. */
156
157void
158fhandler_pty_master::doecho (const void *str, DWORD len)
159{
160 acquire_output_mutex (INFINITE);
578e142a
CF
161 if (!WriteFile (to_master, str, len, &len, NULL))
162 termios_printf ("Write to %p failed, %E", to_master);
1fd5e000
CF
163// WaitForSingleObject (output_done_event, INFINITE);
164 release_output_mutex ();
165}
166
167int
168fhandler_pty_master::accept_input ()
169{
b2be3149
CF
170 DWORD bytes_left;
171 int ret = 1;
306c4b67 172
0c55f6ed 173 WaitForSingleObject (input_mutex, INFINITE);
1fd5e000 174
b2be3149 175 bytes_left = eat_readahead (-1);
1fd5e000 176
b2be3149 177 if (!bytes_left)
1fd5e000 178 {
b2be3149
CF
179 termios_printf ("sending EOF to slave");
180 get_ttyp ()->read_retval = 0;
181 }
182 else
183 {
184 char *p = rabuf;
185 DWORD rc;
186 DWORD written = 0;
4f96ae69 187
b2be3149
CF
188 termios_printf ("about to write %d chars to slave", bytes_left);
189 rc = WriteFile (get_output_handle (), p, bytes_left, &written, NULL);
190 if (!rc)
191 {
192 debug_printf ("error writing to pipe %E");
193 get_ttyp ()->read_retval = -1;
388aa994 194 ret = -1;
b2be3149
CF
195 }
196 else
197 {
198 get_ttyp ()->read_retval = 1;
a069f560
ED
199 p += written;
200 bytes_left -= written;
201 if (bytes_left > 0)
202 {
203 debug_printf ("to_slave pipe is full");
b2be3149
CF
204 puts_readahead (p, bytes_left);
205 ret = 0;
a069f560
ED
206 }
207 }
1fd5e000 208 }
b2be3149 209
306c4b67
ED
210 SetEvent (input_available_event);
211 ReleaseMutex (input_mutex);
b2be3149 212 return ret;
1fd5e000
CF
213}
214
215static DWORD WINAPI
9cec3d45 216process_input (void *)
1fd5e000
CF
217{
218 char rawbuf[INP_BUFFER_SIZE];
219
220 while (1)
221 {
8bce0d72
CF
222 size_t nraw = INP_BUFFER_SIZE;
223 tty_master->console->read ((void *) rawbuf, nraw);
7a44ba05
CF
224 if (tty_master->line_edit (rawbuf, nraw, tty_master->get_ttyp ()->ti)
225 == line_edit_signalled)
226 tty_master->console->eat_readahead (-1);
1fd5e000
CF
227 }
228}
229
35f879a6 230bool
1fd5e000
CF
231fhandler_pty_master::hit_eof ()
232{
233 if (get_ttyp ()->was_opened && !get_ttyp ()->slave_alive ())
234 {
235 /* We have the only remaining open handle to this pty, and
236 the slave pty has been opened at least once. We treat
237 this as EOF. */
238 termios_printf ("all other handles closed");
239 return 1;
240 }
241 return 0;
242}
243
244/* Process tty output requests */
245
246int
3f0b4935 247fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on)
1fd5e000
CF
248{
249 size_t rlen;
3f0b4935 250 char outbuf[OUT_BUFFER_SIZE + 1];
1fd5e000
CF
251 DWORD n;
252 int column = 0;
774ea162 253 int rc = 0;
1fd5e000
CF
254
255 if (len == 0)
774ea162 256 goto out;
1fd5e000 257
3f0b4935 258 if (need_nl)
1fd5e000 259 {
3f0b4935
CF
260 /* We need to return a left over \n character, resulting from
261 \r\n conversion. Note that we already checked for FLUSHO and
b98ebf54 262 output_stopped at the time that we read the character, so we
3f0b4935 263 don't check again here. */
41946df6
CV
264 if (buf)
265 buf[0] = '\n';
3f0b4935 266 need_nl = 0;
14323f6a 267 rc = 1;
3f0b4935
CF
268 goto out;
269 }
1fd5e000 270
3f0b4935
CF
271
272 for (;;)
273 {
774ea162
CF
274 /* Set RLEN to the number of bytes to read from the pipe. */
275 rlen = len;
276 if (get_ttyp ()->ti.c_oflag & OPOST && get_ttyp ()->ti.c_oflag & ONLCR)
277 {
278 /* We are going to expand \n to \r\n, so don't read more than
279 half of the number of bytes requested. */
280 rlen /= 2;
281 if (rlen == 0)
282 rlen = 1;
283 }
284 if (rlen > sizeof outbuf)
285 rlen = sizeof outbuf;
1fd5e000 286
774ea162 287 HANDLE handle = get_io_handle ();
1fd5e000 288
3f0b4935
CF
289 n = 0; // get_readahead_into_buffer (outbuf, len);
290 if (!n)
1fd5e000 291 {
3f0b4935
CF
292 /* Doing a busy wait like this is quite inefficient, but nothing
293 else seems to work completely. Windows should provide some sort
294 of overlapped I/O for pipes, or something, but it doesn't. */
295 while (1)
296 {
297 if (!PeekNamedPipe (handle, NULL, 0, NULL, &n, NULL))
298 goto err;
299 if (n > 0)
300 break;
301 if (hit_eof ())
302 goto out;
41946df6
CV
303 /* DISCARD (FLUSHO) and tcflush can finish here. */
304 if (n == 0 && (get_ttyp ()->ti.c_lflag & FLUSHO || !buf))
e3778517 305 goto out;
5fd12fb0 306 if (n == 0 && is_nonblocking ())
3f0b4935
CF
307 {
308 set_errno (EAGAIN);
309 rc = -1;
310 break;
311 }
312
b263d1d8 313 Sleep (10);
3f0b4935
CF
314 }
315
316 if (ReadFile (handle, outbuf, rlen, &n, NULL) == FALSE)
774ea162 317 goto err;
1fd5e000 318 }
1fd5e000 319
3f0b4935 320 termios_printf ("bytes read %u", n);
29ac7f89
CF
321 get_ttyp ()->write_error = 0;
322 if (output_done_event != NULL)
323 SetEvent (output_done_event);
1fd5e000 324
41946df6 325 if (get_ttyp ()->ti.c_lflag & FLUSHO || !buf)
29ac7f89 326 continue;
1fd5e000 327
3f0b4935
CF
328 char *optr;
329 optr = buf;
330 if (pktmode_on)
331 *optr++ = TIOCPKT_DATA;
332
774ea162 333 if (!(get_ttyp ()->ti.c_oflag & OPOST)) // post-process output
1fd5e000 334 {
3f0b4935
CF
335 memcpy (optr, outbuf, n);
336 optr += n;
774ea162
CF
337 }
338 else // raw output mode
339 {
3f0b4935 340 char *iptr = outbuf;
774ea162
CF
341
342 while (n--)
1fd5e000 343 {
774ea162 344 switch (*iptr)
1fd5e000 345 {
774ea162
CF
346 case '\r':
347 if ((get_ttyp ()->ti.c_oflag & ONOCR) && column == 0)
348 {
349 iptr++;
350 continue;
351 }
352 if (get_ttyp ()->ti.c_oflag & OCRNL)
353 *iptr = '\n';
354 else
355 column = 0;
356 break;
357 case '\n':
358 if (get_ttyp ()->ti.c_oflag & ONLCR)
359 {
360 *optr++ = '\r';
361 column = 0;
362 }
363 if (get_ttyp ()->ti.c_oflag & ONLRET)
364 column = 0;
365 break;
366 default:
367 column++;
368 break;
1fd5e000 369 }
774ea162
CF
370
371 /* Don't store data past the end of the user's buffer. This
372 can happen if the user requests a read of 1 byte when
373 doing \r\n expansion. */
374 if (optr - buf >= (int) len)
1fd5e000 375 {
774ea162
CF
376 if (*iptr != '\n' || n != 0)
377 system_printf ("internal error: %d unexpected characters", n);
3f0b4935 378 need_nl = 1;
774ea162 379 break;
1fd5e000 380 }
1fd5e000 381
774ea162 382 *optr++ = *iptr++;
1fd5e000 383 }
774ea162 384 }
3f0b4935 385 rc = optr - buf;
774ea162 386 break;
1fd5e000 387
774ea162
CF
388 err:
389 if (GetLastError () == ERROR_BROKEN_PIPE)
390 rc = 0;
391 else
392 {
393 __seterrno ();
394 rc = -1;
1fd5e000 395 }
774ea162 396 break;
1fd5e000 397 }
774ea162
CF
398
399out:
400 termios_printf ("returning %d", rc);
401 return rc;
1fd5e000
CF
402}
403
404static DWORD WINAPI
c4ec64d7 405process_output (void *)
1fd5e000 406{
c4ec64d7 407 char buf[OUT_BUFFER_SIZE * 2];
1fd5e000 408
3f0b4935 409 for (;;)
1fd5e000 410 {
3f0b4935 411 int n = tty_master->process_slave_output (buf, OUT_BUFFER_SIZE, 0);
6b2a9a2f 412 if (n <= 0)
1fd5e000 413 {
6b2a9a2f
CF
414 if (n < 0)
415 termios_printf ("ReadFile %E");
c4ec64d7 416 ExitThread (0);
1fd5e000
CF
417 }
418 n = tty_master->console->write ((void *) buf, (size_t) n);
29ac7f89 419 tty_master->get_ttyp ()->write_error = n == -1 ? get_errno () : 0;
1fd5e000
CF
420 }
421}
422
423
424/* Process tty ioctl requests */
425
426static DWORD WINAPI
9cec3d45 427process_ioctl (void *)
1fd5e000
CF
428{
429 while (1)
430 {
431 WaitForSingleObject (tty_master->ioctl_request_event, INFINITE);
432 termios_printf ("ioctl() request");
6258d96a
CV
433 tty *ttyp = tty_master->get_ttyp ();
434 ttyp->ioctl_retval =
435 tty_master->console->ioctl (ttyp->cmd,
436 (ttyp->cmd == KDSKBMETA)
437 ? (void *) ttyp->arg.value
438 : (void *) &ttyp->arg);
1fd5e000
CF
439 SetEvent (tty_master->ioctl_done_event);
440 }
441}
442
443/**********************************************************************/
444/* Tty slave stuff */
445
0476bae5 446fhandler_tty_slave::fhandler_tty_slave ()
3378bdfc 447 : fhandler_tty_common (), inuse (NULL)
1fd5e000 448{
56551a9b 449 uninterruptible_io (true);
1fd5e000
CF
450}
451
f3ea62a8
CF
452/* FIXME: This function needs to close handles when it has
453 a failing condition. */
1fd5e000 454int
7ac61736 455fhandler_tty_slave::open (int flags, mode_t)
1fd5e000 456{
8e10c431 457 if (get_device () == FH_TTY)
c76ca047 458 dev().tty_to_real_device ();
5a0826c3 459 fhandler_tty_slave *arch = (fhandler_tty_slave *) cygheap->fdtab.find_archetype (pc.dev);
8e10c431 460 if (arch)
2e008fb9 461 {
8e10c431 462 *this = *(fhandler_tty_slave *) arch;
3378bdfc 463 termios_printf ("copied fhandler_tty_slave archetype");
0544d116 464 set_flags ((flags & ~O_TEXT) | O_BINARY);
59297e04 465 cygheap->manage_console_count ("fhandler_tty_slave::open<arch>", 1);
8e10c431 466 goto out;
2e008fb9
CF
467 }
468
7ac61736 469 tcinit (cygwin_shared->tty[get_unit ()]);
1fd5e000 470
71d59a92 471 cygwin_shared->tty.attach (get_unit ());
1fd5e000 472
1bc9effd 473 set_flags ((flags & ~O_TEXT) | O_BINARY);
1fd5e000 474 /* Create synchronisation events */
27114d3a 475 char buf[MAX_PATH];
1fd5e000
CF
476
477 /* output_done_event may or may not exist. It will exist if the tty
478 was opened by fhandler_tty_master::init, normally called at
479 startup if use_tty is non-zero. It will not exist if this is a
480 pty opened by fhandler_pty_master::open. In the former case, tty
481 output is handled by a separate thread which controls output. */
8bdfa78a 482 shared_name (buf, OUTPUT_DONE_EVENT, get_unit ());
1fd5e000
CF
483 output_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
484
e62ac9e8 485 if (!(output_mutex = get_ttyp ()->open_output_mutex ()))
1fd5e000
CF
486 {
487 termios_printf ("open output mutex failed, %E");
488 __seterrno ();
489 return 0;
490 }
e62ac9e8 491 if (!(input_mutex = get_ttyp ()->open_input_mutex ()))
306c4b67
ED
492 {
493 termios_printf ("open input mutex failed, %E");
494 __seterrno ();
495 return 0;
496 }
8bdfa78a 497 shared_name (buf, INPUT_AVAILABLE_EVENT, get_unit ());
306c4b67
ED
498 if (!(input_available_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf)))
499 {
500 termios_printf ("open input event failed, %E");
501 __seterrno ();
502 return 0;
503 }
1fd5e000
CF
504
505 /* The ioctl events may or may not exist. See output_done_event,
506 above. */
8bdfa78a 507 shared_name (buf, IOCTL_REQUEST_EVENT, get_unit ());
1fd5e000 508 ioctl_request_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
8bdfa78a 509 shared_name (buf, IOCTL_DONE_EVENT, get_unit ());
1fd5e000
CF
510 ioctl_done_event = OpenEvent (EVENT_ALL_ACCESS, TRUE, buf);
511
512 /* FIXME: Needs a method to eliminate tty races */
513 {
514 acquire_output_mutex (500);
2496a363 515 inuse = get_ttyp ()->create_inuse (TTY_SLAVE_ALIVE);
2e008fb9 516 get_ttyp ()->was_opened = true;
1fd5e000
CF
517 release_output_mutex ();
518 }
519
3378bdfc 520 if (!get_ttyp ()->from_master || !get_ttyp ()->to_master)
1fd5e000
CF
521 {
522 termios_printf ("tty handles have been closed");
523 set_errno (EACCES);
524 return 0;
525 }
526
8e10c431
CF
527 HANDLE from_master_local;
528 HANDLE to_master_local;
529 from_master_local = to_master_local = NULL;
1fd5e000 530
4392d36c 531#ifdef USE_SERVER
a76877e9 532 if (cygserver_running == CYGSERVER_UNAVAIL
3d8a75bd 533 || !cygserver_attach_tty (&from_master_local, &to_master_local))
3872e9a4 534#endif
1fd5e000 535 {
71d59a92
CF
536 if (get_ttyp ()->master_pid < 0)
537 {
538 set_errno (EAGAIN);
539 termios_printf ("*** master is closed");
540 return 0;
541 }
3378bdfc
CF
542 pinfo p (get_ttyp ()->master_pid);
543 if (!p)
544 {
545 set_errno (EAGAIN);
546 termios_printf ("*** couldn't find tty master");
547 return 0;
548 }
e217832c 549#ifdef USE_SERVER
f449bfef 550 termios_printf ("cannot dup handles via server. using old method.");
e217832c 551#endif
f449bfef 552 HANDLE tty_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
3378bdfc 553 p->dwProcessId);
f449bfef 554 if (tty_owner == NULL)
2402700d
CF
555 {
556 termios_printf ("can't open tty (%d) handle process %d",
7ac61736 557 get_unit (), get_ttyp ()->master_pid);
2402700d
CF
558 __seterrno ();
559 return 0;
560 }
561
562 if (!DuplicateHandle (tty_owner, get_ttyp ()->from_master,
563 hMainProc, &from_master_local, 0, TRUE,
f449bfef 564 DUPLICATE_SAME_ACCESS))
2402700d
CF
565 {
566 termios_printf ("can't duplicate input, %E");
567 __seterrno ();
568 return 0;
569 }
f449bfef 570
f7239090 571 VerifyHandle (from_master_local);
2402700d 572 if (!DuplicateHandle (tty_owner, get_ttyp ()->to_master,
f449bfef
RC
573 hMainProc, &to_master_local, 0, TRUE,
574 DUPLICATE_SAME_ACCESS))
2402700d
CF
575 {
576 termios_printf ("can't duplicate output, %E");
577 __seterrno ();
578 return 0;
579 }
f7239090 580 VerifyHandle (to_master_local);
f449bfef 581 CloseHandle (tty_owner);
1fd5e000 582 }
f449bfef
RC
583
584 termios_printf ("duplicated from_master %p->%p from tty_owner",
578e142a 585 get_ttyp ()->from_master, from_master_local);
f449bfef 586 termios_printf ("duplicated to_master %p->%p from tty_owner",
578e142a 587 get_ttyp ()->to_master, to_master_local);
f449bfef
RC
588
589 set_io_handle (from_master_local);
f449bfef 590 set_output_handle (to_master_local);
1fd5e000 591
f3ea62a8 592 set_open_status ();
3b26b6a2
CF
593 if (cygheap->manage_console_count ("fhandler_tty_slave::open", 1) == 1
594 && !output_done_event)
595 fhandler_console::need_invisible ();
8e10c431
CF
596
597 // FIXME: Do this better someday
ee4388c4 598 arch = (fhandler_tty_slave *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
8e10c431
CF
599 *((fhandler_tty_slave **) cygheap->fdtab.add_archetype ()) = arch;
600 archetype = arch;
601 *arch = *this;
602
603out:
604 usecount = 0;
3378bdfc 605 arch->usecount++;
59297e04 606 report_tty_counts (this, "opened", "");
8e10c431 607 myself->set_ctty (get_ttyp (), flags, arch);
1fd5e000
CF
608
609 return 1;
610}
611
c418817e
CF
612int
613fhandler_tty_slave::close ()
614{
6118c524
CF
615 /* This used to always call fhandler_tty_common::close when hExeced but that
616 caused multiple closes of the handles associated with this tty. Since
617 close_all_files is not called until after the cygwin process has synced
618 or before a non-cygwin process has exited, it should be safe to just
619 close this normally. cgf 2006-05-20 */
620 cygheap->manage_console_count ("fhandler_tty_slave::close", -1);
e9737793 621
6118c524
CF
622 archetype->usecount--;
623 report_tty_counts (this, "closed", "");
e9737793 624
6118c524
CF
625 if (archetype->usecount)
626 {
9279515a 627#ifdef DEBUGGING
6118c524
CF
628 if (archetype->usecount < 0)
629 system_printf ("error: usecount %d", archetype->usecount);
9279515a 630#endif
6118c524
CF
631 termios_printf ("just returning because archetype usecount is != 0");
632 return 0;
8e10c431
CF
633 }
634
8ed5c9b6 635 termios_printf ("closing last open %s handle", ttyname ());
3378bdfc
CF
636 if (inuse && !CloseHandle (inuse))
637 termios_printf ("CloseHandle (inuse), %E");
9279515a 638 return fhandler_tty_common::close ();
c418817e
CF
639}
640
f449bfef
RC
641int
642fhandler_tty_slave::cygserver_attach_tty (LPHANDLE from_master_ptr,
2402700d 643 LPHANDLE to_master_ptr)
f449bfef 644{
4392d36c 645#ifndef USE_SERVER
3d8a75bd
CF
646 return 0;
647#else
f449bfef
RC
648 if (!from_master_ptr || !to_master_ptr)
649 return 0;
650
1c001dd2
CS
651 client_request_attach_tty req ((DWORD) get_ttyp ()->master_pid,
652 (HANDLE) get_ttyp ()->from_master,
653 (HANDLE) get_ttyp ()->to_master);
f449bfef 654
1c001dd2 655 if (req.make_request () == -1 || req.error_code ())
f449bfef
RC
656 return 0;
657
1c001dd2
CS
658 *from_master_ptr = req.from_master ();
659 *to_master_ptr = req.to_master ();
3872e9a4 660
f449bfef 661 return 1;
3d8a75bd 662#endif
f449bfef
RC
663}
664
1fd5e000 665void
9cec3d45 666fhandler_tty_slave::init (HANDLE, DWORD a, mode_t)
1fd5e000 667{
7ac61736 668 int flags = 0;
1fd5e000
CF
669
670 a &= GENERIC_READ | GENERIC_WRITE;
671 if (a == GENERIC_READ)
7ac61736 672 flags = O_RDONLY;
1fd5e000 673 if (a == GENERIC_WRITE)
7ac61736 674 flags = O_WRONLY;
1fd5e000 675 if (a == (GENERIC_READ | GENERIC_WRITE))
7ac61736 676 flags = O_RDWR;
1fd5e000 677
7ac61736 678 open (flags);
1fd5e000
CF
679}
680
681int
682fhandler_tty_slave::write (const void *ptr, size_t len)
683{
684 DWORD n, towrite = len;
685
7ac61736 686 termios_printf ("tty%d, write(%x, %d)", get_unit (), ptr, len);
1fd5e000
CF
687
688 acquire_output_mutex (INFINITE);
689
690 while (len)
691 {
692 n = min (OUT_BUFFER_SIZE, len);
693 char *buf = (char *)ptr;
694 ptr = (char *) ptr + n;
695 len -= n;
696
29ac7f89
CF
697 /* Previous write may have set write_error to != 0. Check it here.
698 This is less than optimal, but the alternative slows down tty
699 writes enormously. */
700 if (get_ttyp ()->write_error)
701 {
702 set_errno (get_ttyp ()->write_error);
703 towrite = (DWORD) -1;
704 break;
705 }
706
1fd5e000
CF
707 if (WriteFile (get_output_handle (), buf, n, &n, NULL) == FALSE)
708 {
d824bcf9 709 DWORD err = GetLastError ();
1fd5e000 710 termios_printf ("WriteFile failed, %E");
d824bcf9
CF
711 switch (err)
712 {
713 case ERROR_NO_DATA:
714 err = ERROR_IO_DEVICE;
715 default:
a3ad8241 716 __seterrno_from_win_error (err);
d824bcf9 717 }
d25c187f 718 raise (SIGHUP); /* FIXME: Should this be SIGTTOU? */
d824bcf9 719 towrite = (DWORD) -1;
1fd5e000
CF
720 break;
721 }
722
723 if (output_done_event != NULL)
724 {
774ea162
CF
725 DWORD rc;
726 DWORD x = n * 1000;
727 rc = WaitForSingleObject (output_done_event, x);
2116a175 728 termios_printf ("waited %d ms for output_done_event, WFSO %d", x, rc);
1fd5e000 729 }
1fd5e000
CF
730 }
731 release_output_mutex ();
732 return towrite;
733}
734
8bce0d72
CF
735void __stdcall
736fhandler_tty_slave::read (void *ptr, size_t& len)
1fd5e000 737{
1fd5e000 738 int totalread = 0;
207daf0f 739 int vmin = 0;
1fd5e000 740 int vtime = 0; /* Initialized to prevent -Wuninitialized warning */
306c4b67
ED
741 size_t readlen;
742 DWORD bytes_in_pipe;
1fd5e000 743 char buf[INP_BUFFER_SIZE];
5e8e21d9 744 char peek_buf[INP_BUFFER_SIZE];
306c4b67
ED
745 DWORD time_to_wait;
746 DWORD rc;
747 HANDLE w4[2];
1fd5e000 748
f449bfef 749 termios_printf ("read(%x, %d) handle %p", ptr, len, get_handle ());
1fd5e000 750
41946df6
CV
751 if (!ptr) /* Indicating tcflush(). */
752 time_to_wait = 0;
753 else if ((get_ttyp ()->ti.c_lflag & ICANON))
207daf0f
CF
754 time_to_wait = INFINITE;
755 else
1fd5e000 756 {
2701126a
CF
757 vmin = get_ttyp ()->ti.c_cc[VMIN];
758 if (vmin > INP_BUFFER_SIZE)
759 vmin = INP_BUFFER_SIZE;
1fd5e000 760 vtime = get_ttyp ()->ti.c_cc[VTIME];
7a1174dc
CF
761 if (vmin < 0)
762 vmin = 0;
763 if (vtime < 0)
764 vtime = 0;
207daf0f
CF
765 if (!vmin && !vtime)
766 time_to_wait = 0;
767 else
768 time_to_wait = !vtime ? INFINITE : 100 * vtime;
1fd5e000 769 }
306c4b67
ED
770
771 w4[0] = signal_arrived;
772 w4[1] = input_available_event;
1fd5e000 773
b9cd8fb5 774 DWORD waiter = time_to_wait;
1fd5e000
CF
775 while (len)
776 {
207daf0f
CF
777 rc = WaitForMultipleObjects (2, w4, FALSE, waiter);
778
779 if (rc == WAIT_TIMEOUT)
8cb359d9
CF
780 {
781 termios_printf ("wait timed out, waiter %u", waiter);
782 break;
783 }
207daf0f
CF
784
785 if (rc == WAIT_FAILED)
786 {
787 termios_printf ("wait for input event failed, %E");
788 break;
789 }
790
306c4b67 791 if (rc == WAIT_OBJECT_0)
2116a175 792 {
ed4c976c 793 /* if we've received signal after successfully reading some data,
2116a175
CF
794 just return all data successfully read */
795 if (totalread > 0)
796 break;
797 set_sig_errno (EINTR);
6cce721b 798 len = (size_t) -1;
8bce0d72 799 return;
2116a175 800 }
207daf0f 801
306c4b67
ED
802 rc = WaitForSingleObject (input_mutex, 1000);
803 if (rc == WAIT_FAILED)
2116a175
CF
804 {
805 termios_printf ("wait for input mutex failed, %E");
806 break;
807 }
306c4b67 808 else if (rc == WAIT_TIMEOUT)
2116a175
CF
809 {
810 termios_printf ("failed to acquire input mutex after input event arrived");
811 break;
812 }
c90e1cf1 813 if (!PeekNamedPipe (get_handle (), peek_buf, sizeof (peek_buf), &bytes_in_pipe, NULL, NULL))
1fd5e000 814 {
306c4b67 815 termios_printf ("PeekNamedPipe failed, %E");
d25c187f 816 raise (SIGHUP);
2116a175 817 bytes_in_pipe = 0;
1fd5e000 818 }
207daf0f 819
41946df6
CV
820 /* On first peek determine no. of bytes to flush. */
821 if (!ptr && len == UINT_MAX)
e3778517 822 len = (size_t) bytes_in_pipe;
41946df6 823
b9b1b383 824 if (ptr && !bytes_in_pipe && !vmin && !time_to_wait)
207daf0f
CF
825 {
826 ReleaseMutex (input_mutex);
bd893898 827 len = (size_t) bytes_in_pipe;
8bce0d72 828 return;
207daf0f
CF
829 }
830
306c4b67 831 readlen = min (bytes_in_pipe, min (len, sizeof (buf)));
207daf0f 832
41946df6 833 if (ptr && vmin && readlen > (unsigned) vmin)
207daf0f
CF
834 readlen = vmin;
835
836 DWORD n = 0;
2116a175
CF
837 if (readlen)
838 {
839 termios_printf ("reading %d bytes (vtime %d)", readlen, vtime);
840 if (ReadFile (get_handle (), buf, readlen, &n, NULL) == FALSE)
841 {
306c4b67 842 termios_printf ("read failed, %E");
d25c187f 843 raise (SIGHUP);
306c4b67 844 }
1ff9f4b9
CF
845 /* MSDN states that 5th prameter can be used to determine total
846 number of bytes in pipe, but for some reason this number doesn't
847 change after successful read. So we have to peek into the pipe
848 again to see if input is still available */
849 if (!PeekNamedPipe (get_handle (), peek_buf, 1, &bytes_in_pipe, NULL, NULL))
5e8e21d9
ED
850 {
851 termios_printf ("PeekNamedPipe failed, %E");
d25c187f 852 raise (SIGHUP);
5e8e21d9
ED
853 bytes_in_pipe = 0;
854 }
2116a175
CF
855 if (n)
856 {
857 len -= n;
858 totalread += n;
41946df6 859 if (ptr)
e3778517 860 {
41946df6
CV
861 memcpy (ptr, buf, n);
862 ptr = (char *) ptr + n;
863 }
2116a175
CF
864 }
865 }
306c4b67 866
5e8e21d9
ED
867 if (!bytes_in_pipe)
868 ResetEvent (input_available_event);
306c4b67
ED
869
870 ReleaseMutex (input_mutex);
3f0b4935 871
41946df6
CV
872 if (!ptr)
873 {
874 if (!bytes_in_pipe)
875 break;
876 continue;
e3778517 877 }
41946df6 878
1fd5e000
CF
879 if (get_ttyp ()->read_retval < 0) // read error
880 {
881 set_errno (-get_ttyp ()->read_retval);
882 totalread = -1;
883 break;
884 }
885 if (get_ttyp ()->read_retval == 0) //EOF
886 {
887 termios_printf ("saw EOF");
888 break;
889 }
5fd12fb0 890 if (get_ttyp ()->ti.c_lflag & ICANON || is_nonblocking ())
1fd5e000 891 break;
207daf0f 892 if (vmin && totalread >= vmin)
2116a175 893 break;
306c4b67 894
2116a175 895 /* vmin == 0 && vtime == 0:
306c4b67
ED
896 * we've already read all input, if any, so return immediately
897 * vmin == 0 && vtime > 0:
898 * we've waited for input 10*vtime ms in WFSO(input_available_event),
899 * no matter whether any input arrived, we shouldn't wait any longer,
2116a175 900 * so return immediately
306c4b67
ED
901 * vmin > 0 && vtime == 0:
902 * here, totalread < vmin, so continue waiting until more data
903 * arrive
904 * vmin > 0 && vtime > 0:
905 * similar to the previous here, totalread < vmin, and timer
906 * hadn't expired -- WFSO(input_available_event) != WAIT_TIMEOUT,
907 * so "restart timer" and wait until more data arrive
908 */
909
2116a175
CF
910 if (vmin == 0)
911 break;
207daf0f
CF
912
913 if (n)
914 waiter = time_to_wait;
1fd5e000
CF
915 }
916 termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
bd893898 917 len = (size_t) totalread;
1fd5e000
CF
918}
919
c418817e 920int
dcb091ca 921fhandler_tty_slave::dup (fhandler_base *child)
c418817e 922{
8e10c431
CF
923 fhandler_tty_slave *arch = (fhandler_tty_slave *) archetype;
924 *(fhandler_tty_slave *) child = *arch;
4248960e 925 child->set_flags (get_flags ());
8e10c431 926 child->usecount = 0;
e9737793 927 arch->usecount++;
59297e04
CF
928 cygheap->manage_console_count ("fhandler_tty_slave::dup", 1);
929 report_tty_counts (child, "duped", "");
8e10c431 930 return 0;
c418817e
CF
931}
932
1fd5e000 933int
3378bdfc 934fhandler_pty_master::dup (fhandler_base *child)
1fd5e000 935{
3378bdfc
CF
936 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
937 *(fhandler_tty_master *) child = *arch;
4248960e 938 child->set_flags (get_flags ());
3378bdfc
CF
939 child->usecount = 0;
940 arch->usecount++;
941 report_tty_counts (child, "duped master", "");
1fd5e000 942 return 0;
1fd5e000
CF
943}
944
945int
946fhandler_tty_slave::tcgetattr (struct termios *t)
947{
948 *t = get_ttyp ()->ti;
949 return 0;
950}
951
952int
9cec3d45 953fhandler_tty_slave::tcsetattr (int, const struct termios *t)
1fd5e000
CF
954{
955 acquire_output_mutex (INFINITE);
956 get_ttyp ()->ti = *t;
957 release_output_mutex ();
958 return 0;
959}
960
961int
41946df6 962fhandler_tty_slave::tcflush (int queue)
1fd5e000 963{
41946df6
CV
964 int ret = 0;
965
966 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
967
968 if (queue == TCIFLUSH || queue == TCIOFLUSH)
969 {
970 size_t len = UINT_MAX;
971 read (NULL, len);
c8f07ce7 972 ret = ((int) len) >= 0 ? 0 : -1;
41946df6
CV
973 }
974 if (queue == TCOFLUSH || queue == TCIOFLUSH)
975 {
976 /* do nothing for now. */
977 }
978
979 termios_printf ("%d=tcflush(%d)", ret, queue);
980 return ret;
1fd5e000
CF
981}
982
1fd5e000
CF
983int
984fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
985{
986 termios_printf ("ioctl (%x)", cmd);
987
7a1174dc 988 if (myself->pgid && get_ttyp ()->getpgid () != myself->pgid
7ac61736 989 && myself->ctty == get_unit () && (get_ttyp ()->ti.c_lflag & TOSTOP))
1fd5e000
CF
990 {
991 /* background process */
59297e04
CF
992 termios_printf ("bg ioctl pgid %d, tpgid %d, %s", myself->pgid,
993 get_ttyp ()->getpgid (), myctty ());
d25c187f 994 raise (SIGTTOU);
1fd5e000 995 }
ad0bed74 996
e64a50ed 997 int retval;
1fd5e000
CF
998 switch (cmd)
999 {
1000 case TIOCGWINSZ:
1fd5e000 1001 case TIOCSWINSZ:
63726a5e 1002 case TIOCLINUX:
6258d96a
CV
1003 case KDGKBMETA:
1004 case KDSKBMETA:
1fd5e000
CF
1005 break;
1006 case FIONBIO:
5fd12fb0 1007 set_nonblocking (*(int *) arg);
e64a50ed 1008 retval = 0;
ad0bed74 1009 goto out;
1fd5e000
CF
1010 default:
1011 set_errno (EINVAL);
1012 return -1;
1013 }
ad0bed74
CF
1014
1015 acquire_output_mutex (INFINITE);
1016
1017 get_ttyp ()->cmd = cmd;
1018 get_ttyp ()->ioctl_retval = 0;
f62412f2 1019 int val;
ad0bed74
CF
1020 switch (cmd)
1021 {
1022 case TIOCGWINSZ:
1023 get_ttyp ()->arg.winsize = get_ttyp ()->winsize;
1024 if (ioctl_request_event)
1025 SetEvent (ioctl_request_event);
2601ab57 1026 *(struct winsize *) arg = get_ttyp ()->arg.winsize;
ad0bed74
CF
1027 if (ioctl_done_event)
1028 WaitForSingleObject (ioctl_done_event, INFINITE);
1029 get_ttyp ()->winsize = get_ttyp ()->arg.winsize;
1030 break;
1031 case TIOCSWINSZ:
2601ab57
CF
1032 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1033 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1034 {
bcb4223c
CF
1035 get_ttyp ()->arg.winsize = *(struct winsize *) arg;
1036 if (ioctl_request_event)
2601ab57 1037 {
bcb4223c 1038 get_ttyp ()->ioctl_retval = -EINVAL;
a3cbb4a7 1039 SetEvent (ioctl_request_event);
bcb4223c
CF
1040 }
1041 else
1042 {
2601ab57 1043 get_ttyp ()->winsize = *(struct winsize *) arg;
f6936c48 1044 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
2601ab57 1045 }
bcb4223c
CF
1046 if (ioctl_done_event)
1047 WaitForSingleObject (ioctl_done_event, INFINITE);
2601ab57 1048 }
ad0bed74 1049 break;
63726a5e 1050 case TIOCLINUX:
f62412f2 1051 val = *(unsigned char *) arg;
a3cbb4a7
CF
1052 if (val != 6 || !ioctl_request_event || !ioctl_done_event)
1053 get_ttyp ()->ioctl_retval = -EINVAL;
1054 else
63726a5e 1055 {
a3cbb4a7 1056 get_ttyp ()->arg.value = val;
63726a5e
CF
1057 SetEvent (ioctl_request_event);
1058 WaitForSingleObject (ioctl_done_event, INFINITE);
a3cbb4a7 1059 *(unsigned char *) arg = get_ttyp ()->arg.value & 0xFF;
63726a5e
CF
1060 }
1061 break;
6258d96a
CV
1062 case KDGKBMETA:
1063 if (ioctl_request_event)
1064 {
1065 SetEvent (ioctl_request_event);
1066 if (ioctl_done_event)
1067 WaitForSingleObject (ioctl_done_event, INFINITE);
1068 *(int *) arg = get_ttyp ()->arg.value;
1069 }
1070 else
1071 get_ttyp ()->ioctl_retval = -EINVAL;
1072 break;
1073 case KDSKBMETA:
1074 if (ioctl_request_event)
1075 {
1076 get_ttyp ()->arg.value = (int) arg;
1077 SetEvent (ioctl_request_event);
1078 if (ioctl_done_event)
1079 WaitForSingleObject (ioctl_done_event, INFINITE);
1080 }
1081 else
1082 get_ttyp ()->ioctl_retval = -EINVAL;
1083 break;
ad0bed74
CF
1084 }
1085
1086 release_output_mutex ();
e64a50ed 1087 retval = get_ttyp ()->ioctl_retval;
a3cbb4a7
CF
1088 if (retval < 0)
1089 {
1090 set_errno (-retval);
1091 retval = -1;
1092 }
e64a50ed
CF
1093
1094out:
a3cbb4a7
CF
1095 termios_printf ("%d = ioctl (%x)", retval, cmd);
1096 return retval;
1fd5e000
CF
1097}
1098
1099/*******************************************************
1100 fhandler_pty_master
1101*/
7ac61736 1102fhandler_pty_master::fhandler_pty_master ()
3378bdfc 1103 : fhandler_tty_common (), pktmode (0), need_nl (0), dwProcessId (0)
1fd5e000 1104{
1fd5e000
CF
1105}
1106
1107int
7ac61736 1108fhandler_pty_master::open (int flags, mode_t)
1fd5e000 1109{
71d59a92
CF
1110 int ntty;
1111 ntty = cygwin_shared->tty.allocate (false);
7ac61736 1112 if (ntty < 0)
1fd5e000
CF
1113 return 0;
1114
c76ca047
CF
1115 dev().devn = FHDEV (DEV_TTYM_MAJOR, ntty);
1116 if (!setup (true))
3378bdfc 1117 {
71d59a92 1118 lock_ttys::release ();
3378bdfc
CF
1119 return 0;
1120 }
71d59a92 1121 lock_ttys::release ();
1bc9effd 1122 set_flags ((flags & ~O_TEXT) | O_BINARY);
f3ea62a8 1123 set_open_status ();
3378bdfc
CF
1124 //
1125 // FIXME: Do this better someday
ee4388c4 1126 fhandler_pty_master *arch = (fhandler_tty_master *) cmalloc_abort (HEAP_ARCHETYPES, sizeof (*this));
3378bdfc
CF
1127 *((fhandler_pty_master **) cygheap->fdtab.add_archetype ()) = arch;
1128 archetype = arch;
1129 *arch = *this;
1130 arch->dwProcessId = GetCurrentProcessId ();
1fd5e000 1131
3378bdfc
CF
1132 usecount = 0;
1133 arch->usecount++;
71d59a92
CF
1134 char buf[sizeof ("opened pty master for ttyNNNNNNNNNNN")];
1135 __small_sprintf (buf, "opened pty master for tty%d", get_unit ());
1136 report_tty_counts (this, buf, "");
1fd5e000
CF
1137 return 1;
1138}
1139
4f3e6ff1
CF
1140_off64_t
1141fhandler_tty_common::lseek (_off64_t, int)
1142{
1143 set_errno (ESPIPE);
1144 return -1;
1145}
1146
1fd5e000
CF
1147int
1148fhandler_tty_common::close ()
1149{
ce40c6ba 1150 termios_printf ("tty%d <%p,%p> closing", get_unit (), get_handle (), get_output_handle ());
1fd5e000
CF
1151 if (output_done_event && !CloseHandle (output_done_event))
1152 termios_printf ("CloseHandle (output_done_event), %E");
1153 if (ioctl_done_event && !CloseHandle (ioctl_done_event))
1154 termios_printf ("CloseHandle (ioctl_done_event), %E");
1155 if (ioctl_request_event && !CloseHandle (ioctl_request_event))
1156 termios_printf ("CloseHandle (ioctl_request_event), %E");
306c4b67
ED
1157 if (!ForceCloseHandle (input_mutex))
1158 termios_printf ("CloseHandle (input_mutex<%p>), %E", input_mutex);
083abe54
CF
1159 if (!ForceCloseHandle (output_mutex))
1160 termios_printf ("CloseHandle (output_mutex<%p>), %E", output_mutex);
0d339267
CF
1161 if (!ForceCloseHandle1 (get_handle (), from_pty))
1162 termios_printf ("CloseHandle (get_handle ()<%p>), %E", get_handle ());
1163 if (!ForceCloseHandle1 (get_output_handle (), to_pty))
1164 termios_printf ("CloseHandle (get_output_handle ()<%p>), %E", get_output_handle ());
78ace8a7 1165
306c4b67
ED
1166 if (!ForceCloseHandle (input_available_event))
1167 termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event);
1fd5e000 1168
1fd5e000
CF
1169 return 0;
1170}
1171
1172int
1173fhandler_pty_master::close ()
1174{
1175#if 0
1176 while (accept_input () > 0)
1177 continue;
1178#endif
3378bdfc
CF
1179 archetype->usecount--;
1180 report_tty_counts (this, "closing master", "");
1fd5e000 1181
3378bdfc 1182 if (archetype->usecount)
1fd5e000 1183 {
3378bdfc
CF
1184#ifdef DEBUGGING
1185 if (archetype->usecount < 0)
1186 system_printf ("error: usecount %d", archetype->usecount);
92e19690 1187#endif
3378bdfc
CF
1188 termios_printf ("just returning because archetype usecount is != 0");
1189 return 0;
1190 }
0d339267 1191
3378bdfc 1192 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
313b51e6
CF
1193 termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%d)",
1194 arch->from_master, arch->to_master, arch->dwProcessId);
1195 if (!ForceCloseHandle (arch->from_master))
1196 termios_printf ("error closing from_master %p, %E", arch->from_master);
1197 if (!ForceCloseHandle (arch->to_master))
1198 termios_printf ("error closing from_master %p, %E", arch->to_master);
3378bdfc 1199 fhandler_tty_common::close ();
0d339267 1200
71d59a92
CF
1201 if (hExeced || get_ttyp ()->master_pid != myself->pid)
1202 termios_printf ("not clearing: %d, master_pid %d", hExeced, get_ttyp ()->master_pid);
1203 else
1204 get_ttyp ()->set_master_closed ();
1fd5e000
CF
1205
1206 return 0;
1207}
1208
1209int
1210fhandler_pty_master::write (const void *ptr, size_t len)
1211{
388aa994 1212 int i;
49dd6fc6 1213 char *p = (char *) ptr;
46b73ef1
CF
1214 termios ti = tc->ti;
1215
1216 for (i = 0; i < (int) len; i++)
388aa994 1217 {
46b73ef1 1218 line_edit_status status = line_edit (p++, 1, ti);
b18962e2
CF
1219 if (status > line_edit_signalled)
1220 {
1221 if (status != line_edit_pipe_full)
1222 i = -1;
1223 break;
1224 }
388aa994 1225 }
49dd6fc6 1226 return i;
1fd5e000
CF
1227}
1228
8bce0d72
CF
1229void __stdcall
1230fhandler_pty_master::read (void *ptr, size_t& len)
1fd5e000 1231{
bd893898 1232 len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
1fd5e000
CF
1233}
1234
1235int
1236fhandler_pty_master::tcgetattr (struct termios *t)
1237{
7ac61736 1238 *t = cygwin_shared->tty[get_unit ()]->ti;
1fd5e000
CF
1239 return 0;
1240}
1241
1242int
9cec3d45 1243fhandler_pty_master::tcsetattr (int, const struct termios *t)
1fd5e000 1244{
7ac61736 1245 cygwin_shared->tty[get_unit ()]->ti = *t;
1fd5e000
CF
1246 return 0;
1247}
1248
1249int
41946df6 1250fhandler_pty_master::tcflush (int queue)
1fd5e000 1251{
41946df6
CV
1252 int ret = 0;
1253
1254 termios_printf ("tcflush(%d) handle %p", queue, get_handle ());
1255
1256 if (queue == TCIFLUSH || queue == TCIOFLUSH)
1257 ret = process_slave_output (NULL, OUT_BUFFER_SIZE, 0);
1258 else if (queue == TCIFLUSH || queue == TCIOFLUSH)
1259 {
1260 /* do nothing for now. */
1261 }
1262
1263 termios_printf ("%d=tcflush(%d)", ret, queue);
1264 return ret;
1fd5e000
CF
1265}
1266
1267int
1268fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
1269{
1270 switch (cmd)
1271 {
1272 case TIOCPKT:
a3cbb4a7 1273 pktmode = *(int *) arg;
1fd5e000
CF
1274 break;
1275 case TIOCGWINSZ:
66dcfc44 1276 *(struct winsize *) arg = get_ttyp ()->winsize;
1fd5e000
CF
1277 break;
1278 case TIOCSWINSZ:
2601ab57
CF
1279 if (get_ttyp ()->winsize.ws_row != ((struct winsize *) arg)->ws_row
1280 || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col)
1281 {
a3cbb4a7 1282 get_ttyp ()->winsize = *(struct winsize *) arg;
f6936c48 1283 killsys (-get_ttyp ()->getpgid (), SIGWINCH);
2601ab57 1284 }
1fd5e000
CF
1285 break;
1286 case FIONBIO:
5fd12fb0 1287 set_nonblocking (*(int *) arg);
1fd5e000
CF
1288 break;
1289 default:
1290 set_errno (EINVAL);
1291 return -1;
1292 }
1293 return 0;
1294}
1295
1296char *
7ac61736 1297fhandler_pty_master::ptsname ()
1fd5e000 1298{
d8a5f046 1299 static char buf[TTY_NAME_MAX];
1fd5e000 1300
7ac61736 1301 __small_sprintf (buf, "/dev/tty%d", get_unit ());
1fd5e000
CF
1302 return buf;
1303}
1304
1305void
56551a9b 1306fhandler_tty_common::set_close_on_exec (bool val)
1fd5e000 1307{
3378bdfc
CF
1308 // Cygwin processes will handle this specially on exec.
1309 close_on_exec (val);
1fd5e000
CF
1310}
1311
c418817e
CF
1312void
1313fhandler_tty_slave::fixup_after_fork (HANDLE parent)
1314{
3378bdfc 1315 // fork_fixup (parent, inuse, "inuse");
8ed5c9b6 1316 // fhandler_tty_common::fixup_after_fork (parent);
59297e04 1317 report_tty_counts (this, "inherited", "");
c418817e
CF
1318}
1319
1fd5e000 1320void
3378bdfc 1321fhandler_tty_slave::fixup_after_exec ()
1fd5e000 1322{
578e142a 1323 if (!close_on_exec ())
3378bdfc 1324 fixup_after_fork (NULL);
1fd5e000
CF
1325}
1326
1fd5e000
CF
1327int
1328fhandler_tty_master::init_console ()
1329{
7ac61736 1330 console = (fhandler_console *) build_fh_dev (*console_dev, "/dev/ttym");
1fd5e000
CF
1331 if (console == NULL)
1332 return -1;
1333
1334 console->init (INVALID_HANDLE_VALUE, GENERIC_READ | GENERIC_WRITE, O_BINARY);
59297e04 1335 cygheap->manage_console_count ("fhandler_tty_master::init_console", -1, true);
56551a9b 1336 console->uninterruptible_io (true);
1fd5e000
CF
1337 return 0;
1338}
3378bdfc
CF
1339
1340#define close_maybe(h) \
1341 do { \
1342 if (h) \
1343 CloseHandle (h); \
1344 } while (0)
1345
1346bool
c76ca047 1347fhandler_pty_master::setup (bool ispty)
3378bdfc 1348{
1ffe3e67 1349 int res;
c76ca047
CF
1350 tty& t = *cygwin_shared->tty[get_unit ()];
1351
3378bdfc
CF
1352 tcinit (&t, true); /* Set termios information. Force initialization. */
1353
1354 const char *errstr = NULL;
1355 DWORD pipe_mode = PIPE_NOWAIT;
1356
1357 /* Create communication pipes */
1358
3378bdfc 1359 /* FIXME: should this be sec_none_nih? */
1ffe3e67
CF
1360
1361 /* Create communication pipes */
1362
1363 char pipename[sizeof("ttyNNNN-from-master")];
1364 __small_sprintf (pipename, "tty%d-from-master", get_unit ());
1365 res = fhandler_pipe::create_selectable (&sec_all_nih, from_master,
1366 get_output_handle (), 128 * 1024,
1367 pipename);
1368 if (res)
3378bdfc
CF
1369 {
1370 errstr = "input pipe";
1371 goto err;
1372 }
1373
1ffe3e67
CF
1374 __small_sprintf (pipename, "tty%d-to-master", get_unit ());
1375 res = fhandler_pipe::create_selectable (&sec_all_nih, get_io_handle (),
1376 to_master, 128 * 1024, pipename);
1377 if (res)
3378bdfc
CF
1378 {
1379 errstr = "output pipe";
1380 goto err;
1381 }
1382
71d59a92 1383 if (!SetNamedPipeHandleState (get_output_handle (), &pipe_mode, NULL, NULL))
3378bdfc
CF
1384 termios_printf ("can't set output_handle(%p) to non-blocking mode",
1385 get_output_handle ());
1386
1387 need_nl = 0;
1388
1ffe3e67 1389 /* We do not allow others to open us (for handle duplication)
3378bdfc
CF
1390 but rely on cygheap->inherited_ctty for descendant processes.
1391 In the future the cygserver may allow access by others. */
1392
1393#ifdef USE_SERVER
a76877e9
CV
1394 if (cygserver_running == CYGSERVER_UNKNOWN)
1395 cygserver_init ();
3378bdfc
CF
1396#endif
1397
1398 /* Create synchronisation events */
1399
c76ca047 1400 if (!ispty)
3378bdfc
CF
1401 {
1402 if (!(output_done_event = t.get_event (errstr = OUTPUT_DONE_EVENT)))
1403 goto err;
1404 if (!(ioctl_done_event = t.get_event (errstr = IOCTL_DONE_EVENT)))
1405 goto err;
1406 if (!(ioctl_request_event = t.get_event (errstr = IOCTL_REQUEST_EVENT)))
1407 goto err;
1408 }
1409
1410 if (!(input_available_event = t.get_event (errstr = INPUT_AVAILABLE_EVENT, TRUE)))
1411 goto err;
1412
27114d3a 1413 char buf[MAX_PATH];
3378bdfc
CF
1414 errstr = shared_name (buf, OUTPUT_MUTEX, t.ntty);
1415 if (!(output_mutex = CreateMutex (&sec_all, FALSE, buf)))
1416 goto err;
1417
1418 errstr = shared_name (buf, INPUT_MUTEX, t.ntty);
1419 if (!(input_mutex = CreateMutex (&sec_all, FALSE, buf)))
1420 goto err;
1421
1422 if (!DuplicateHandle (hMainProc, from_master, hMainProc, &from_master, 0, false,
daff1587 1423 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
3378bdfc
CF
1424 {
1425 errstr = "non-inheritable from_master";
1426 goto err;
1427 }
1428
1429 if (!DuplicateHandle (hMainProc, to_master, hMainProc, &to_master, 0, false,
daff1587 1430 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
3378bdfc
CF
1431 {
1432 errstr = "non-inheritable to_master";
1433 goto err;
1434 }
1435
1436 t.from_master = from_master;
1437 t.to_master = to_master;
1438 // /* screws up tty master */ ProtectHandle1INH (output_mutex, output_mutex);
1439 // /* screws up tty master */ ProtectHandle1INH (input_mutex, input_mutex);
1440 t.winsize.ws_col = 80;
1441 t.winsize.ws_row = 25;
1442 t.master_pid = myself->pid;
1443
1444 termios_printf ("tty%d opened - from_slave %p, to_slave %p", t.ntty,
1445 get_io_handle (), get_output_handle ());
1446 return true;
1447
1448err:
1449 __seterrno ();
1450 close_maybe (get_io_handle ());
1451 close_maybe (get_output_handle ());
1452 close_maybe (output_done_event);
1453 close_maybe (ioctl_done_event);
1454 close_maybe (ioctl_request_event);
1455 close_maybe (input_available_event);
1456 close_maybe (output_mutex);
1457 close_maybe (input_mutex);
578e142a
CF
1458 close_maybe (from_master);
1459 close_maybe (to_master);
3378bdfc
CF
1460 termios_printf ("tty%d open failed - failed to create %s", errstr);
1461 return false;
1462}
1463
1464void
1465fhandler_pty_master::fixup_after_fork (HANDLE parent)
1466{
1467 DWORD wpid = GetCurrentProcessId ();
1468 fhandler_tty_master *arch = (fhandler_tty_master *) archetype;
1469 if (arch->dwProcessId != wpid)
1470 {
1471 tty& t = *get_ttyp ();
1472 if (!DuplicateHandle (parent, arch->from_master, hMainProc,
1473 &arch->from_master, 0, false, DUPLICATE_SAME_ACCESS))
1474 system_printf ("couldn't duplicate from_parent(%p), %E", arch->from_master);
1475 if (!DuplicateHandle (parent, arch->to_master, hMainProc,
1476 &arch->to_master, 0, false, DUPLICATE_SAME_ACCESS))
1477 system_printf ("couldn't duplicate to_parent(%p), %E", arch->from_master);
1478 if (myself->pid == t.master_pid)
1479 {
1480 t.from_master = arch->from_master;
1481 t.to_master = arch->to_master;
1482 }
1483 arch->dwProcessId = wpid;
1484 }
daff1587
CF
1485 from_master = arch->from_master;
1486 to_master = arch->to_master;
3378bdfc
CF
1487 report_tty_counts (this, "inherited master", "");
1488}
1489
1490void
1491fhandler_pty_master::fixup_after_exec ()
1492{
578e142a 1493 if (!close_on_exec ())
3378bdfc 1494 fixup_after_fork (spawn_info->parent);
daff1587
CF
1495 else
1496 from_master = to_master = NULL;
3378bdfc 1497}
This page took 0.507269 seconds and 5 git commands to generate.