3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009,
4 2010, 2011 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
24 /* Common functions shared by tty/console */
27 fhandler_termios::tcinit (bool is_pty_master)
29 /* Initial termios values */
31 if (is_pty_master || !tc ()->initialized ())
33 tc ()->ti.c_iflag = BRKINT | ICRNL | IXON;
34 tc ()->ti.c_oflag = OPOST | ONLCR;
35 tc ()->ti.c_cflag = B38400 | CS8 | CREAD;
36 tc ()->ti.c_lflag = ISIG | ICANON | ECHO | IEXTEN;
38 tc ()->ti.c_cc[VDISCARD] = CFLUSH;
39 tc ()->ti.c_cc[VEOL] = CEOL;
40 tc ()->ti.c_cc[VEOL2] = CEOL2;
41 tc ()->ti.c_cc[VEOF] = CEOF;
42 tc ()->ti.c_cc[VERASE] = CERASE;
43 tc ()->ti.c_cc[VINTR] = CINTR;
44 tc ()->ti.c_cc[VKILL] = CKILL;
45 tc ()->ti.c_cc[VLNEXT] = CLNEXT;
46 tc ()->ti.c_cc[VMIN] = 1;
47 tc ()->ti.c_cc[VQUIT] = CQUIT;
48 tc ()->ti.c_cc[VREPRINT] = CRPRNT;
49 tc ()->ti.c_cc[VSTART] = CSTART;
50 tc ()->ti.c_cc[VSTOP] = CSTOP;
51 tc ()->ti.c_cc[VSUSP] = CSUSP;
52 tc ()->ti.c_cc[VSWTC] = CSWTCH;
53 tc ()->ti.c_cc[VTIME] = 0;
54 tc ()->ti.c_cc[VWERASE] = CWERASE;
56 tc ()->ti.c_ispeed = tc ()->ti.c_ospeed = B38400;
57 tc ()->pgid = is_pty_master ? 0 : myself->pgid;
58 tc ()->initialized (true);
63 fhandler_termios::tcsetpgrp (const pid_t pgid)
65 termios_printf ("tty %d pgid %d, sid %d, tsid %d", tc ()->ntty, pgid,
66 myself->sid, tc ()->getsid ());
67 if (myself->sid != tc ()->getsid ())
75 res = bg_check (-SIGTTOU);
80 tc ()->setpgid (pgid);
81 if (tc ()->is_console)
82 tc ()->kill_pgrp (__SIGSETPGRP);
86 if (_my_tls.call_signal_handler ())
89 /* fall through intentionally */
100 fhandler_termios::tcgetpgrp ()
102 if (myself->ctty != -1 && myself->ctty == tc ()->ntty)
109 fhandler_pty_master::tcgetpgrp ()
115 tty_min::kill_pgrp (int sig)
118 winpids pids ((DWORD) PID_MAP_RW);
121 si.si_code = SI_KERNEL;
122 for (unsigned i = 0; i < pids.npids; i++)
125 if (!p->exists () || p->ctty != ntty || p->pgid != pgid)
133 sig_send (myself, si);
137 tty_min::is_orphaned_process_group (int pgid)
139 /* An orphaned process group is a process group in which the parent
140 of every member is either itself a member of the group or is not
141 a member of the group's session. */
142 termios_printf ("checking pgid %d, my sid %d, my parent %d", pgid, myself->sid, myself->ppid);
143 winpids pids ((DWORD) 0);
144 for (unsigned i = 0; i < pids.npids; i++)
147 termios_printf ("checking pid %d - has pgid %d\n", p->pid, p->pgid);
148 if (!p || !p->exists () || p->pgid != pgid)
150 pinfo ppid (p->ppid);
153 termios_printf ("ppid->pgid %d, ppid->sid %d", ppid->pgid, ppid->sid);
154 if (ppid->pgid != pgid && ppid->sid == myself->sid)
161 fhandler_termios::bg_check (int sig)
163 if (!myself->pgid || tc ()->getpgid () == myself->pgid ||
164 myself->ctty != tc ()->ntty ||
165 ((sig == SIGTTOU) && !(tc ()->ti.c_lflag & TOSTOP)))
171 termios_printf ("bg I/O pgid %d, tpgid %d, %s, ntty %s", myself->pgid, tc ()->getpgid (),
172 myctty (), tc ()->ttyname ());
174 if (tc ()->getsid () == 0)
176 /* The pty has been closed by the master. Return an EOF
177 indication. FIXME: There is nothing to stop somebody
178 from reallocating this pty. I think this is the case
179 which is handled by unlockpt on a Unix system. */
180 termios_printf ("closed by master");
185 ((void *) global_sigs[sig].sa_handler == (void *) SIG_IGN) ||
186 (_main_tls->sigmask & SIGTOMASK (sig));
188 /* If the process is ignoring SIGTT*, then background IO is OK. If
189 the process is not ignoring SIGTT*, then the sig is to be sent to
190 all processes in the process group (unless the process group of the
191 process is orphaned, in which case we return EIO). */
193 return bg_ok; /* Just allow the IO */
194 else if (tc ()->is_orphaned_process_group (myself->pgid))
196 termios_printf ("process group is orphaned");
197 set_errno (EIO); /* This is an IO error */
202 /* Don't raise a SIGTT* signal if we have already been
203 interrupted by another signal. */
204 if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
208 si.si_code = SI_KERNEL;
209 kill_pgrp (myself->pgid, si);
215 #define set_input_done(x) input_done = input_done || (x)
218 fhandler_termios::echo_erase (int force)
220 if (force || tc ()->ti.c_lflag & ECHO)
225 fhandler_termios::line_edit (const char *rptr, int nread, termios& ti)
227 line_edit_status ret = line_edit_ok;
231 int iscanon = ti.c_lflag & ICANON;
237 termios_printf ("char %c", c);
239 /* Check for special chars */
243 if (ti.c_iflag & IGNCR)
245 if (ti.c_iflag & ICRNL)
248 set_input_done (iscanon);
253 if (ti.c_iflag & INLCR)
256 set_input_done (iscanon);
259 if (ti.c_iflag & ISTRIP)
261 if (ti.c_lflag & ISIG)
264 if (CCEQ (ti.c_cc[VINTR], c))
266 else if (CCEQ (ti.c_cc[VQUIT], c))
268 else if (CCEQ (ti.c_cc[VSUSP], c))
273 termios_printf ("got interrupt %d, sending signal %d", c, sig);
275 tc ()->kill_pgrp (sig);
276 ti.c_lflag &= ~FLUSHO;
281 if (ti.c_iflag & IXON)
283 if (CCEQ (ti.c_cc[VSTOP], c))
285 if (!tc ()->output_stopped)
287 tc ()->output_stopped = 1;
288 acquire_output_mutex (INFINITE);
292 else if (CCEQ (ti.c_cc[VSTART], c))
295 tc ()->output_stopped = 0;
296 release_output_mutex ();
299 else if ((ti.c_iflag & IXANY) && tc ()->output_stopped)
302 if (iscanon && ti.c_lflag & IEXTEN && CCEQ (ti.c_cc[VDISCARD], c))
304 ti.c_lflag ^= FLUSHO;
309 else if (CCEQ (ti.c_cc[VERASE], c))
311 if (eat_readahead (1))
315 else if (CCEQ (ti.c_cc[VWERASE], c))
319 if (!eat_readahead (1))
323 while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
326 else if (CCEQ (ti.c_cc[VKILL], c))
328 int nchars = eat_readahead (-1);
329 if (ti.c_lflag & ECHO)
334 else if (CCEQ (ti.c_cc[VREPRINT], c))
336 if (ti.c_lflag & ECHO)
339 doecho (rabuf, ralen);
343 else if (CCEQ (ti.c_cc[VEOF], c))
345 termios_printf ("EOF");
347 ret = line_edit_input_done;
350 else if (CCEQ (ti.c_cc[VEOL], c) ||
351 CCEQ (ti.c_cc[VEOL2], c) ||
355 termios_printf ("EOL");
358 if (ti.c_iflag & IUCLC && isupper (c))
362 if (ti.c_lflag & ECHO)
364 if (!iscanon || input_done)
366 int status = accept_input ();
369 ret = status ? line_edit_error : line_edit_pipe_full;
373 ret = line_edit_input_done;
378 if (!iscanon && ralen > 0)
379 ret = line_edit_input_done;
382 ret = line_edit_signalled;
388 fhandler_termios::lseek (_off64_t, int)
395 fhandler_termios::sigflush ()
397 /* FIXME: Checking get_ttyp() for NULL is not right since it should not
398 be NULL while this is alive. However, we can conceivably close a
399 ctty while exiting and that will zero this. */
400 if (get_ttyp () && !(get_ttyp ()->ti.c_lflag & NOFLSH))