OSDN Git Service

Eliminate most unneeded this-> pointers throughout.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / fhandler_termios.cc
1 /* fhandler_termios.cc
2
3    Copyright 1999, 2000, 2001, 2002, 2003 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 <sys/termios.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <ctype.h>
17 #include "cygerrno.h"
18 #include "security.h"
19 #include "fhandler.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 ("tty %d pgid %d, sid %d, tsid %d", tc->ntty, 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 tty_min::kill_pgrp (int sig)
86 {
87   int killself = 0;
88   winpids pids;
89   for (unsigned i = 0; i < pids.npids; i++)
90     {
91       _pinfo *p = pids[i];
92       if (!proc_exists (p) || p->ctty != ntty || p->pgid != pgid)
93         continue;
94       if (p == myself)
95         killself++;
96       else
97         (void) sig_send (p, sig);
98     }
99   if (killself)
100     sig_send (myself, sig);
101 }
102
103 void
104 tty_min::set_ctty (int ttynum, int flags)
105 {
106   if ((myself->ctty < 0 || myself->ctty == ttynum) && !(flags & O_NOCTTY))
107     {
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 ());
111
112       pinfo p (getsid ());
113       if (myself->sid == myself->pid &&
114           (p == myself || !proc_exists (p)))
115         {
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);
121         }
122       else
123         myself->sid = getsid ();
124       if (getpgid () == 0)
125         setpgid (myself->pgid);
126     }
127 }
128
129 bg_check_types
130 fhandler_termios::bg_check (int sig)
131 {
132   if (!myself->pgid || tc->getpgid () == myself->pgid ||
133         myself->ctty != tc->ntty ||
134         ((sig == SIGTTOU) && !(tc->ti.c_lflag & TOSTOP)))
135     return bg_ok;
136
137   if (sig < 0)
138     sig = -sig;
139
140   termios_printf ("bg I/O pgid %d, tpgid %d, ctty %d",
141                     myself->pgid, tc->getpgid (), myself->ctty);
142
143   if (tc->getsid () == 0)
144     {
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");
150       return bg_eof;
151     }
152
153   /* If the process group is no more or if process is ignoring or blocks 'sig',
154      return with error */
155   int pgid_gone = !pid_exists (myself->pgid);
156   int sigs_ignored =
157     ((void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN) ||
158     (myself->getsigmask () & SIGTOMASK (sig));
159
160   if (pgid_gone)
161     goto setEIO;
162   else if (!sigs_ignored)
163     /* nothing */;
164   else if (sig == SIGTTOU)
165     return bg_ok;               /* Just allow the output */
166   else
167     goto setEIO;        /* This is an output error */
168
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);
173   return bg_signalled;
174
175 setEIO:
176   set_errno (EIO);
177   return bg_error;
178 }
179
180 #define set_input_done(x) input_done = input_done || (x)
181
182 inline void
183 fhandler_termios::echo_erase (int force)
184 {
185   if (force || tc->ti.c_lflag & ECHO)
186     doecho ("\b \b", 3);
187 }
188
189 line_edit_status
190 fhandler_termios::line_edit (const char *rptr, int nread, termios& ti)
191 {
192   line_edit_status ret = line_edit_ok;
193   char c;
194   int input_done = 0;
195   bool sawsig = false;
196   int iscanon = ti.c_lflag & ICANON;
197
198   while (nread-- > 0)
199     {
200       c = *rptr++;
201
202       termios_printf ("char %c", c);
203
204       /* Check for special chars */
205
206       if (c == '\r')
207         {
208           if (ti.c_iflag & IGNCR)
209             continue;
210           if (ti.c_iflag & ICRNL)
211             {
212               c = '\n';
213               set_input_done (iscanon);
214             }
215         }
216       else if (c == '\n')
217         {
218           if (ti.c_iflag & INLCR)
219             c = '\r';
220           else
221             set_input_done (iscanon);
222         }
223
224       if (ti.c_iflag & ISTRIP)
225         c &= 0x7f;
226       if (ti.c_lflag & ISIG)
227         {
228           int sig;
229           if (CCEQ (ti.c_cc[VINTR], c))
230             sig = SIGINT;
231           else if (CCEQ (ti.c_cc[VQUIT], c))
232             sig = SIGQUIT;
233           else if (CCEQ (ti.c_cc[VSUSP], c))
234             sig = SIGTSTP;
235           else
236             goto not_a_sig;
237
238           termios_printf ("got interrupt %d, sending signal %d", c, sig);
239           eat_readahead (-1);
240           tc->kill_pgrp (sig);
241           ti.c_lflag &= ~FLUSHO;
242           sawsig = true;
243           goto restart_output;
244         }
245     not_a_sig:
246       if (ti.c_iflag & IXON)
247         {
248           if (CCEQ (ti.c_cc[VSTOP], c))
249             {
250               if (!tc->output_stopped)
251                 {
252                   tc->output_stopped = 1;
253                   acquire_output_mutex (INFINITE);
254                 }
255               continue;
256             }
257           else if (CCEQ (ti.c_cc[VSTART], c))
258             {
259     restart_output:
260               tc->output_stopped = 0;
261               release_output_mutex ();
262               continue;
263             }
264           else if ((ti.c_iflag & IXANY) && tc->output_stopped)
265             goto restart_output;
266         }
267       if (iscanon && ti.c_lflag & IEXTEN && CCEQ (ti.c_cc[VDISCARD], c))
268         {
269           ti.c_lflag ^= FLUSHO;
270           continue;
271         }
272       if (!iscanon)
273         /* nothing */;
274       else if (CCEQ (ti.c_cc[VERASE], c))
275         {
276           if (eat_readahead (1))
277             echo_erase ();
278           continue;
279         }
280       else if (CCEQ (ti.c_cc[VWERASE], c))
281         {
282           int ch;
283           do
284             if (!eat_readahead (1))
285               break;
286             else
287               echo_erase ();
288           while ((ch = peek_readahead (1)) >= 0 && !isspace (ch));
289           continue;
290         }
291       else if (CCEQ (ti.c_cc[VKILL], c))
292         {
293           int nchars = eat_readahead (-1);
294           if (ti.c_lflag & ECHO)
295             while (nchars--)
296               echo_erase (1);
297           continue;
298         }
299       else if (CCEQ (ti.c_cc[VREPRINT], c))
300         {
301           if (ti.c_lflag & ECHO)
302             {
303               doecho ("\n\r", 2);
304               doecho (rabuf, ralen);
305             }
306           continue;
307         }
308       else if (CCEQ (ti.c_cc[VEOF], c))
309         {
310           termios_printf ("EOF");
311           (void) accept_input();
312           ret = line_edit_input_done;
313           continue;
314         }
315       else if (CCEQ (ti.c_cc[VEOL], c) ||
316                CCEQ (ti.c_cc[VEOL2], c) ||
317                c == '\n')
318         {
319           set_input_done (1);
320           termios_printf ("EOL");
321         }
322
323       if (ti.c_iflag & IUCLC && isupper (c))
324         c = cyg_tolower (c);
325
326       put_readahead (c);
327       if (ti.c_lflag & ECHO)
328         doecho (&c, 1);
329       if (!iscanon || input_done)
330         {
331           int status = accept_input ();
332           if (status != 1)
333             {
334               ret = status ? line_edit_error : line_edit_pipe_full;
335               eat_readahead (1);
336               break;
337             }
338           ret = line_edit_input_done;
339           input_done = 0;
340         }
341     }
342
343   if (!iscanon && ralen > 0)
344     ret = line_edit_input_done;
345
346   if (sawsig)
347     ret = line_edit_signalled;
348
349   return ret;
350 }
351
352 void
353 fhandler_termios::fixup_after_fork (HANDLE parent)
354 {
355   fhandler_base::fixup_after_fork (parent);
356   fork_fixup (parent, get_output_handle (), "output_handle");
357 }
358
359 __off64_t
360 fhandler_termios::lseek (__off64_t, int)
361 {
362   set_errno (ESPIPE);
363   return -1;
364 }