OSDN Git Service

* gas/mri/mri.exp: Fix test of m6811/m6812 targets.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler_termios.cc
1 /* fhandler_termios.cc
2
3    Copyright 1999, 2000, 2001 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11 #include "winsup.h"
12 #include <stdlib.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <ctype.h>
17 #include "cygerrno.h"
18 #include "fhandler.h"
19 #include "sync.h"
20 #include "sigproc.h"
21 #include "pinfo.h"
22 #include "tty.h"
23
24 /* Common functions shared by tty/console */
25
26 void
27 fhandler_termios::tcinit (tty_min *this_tc, int force)
28 {
29   /* Initial termios values */
30
31   tc = this_tc;
32
33   if (force || !TTYISSETF (INITIALIZED))
34     {
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;
39
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;
57
58       tc->ti.c_ispeed = tc->ti.c_ospeed = B38400;
59       tc->pgid = myself->pgid;
60       TTYSETF (INITIALIZED);
61     }
62 }
63
64 int
65 fhandler_termios::tcsetpgrp (const pid_t pgid)
66 {
67   termios_printf ("pgid %d, sid %d, tsid %d", pgid,
68                     myself->sid, tc->getsid ());
69   if (myself->sid != tc->getsid ())
70     {
71       set_errno (EPERM);
72       return -1;
73     }
74   tc->setpgid (pgid);
75   return 0;
76 }
77
78 int
79 fhandler_termios::tcgetpgrp ()
80 {
81   return tc->pgid;
82 }
83
84 void
85 fhandler_termios::set_ctty (int ttynum, int flags)
86 {
87   if ((myself->ctty < 0 || myself->ctty == ttynum) && !(flags & O_NOCTTY))
88     {
89       myself->ctty = ttynum;
90       syscall_printf ("attached tty%d sid %d, pid %d, tty->pgid %d, tty->sid %d",
91                       ttynum, myself->sid, myself->pid, tc->pgid, tc->getsid ());
92
93       pinfo p (tc->getsid ());
94       if (myself->sid == myself->pid &&
95           (p == myself || !proc_exists (p)))
96         {
97           paranoid_printf ("resetting tty%d sid.  Was %d, now %d.  pgid was %d, now %d.",
98                            ttynum, tc->getsid(), myself->sid, tc->getpgid (), myself->pgid);
99           /* We are the session leader */
100           tc->setsid (myself->sid);
101           tc->setpgid (myself->pgid);
102         }
103       else
104         myself->sid = tc->getsid ();
105       if (tc->getpgid () == 0)
106         tc->setpgid (myself->pgid);
107     }
108 }
109
110 bg_check_types
111 fhandler_termios::bg_check (int sig)
112 {
113   if (!myself->pgid || tc->getpgid () == myself->pgid ||
114         myself->ctty != tc->ntty ||
115         ((sig == SIGTTOU) && !(tc->ti.c_lflag & TOSTOP)))
116     return bg_ok;
117
118   if (sig < 0)
119     sig = -sig;
120
121   termios_printf("bg I/O pgid %d, tpgid %d, ctty %d",
122                     myself->pgid, tc->getpgid (), myself->ctty);
123
124   if (tc->getsid () == 0)
125     {
126       /* The pty has been closed by the master.  Return an EOF
127          indication.  FIXME: There is nothing to stop somebody
128          from reallocating this pty.  I think this is the case
129          which is handled by unlockpt on a Unix system.  */
130       termios_printf ("closed by master");
131       return bg_eof;
132     }
133
134   /* If the process group is no more or if process is ignoring or blocks 'sig',
135      return with error */
136   int pgid_gone = !pid_exists (myself->pgid);
137   int sigs_ignored =
138     ((void *) myself->getsig(sig).sa_handler == (void *) SIG_IGN) ||
139     (myself->getsigmask () & SIGTOMASK (sig));
140
141   if (pgid_gone)
142     goto setEIO;
143   else if (!sigs_ignored)
144     /* nothing */;
145   else if (sig == SIGTTOU)
146     return bg_ok;               /* Just allow the output */
147   else
148     goto setEIO;        /* This is an output error */
149
150   /* Don't raise a SIGTT* signal if we have already been interrupted
151      by another signal. */
152   if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0)
153     _raise (sig);
154   return bg_signalled;
155
156 setEIO:
157   set_errno (EIO);
158   return bg_error;
159 }
160
161 #define set_input_done(x) input_done = input_done || (x)
162
163 int
164 fhandler_termios::line_edit (const char *rptr, int nread, int always_accept)
165 {
166   char c;
167   int input_done = 0;
168   bool sawsig = FALSE;
169   int iscanon = tc->ti.c_lflag & ICANON;
170
171   while (nread-- > 0)
172     {
173       c = *rptr++;
174
175       termios_printf ("char %c", c);
176
177       /* Check for special chars */
178
179       if (c == '\r')
180         {
181           if (tc->ti.c_iflag & IGNCR)
182             continue;
183           if (tc->ti.c_iflag & ICRNL)
184             {
185               c = '\n';
186               set_input_done (iscanon);
187             }
188         }
189       else if (c == '\n')
190         {
191           if (tc->ti.c_iflag & INLCR)
192             c = '\r';
193           else
194             set_input_done (iscanon);
195         }
196
197       if (tc->ti.c_iflag & ISTRIP)
198         c &= 0x7f;
199       if (tc->ti.c_lflag & ISIG)
200         {
201           int sig;
202           if (c ==  tc->ti.c_cc[VINTR])
203             sig = SIGINT;
204           else if (c == tc->ti.c_cc[VQUIT])
205             sig = SIGQUIT;
206           else if (c == tc->ti.c_cc[VSUSP])
207             sig = SIGTSTP;
208           else
209             goto not_a_sig;
210
211           termios_printf ("got interrupt %d, sending signal %d", c, sig);
212           kill_pgrp (tc->getpgid (), sig);
213           tc->ti.c_lflag &= ~FLUSHO;
214           sawsig = 1;
215           goto restart_output;
216         }
217     not_a_sig:
218       if (tc->ti.c_iflag & IXON)
219         {
220           if (c == tc->ti.c_cc[VSTOP])
221             {
222               if (!tc->OutputStopped)
223                 {
224                   tc->OutputStopped = 1;
225                   acquire_output_mutex (INFINITE);
226                 }
227               continue;
228             }
229           else if (c == tc->ti.c_cc[VSTART])
230             {
231     restart_output:
232               tc->OutputStopped = 0;
233               release_output_mutex ();
234               continue;
235             }
236           else if ((tc->ti.c_iflag & IXANY) && tc->OutputStopped)
237             goto restart_output;
238         }
239       if (tc->ti.c_lflag & IEXTEN && c == tc->ti.c_cc[VDISCARD])
240         {
241           tc->ti.c_lflag ^= FLUSHO;
242           continue;
243         }
244       if (!iscanon)
245         /* nothing */;
246       else if (c == tc->ti.c_cc[VERASE])
247         {
248           if (eat_readahead (1))
249             doecho ("\b \b", 3);
250           continue;
251         }
252       else if (c == tc->ti.c_cc[VWERASE])
253         {
254           int ch;
255           do
256             if (!eat_readahead (1))
257               break;
258             else
259               doecho ("\b \b", 3);
260           while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
261           continue;
262         }
263       else if (c == tc->ti.c_cc[VKILL])
264         {
265           int nchars = eat_readahead (-1);
266           while (nchars--)
267             doecho ("\b \b", 3);
268           continue;
269         }
270       else if (c == tc->ti.c_cc[VREPRINT])
271         {
272           doecho ("\n\r", 2);
273           doecho (rabuf, ralen);
274           continue;
275         }
276       else if (c == tc->ti.c_cc[VEOF])
277         {
278           termios_printf ("EOF");
279           input_done = 1;
280           continue;
281         }
282       else if (c == tc->ti.c_cc[VEOL] ||
283                c == tc->ti.c_cc[VEOL2] ||
284                c == '\n')
285         {
286           set_input_done (1);
287           termios_printf ("EOL");
288         }
289
290       if (tc->ti.c_iflag & IUCLC && isupper (c))
291         c = cyg_tolower (c);
292
293       if (tc->ti.c_lflag & ECHO)
294         doecho (&c, 1);
295       put_readahead (c);
296     }
297
298   if (!iscanon || always_accept)
299     set_input_done (ralen > 0);
300
301   if (sawsig)
302     input_done = -1;
303   else if (input_done)
304     (void) accept_input ();
305
306   return input_done;
307 }
308
309 void
310 fhandler_termios::fixup_after_fork (HANDLE parent)
311 {
312   this->fhandler_base::fixup_after_fork (parent);
313   fork_fixup (parent, get_output_handle (), "output_handle");
314 }