]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/fhandler_termios.cc
Revert errneous checkin.
[newlib-cygwin.git] / winsup / cygwin / fhandler_termios.cc
CommitLineData
1fd5e000
CF
1/* fhandler_termios.cc
2
05c98e07 3 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009,
580df3b6 4 2010, 2011, 2012 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>
1fd5e000 14#include <ctype.h>
9e2baf8d 15#include "cygerrno.h"
7ac61736 16#include "path.h"
bccd5e0d 17#include "fhandler.h"
bccd5e0d
CF
18#include "sigproc.h"
19#include "pinfo.h"
29ac7f89 20#include "tty.h"
5b3e1f73 21#include "cygtls.h"
55dcba98
CF
22#include "dtable.h"
23#include "cygheap.h"
24#include "child_info.h"
bd139e52 25#include "ntdll.h"
1fd5e000
CF
26
27/* Common functions shared by tty/console */
28
29void
32bf3082 30fhandler_termios::tcinit (bool is_pty_master)
1fd5e000
CF
31{
32 /* Initial termios values */
33
32bf3082 34 if (is_pty_master || !tc ()->initialized ())
1fd5e000 35 {
32bf3082
CF
36 tc ()->ti.c_iflag = BRKINT | ICRNL | IXON;
37 tc ()->ti.c_oflag = OPOST | ONLCR;
38 tc ()->ti.c_cflag = B38400 | CS8 | CREAD;
39 tc ()->ti.c_lflag = ISIG | ICANON | ECHO | IEXTEN;
1fd5e000 40
32bf3082
CF
41 tc ()->ti.c_cc[VDISCARD] = CFLUSH;
42 tc ()->ti.c_cc[VEOL] = CEOL;
43 tc ()->ti.c_cc[VEOL2] = CEOL2;
44 tc ()->ti.c_cc[VEOF] = CEOF;
45 tc ()->ti.c_cc[VERASE] = CERASE;
46 tc ()->ti.c_cc[VINTR] = CINTR;
47 tc ()->ti.c_cc[VKILL] = CKILL;
48 tc ()->ti.c_cc[VLNEXT] = CLNEXT;
49 tc ()->ti.c_cc[VMIN] = 1;
50 tc ()->ti.c_cc[VQUIT] = CQUIT;
51 tc ()->ti.c_cc[VREPRINT] = CRPRNT;
52 tc ()->ti.c_cc[VSTART] = CSTART;
53 tc ()->ti.c_cc[VSTOP] = CSTOP;
54 tc ()->ti.c_cc[VSUSP] = CSUSP;
55 tc ()->ti.c_cc[VSWTC] = CSWTCH;
56 tc ()->ti.c_cc[VTIME] = 0;
57 tc ()->ti.c_cc[VWERASE] = CWERASE;
1fd5e000 58
32bf3082
CF
59 tc ()->ti.c_ispeed = tc ()->ti.c_ospeed = B38400;
60 tc ()->pgid = is_pty_master ? 0 : myself->pgid;
61 tc ()->initialized (true);
1fd5e000
CF
62 }
63}
64
65int
66fhandler_termios::tcsetpgrp (const pid_t pgid)
67{
a345dc55 68 termios_printf ("%s, pgid %d, sid %d, tsid %d", tc ()->ttyname (), pgid,
32bf3082
CF
69 myself->sid, tc ()->getsid ());
70 if (myself->sid != tc ()->getsid ())
1fd5e000
CF
71 {
72 set_errno (EPERM);
73 return -1;
74 }
5b3e1f73
CF
75 int res;
76 while (1)
77 {
78 res = bg_check (-SIGTTOU);
79
80 switch (res)
81 {
82 case bg_ok:
32bf3082 83 tc ()->setpgid (pgid);
ca35d41c 84 if (tc ()->is_console && (strace.active () || !being_debugged ()))
852908e8 85 tc ()->kill_pgrp (__SIGSETPGRP);
5b3e1f73
CF
86 res = 0;
87 break;
88 case bg_signalled:
89 if (_my_tls.call_signal_handler ())
90 continue;
91 set_errno (EINTR);
92 /* fall through intentionally */
93 default:
94 res = -1;
95 break;
96 }
97 break;
98 }
99 return res;
1fd5e000
CF
100}
101
102int
103fhandler_termios::tcgetpgrp ()
104{
bd7c9459 105 if (myself->ctty > 0 && myself->ctty == tc ()->ntty)
32bf3082 106 return tc ()->pgid;
b4311a90
CV
107 set_errno (ENOTTY);
108 return -1;
109}
110
111int
112fhandler_pty_master::tcgetpgrp ()
113{
32bf3082 114 return tc ()->pgid;
7123c8b1
CF
115}
116
083abe54
CF
117void
118tty_min::kill_pgrp (int sig)
119{
069e637c 120 bool killself = false;
deb648cc 121 winpids pids ((DWORD) PID_MAP_RW);
985d0e68 122 siginfo_t si = {0};
f6936c48
CF
123 si.si_signo = sig;
124 si.si_code = SI_KERNEL;
083abe54
CF
125 for (unsigned i = 0; i < pids.npids; i++)
126 {
127 _pinfo *p = pids[i];
1a9a235a 128 if (!p->exists () || p->ctty != ntty || p->pgid != pgid)
083abe54
CF
129 continue;
130 if (p == myself)
069e637c 131 killself = sig != __SIGSETPGRP;
083abe54 132 else
0c55f6ed 133 sig_send (p, si);
083abe54
CF
134 }
135 if (killself)
f6936c48 136 sig_send (myself, si);
083abe54 137}
2402700d 138
32bf3082
CF
139int
140tty_min::is_orphaned_process_group (int pgid)
141{
142 /* An orphaned process group is a process group in which the parent
143 of every member is either itself a member of the group or is not
144 a member of the group's session. */
145 termios_printf ("checking pgid %d, my sid %d, my parent %d", pgid, myself->sid, myself->ppid);
146 winpids pids ((DWORD) 0);
147 for (unsigned i = 0; i < pids.npids; i++)
148 {
149 _pinfo *p = pids[i];
150 termios_printf ("checking pid %d - has pgid %d\n", p->pid, p->pgid);
151 if (!p || !p->exists () || p->pgid != pgid)
b86f999a 152 continue;
32bf3082
CF
153 pinfo ppid (p->ppid);
154 if (!ppid)
155 continue;
156 termios_printf ("ppid->pgid %d, ppid->sid %d", ppid->pgid, ppid->sid);
157 if (ppid->pgid != pgid && ppid->sid == myself->sid)
b86f999a 158 return 0;
32bf3082
CF
159 }
160 return 1;
161}
162
a7cde2b9 163bg_check_types
9cec3d45 164fhandler_termios::bg_check (int sig)
1fd5e000 165{
32bf3082
CF
166 if (!myself->pgid || tc ()->getpgid () == myself->pgid ||
167 myself->ctty != tc ()->ntty ||
168 ((sig == SIGTTOU) && !(tc ()->ti.c_lflag & TOSTOP)))
a7cde2b9 169 return bg_ok;
1fd5e000
CF
170
171 if (sig < 0)
172 sig = -sig;
173
a345dc55
CF
174 termios_printf ("%s, bg I/O pgid %d, tpgid %d, myctty %s", tc ()->ttyname (),
175 myself->pgid, tc ()->getpgid (), myctty ());
1fd5e000 176
32bf3082 177 if (tc ()->getsid () == 0)
1fd5e000
CF
178 {
179 /* The pty has been closed by the master. Return an EOF
180 indication. FIXME: There is nothing to stop somebody
181 from reallocating this pty. I think this is the case
182 which is handled by unlockpt on a Unix system. */
183 termios_printf ("closed by master");
a7cde2b9 184 return bg_eof;
1fd5e000
CF
185 }
186
1fd5e000 187 int sigs_ignored =
13584f07 188 ((void *) global_sigs[sig].sa_handler == (void *) SIG_IGN) ||
70300fdb 189 (_main_tls->sigmask & SIGTOMASK (sig));
1fd5e000 190
7123c8b1
CF
191 /* If the process is ignoring SIGTT*, then background IO is OK. If
192 the process is not ignoring SIGTT*, then the sig is to be sent to
193 all processes in the process group (unless the process group of the
194 process is orphaned, in which case we return EIO). */
195 if (sigs_ignored)
196 return bg_ok; /* Just allow the IO */
32bf3082 197 else if (tc ()->is_orphaned_process_group (myself->pgid))
f6936c48 198 {
7123c8b1
CF
199 termios_printf ("process group is orphaned");
200 set_errno (EIO); /* This is an IO error */
201 return bg_error;
f6936c48 202 }
7123c8b1
CF
203 else
204 {
205 /* Don't raise a SIGTT* signal if we have already been
206 interrupted by another signal. */
2addde8c 207 if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
7123c8b1
CF
208 {
209 siginfo_t si = {0};
210 si.si_signo = sig;
211 si.si_code = SI_KERNEL;
212 kill_pgrp (myself->pgid, si);
213 }
214 return bg_signalled;
b86f999a 215 }
1fd5e000
CF
216}
217
218#define set_input_done(x) input_done = input_done || (x)
219
cd94b71c
CF
220inline void
221fhandler_termios::echo_erase (int force)
222{
32bf3082 223 if (force || tc ()->ti.c_lflag & ECHO)
cd94b71c
CF
224 doecho ("\b \b", 3);
225}
226
49dd6fc6 227line_edit_status
46b73ef1 228fhandler_termios::line_edit (const char *rptr, int nread, termios& ti)
1fd5e000 229{
49dd6fc6 230 line_edit_status ret = line_edit_ok;
1fd5e000
CF
231 char c;
232 int input_done = 0;
b18962e2 233 bool sawsig = false;
46b73ef1 234 int iscanon = ti.c_lflag & ICANON;
1fd5e000
CF
235
236 while (nread-- > 0)
237 {
238 c = *rptr++;
239
240 termios_printf ("char %c", c);
241
242 /* Check for special chars */
243
244 if (c == '\r')
245 {
46b73ef1 246 if (ti.c_iflag & IGNCR)
1fd5e000 247 continue;
46b73ef1 248 if (ti.c_iflag & ICRNL)
1fd5e000
CF
249 {
250 c = '\n';
251 set_input_done (iscanon);
252 }
253 }
254 else if (c == '\n')
255 {
46b73ef1 256 if (ti.c_iflag & INLCR)
1fd5e000
CF
257 c = '\r';
258 else
259 set_input_done (iscanon);
260 }
261
46b73ef1 262 if (ti.c_iflag & ISTRIP)
1fd5e000 263 c &= 0x7f;
46b73ef1 264 if (ti.c_lflag & ISIG)
1fd5e000
CF
265 {
266 int sig;
46b73ef1 267 if (CCEQ (ti.c_cc[VINTR], c))
1fd5e000 268 sig = SIGINT;
46b73ef1 269 else if (CCEQ (ti.c_cc[VQUIT], c))
1fd5e000 270 sig = SIGQUIT;
46b73ef1 271 else if (CCEQ (ti.c_cc[VSUSP], c))
1fd5e000
CF
272 sig = SIGTSTP;
273 else
274 goto not_a_sig;
275
276 termios_printf ("got interrupt %d, sending signal %d", c, sig);
5e8e21d9 277 eat_readahead (-1);
32bf3082 278 tc ()->kill_pgrp (sig);
46b73ef1 279 ti.c_lflag &= ~FLUSHO;
b18962e2 280 sawsig = true;
1fd5e000
CF
281 goto restart_output;
282 }
283 not_a_sig:
46b73ef1 284 if (ti.c_iflag & IXON)
1fd5e000 285 {
46b73ef1 286 if (CCEQ (ti.c_cc[VSTOP], c))
1fd5e000 287 {
32bf3082 288 if (!tc ()->output_stopped)
c1644acb 289 {
32bf3082 290 tc ()->output_stopped = 1;
c1644acb
CF
291 acquire_output_mutex (INFINITE);
292 }
1fd5e000
CF
293 continue;
294 }
46b73ef1 295 else if (CCEQ (ti.c_cc[VSTART], c))
1fd5e000
CF
296 {
297 restart_output:
32bf3082 298 tc ()->output_stopped = 0;
c1644acb 299 release_output_mutex ();
1fd5e000
CF
300 continue;
301 }
32bf3082 302 else if ((ti.c_iflag & IXANY) && tc ()->output_stopped)
1fd5e000
CF
303 goto restart_output;
304 }
46b73ef1 305 if (iscanon && ti.c_lflag & IEXTEN && CCEQ (ti.c_cc[VDISCARD], c))
1fd5e000 306 {
46b73ef1 307 ti.c_lflag ^= FLUSHO;
1fd5e000
CF
308 continue;
309 }
310 if (!iscanon)
311 /* nothing */;
46b73ef1 312 else if (CCEQ (ti.c_cc[VERASE], c))
1fd5e000
CF
313 {
314 if (eat_readahead (1))
cd94b71c 315 echo_erase ();
1fd5e000
CF
316 continue;
317 }
46b73ef1 318 else if (CCEQ (ti.c_cc[VWERASE], c))
1fd5e000
CF
319 {
320 int ch;
321 do
322 if (!eat_readahead (1))
323 break;
324 else
cd94b71c 325 echo_erase ();
1fd5e000
CF
326 while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
327 continue;
328 }
46b73ef1 329 else if (CCEQ (ti.c_cc[VKILL], c))
1fd5e000
CF
330 {
331 int nchars = eat_readahead (-1);
46b73ef1 332 if (ti.c_lflag & ECHO)
cd94b71c
CF
333 while (nchars--)
334 echo_erase (1);
1fd5e000
CF
335 continue;
336 }
46b73ef1 337 else if (CCEQ (ti.c_cc[VREPRINT], c))
1fd5e000 338 {
46b73ef1 339 if (ti.c_lflag & ECHO)
cd94b71c
CF
340 {
341 doecho ("\n\r", 2);
342 doecho (rabuf, ralen);
343 }
1fd5e000
CF
344 continue;
345 }
46b73ef1 346 else if (CCEQ (ti.c_cc[VEOF], c))
1fd5e000
CF
347 {
348 termios_printf ("EOF");
0c55f6ed 349 accept_input ();
bd2001ae 350 ret = line_edit_input_done;
1fd5e000
CF
351 continue;
352 }
46b73ef1
CF
353 else if (CCEQ (ti.c_cc[VEOL], c) ||
354 CCEQ (ti.c_cc[VEOL2], c) ||
1fd5e000
CF
355 c == '\n')
356 {
357 set_input_done (1);
358 termios_printf ("EOL");
359 }
360
46b73ef1 361 if (ti.c_iflag & IUCLC && isupper (c))
2556e737 362 c = cyg_tolower (c);
1fd5e000 363
49dd6fc6 364 put_readahead (c);
caf27c01
CF
365 if (ti.c_lflag & ECHO)
366 doecho (&c, 1);
46b73ef1 367 if (!iscanon || input_done)
bd2001ae 368 {
388aa994 369 int status = accept_input ();
0c0eec3f 370 if (status != 1)
b2be3149 371 {
388aa994 372 ret = status ? line_edit_error : line_edit_pipe_full;
b2be3149
CF
373 eat_readahead (1);
374 break;
375 }
bd2001ae
CF
376 ret = line_edit_input_done;
377 input_done = 0;
378 }
1fd5e000
CF
379 }
380
46b73ef1 381 if (!iscanon && ralen > 0)
bd2001ae 382 ret = line_edit_input_done;
1fd5e000 383
95a8465b 384 if (sawsig)
49dd6fc6 385 ret = line_edit_signalled;
1fd5e000 386
49dd6fc6 387 return ret;
1fd5e000 388}
e935fcf0 389
1727fba0
CV
390_off64_t
391fhandler_termios::lseek (_off64_t, int)
b0359971
RC
392{
393 set_errno (ESPIPE);
2402700d 394 return -1;
b0359971 395}
f4c1f003
CF
396
397void
398fhandler_termios::sigflush ()
399{
71c17c54
CF
400 /* FIXME: Checking get_ttyp() for NULL is not right since it should not
401 be NULL while this is alive. However, we can conceivably close a
402 ctty while exiting and that will zero this. */
55dcba98
CF
403 if ((!have_execed || have_execed_cygwin) && get_ttyp ()
404 && !(get_ttyp ()->ti.c_lflag & NOFLSH))
f4c1f003
CF
405 tcflush (TCIFLUSH);
406}
4add6f8d 407
580df3b6 408pid_t
4add6f8d
CF
409fhandler_termios::tcgetsid ()
410{
bd7c9459 411 if (myself->ctty > 0 && myself->ctty == tc ()->ntty)
4add6f8d
CF
412 return tc ()->getsid ();
413 set_errno (ENOTTY);
414 return -1;
415}
416
417int
23771fa1 418fhandler_termios::ioctl (int cmd, void *varg)
4add6f8d
CF
419{
420 if (cmd != TIOCSCTTY)
421 return 1; /* Not handled by this function */
422
23771fa1
CF
423 int arg = (int) varg;
424
4add6f8d
CF
425 if (arg != 0 && arg != 1)
426 {
427 set_errno (EINVAL);
428 return -1;
429 }
430
431 termios_printf ("myself->ctty %d, myself->sid %d, myself->pid %d, arg %d, tc()->getsid () %d\n",
432 myself->ctty, myself->sid, myself->pid, arg, tc ()->getsid ());
433 if (myself->ctty > 0 || myself->sid != myself->pid || (!arg && tc ()->getsid () > 0))
434 {
435 set_errno (EPERM);
436 return -1;
437 }
438
439 myself->ctty = -1;
23771fa1 440 myself->set_ctty (this, 0);
4add6f8d
CF
441 return 0;
442}
This page took 0.404698 seconds and 5 git commands to generate.