3 Copyright 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12 #include <sys/termios.h>
24 /* Common functions shared by tty/console */
27 fhandler_termios::tcinit (tty_min *this_tc, int force)
29 /* Initial termios values */
33 if (force || !TTYISSETF (INITIALIZED))
35 tc->ti.c_iflag = BRKINT | ICRNL | IXON;
36 tc->ti.c_oflag = OPOST | ONLCR;
37 tc->ti.c_cflag = B38400 | CS8 | CREAD;
38 tc->ti.c_lflag = ISIG | ICANON | ECHO | IEXTEN;
40 tc->ti.c_cc[VDISCARD] = CFLUSH;
41 tc->ti.c_cc[VEOL] = CEOL;
42 tc->ti.c_cc[VEOL2] = CEOL2;
43 tc->ti.c_cc[VEOF] = CEOF;
44 tc->ti.c_cc[VERASE] = CERASE;
45 tc->ti.c_cc[VINTR] = CINTR;
46 tc->ti.c_cc[VKILL] = CKILL;
47 tc->ti.c_cc[VLNEXT] = CLNEXT;
48 tc->ti.c_cc[VMIN] = 1;
49 tc->ti.c_cc[VQUIT] = CQUIT;
50 tc->ti.c_cc[VREPRINT] = CRPRNT;
51 tc->ti.c_cc[VSTART] = CSTART;
52 tc->ti.c_cc[VSTOP] = CSTOP;
53 tc->ti.c_cc[VSUSP] = CSUSP;
54 tc->ti.c_cc[VSWTC] = CSWTCH;
55 tc->ti.c_cc[VTIME] = 0;
56 tc->ti.c_cc[VWERASE] = CWERASE;
58 tc->ti.c_ispeed = tc->ti.c_ospeed = B38400;
59 tc->pgid = myself->pgid;
60 TTYSETF (INITIALIZED);
65 fhandler_termios::tcsetpgrp (const pid_t pgid)
67 termios_printf ("tty %d pgid %d, sid %d, tsid %d", tc->ntty, pgid,
68 myself->sid, tc->getsid ());
69 if (myself->sid != tc->getsid ())
79 fhandler_termios::tcgetpgrp ()
85 tty_min::kill_pgrp (int sig)
89 for (unsigned i = 0; i < pids.npids; i++)
92 if (!proc_exists (p) || p->ctty != ntty || p->pgid != pgid)
97 (void) sig_send (p, sig);
100 sig_send (myself, sig);
104 tty_min::set_ctty (int ttynum, int flags)
106 if ((myself->ctty < 0 || myself->ctty == ttynum) && !(flags & O_NOCTTY))
108 myself->ctty = ttynum;
109 syscall_printf ("attached tty%d sid %d, pid %d, tty->pgid %d, tty->sid %d",
110 ttynum, myself->sid, myself->pid, pgid, getsid ());
113 if (myself->sid == myself->pid &&
114 (p == myself || !proc_exists (p)))
116 paranoid_printf ("resetting tty%d sid. Was %d, now %d. pgid was %d, now %d.",
117 ttynum, getsid (), myself->sid, getpgid (), myself->pgid);
118 /* We are the session leader */
119 setsid (myself->sid);
120 setpgid (myself->pgid);
123 myself->sid = getsid ();
125 setpgid (myself->pgid);
130 fhandler_termios::bg_check (int sig)
132 if (!myself->pgid || tc->getpgid () == myself->pgid ||
133 myself->ctty != tc->ntty ||
134 ((sig == SIGTTOU) && !(tc->ti.c_lflag & TOSTOP)))
140 termios_printf ("bg I/O pgid %d, tpgid %d, ctty %d",
141 myself->pgid, tc->getpgid (), myself->ctty);
143 if (tc->getsid () == 0)
145 /* The pty has been closed by the master. Return an EOF
146 indication. FIXME: There is nothing to stop somebody
147 from reallocating this pty. I think this is the case
148 which is handled by unlockpt on a Unix system. */
149 termios_printf ("closed by master");
153 /* If the process group is no more or if process is ignoring or blocks 'sig',
155 int pgid_gone = !pid_exists (myself->pgid);
157 ((void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN) ||
158 (myself->getsigmask () & SIGTOMASK (sig));
162 else if (!sigs_ignored)
164 else if (sig == SIGTTOU)
165 return bg_ok; /* Just allow the output */
167 goto setEIO; /* This is an output error */
169 /* Don't raise a SIGTT* signal if we have already been interrupted
170 by another signal. */
171 if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
172 kill_pgrp (myself->pgid, sig);
180 #define set_input_done(x) input_done = input_done || (x)
183 fhandler_termios::echo_erase (int force)
185 if (force || tc->ti.c_lflag & ECHO)
190 fhandler_termios::line_edit (const char *rptr, int nread, termios& ti)
192 line_edit_status ret = line_edit_ok;
196 int iscanon = ti.c_lflag & ICANON;
202 termios_printf ("char %c", c);
204 /* Check for special chars */
208 if (ti.c_iflag & IGNCR)
210 if (ti.c_iflag & ICRNL)
213 set_input_done (iscanon);
218 if (ti.c_iflag & INLCR)
221 set_input_done (iscanon);
224 if (ti.c_iflag & ISTRIP)
226 if (ti.c_lflag & ISIG)
229 if (CCEQ (ti.c_cc[VINTR], c))
231 else if (CCEQ (ti.c_cc[VQUIT], c))
233 else if (CCEQ (ti.c_cc[VSUSP], c))
238 termios_printf ("got interrupt %d, sending signal %d", c, sig);
241 ti.c_lflag &= ~FLUSHO;
246 if (ti.c_iflag & IXON)
248 if (CCEQ (ti.c_cc[VSTOP], c))
250 if (!tc->output_stopped)
252 tc->output_stopped = 1;
253 acquire_output_mutex (INFINITE);
257 else if (CCEQ (ti.c_cc[VSTART], c))
260 tc->output_stopped = 0;
261 release_output_mutex ();
264 else if ((ti.c_iflag & IXANY) && tc->output_stopped)
267 if (iscanon && ti.c_lflag & IEXTEN && CCEQ (ti.c_cc[VDISCARD], c))
269 ti.c_lflag ^= FLUSHO;
274 else if (CCEQ (ti.c_cc[VERASE], c))
276 if (eat_readahead (1))
280 else if (CCEQ (ti.c_cc[VWERASE], c))
284 if (!eat_readahead (1))
288 while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
291 else if (CCEQ (ti.c_cc[VKILL], c))
293 int nchars = eat_readahead (-1);
294 if (ti.c_lflag & ECHO)
299 else if (CCEQ (ti.c_cc[VREPRINT], c))
301 if (ti.c_lflag & ECHO)
304 doecho (rabuf, ralen);
308 else if (CCEQ (ti.c_cc[VEOF], c))
310 termios_printf ("EOF");
311 (void) accept_input();
312 ret = line_edit_input_done;
315 else if (CCEQ (ti.c_cc[VEOL], c) ||
316 CCEQ (ti.c_cc[VEOL2], c) ||
320 termios_printf ("EOL");
323 if (ti.c_iflag & IUCLC && isupper (c))
327 if (ti.c_lflag & ECHO)
329 if (!iscanon || input_done)
331 int status = accept_input ();
334 ret = status ? line_edit_error : line_edit_pipe_full;
338 ret = line_edit_input_done;
343 if (!iscanon && ralen > 0)
344 ret = line_edit_input_done;
347 ret = line_edit_signalled;
353 fhandler_termios::fixup_after_fork (HANDLE parent)
355 fhandler_base::fixup_after_fork (parent);
356 fork_fixup (parent, get_output_handle (), "output_handle");
360 fhandler_termios::lseek (__off64_t, int)