Add checkpoint tty signaling support to stty and tcsh. The signal
[dragonfly.git] / contrib / tcsh / ed.term.c
1 /*
2  * $Header: /src/pub/tcsh/ed.term.c,v 1.28 2002/07/06 22:28:13 christos Exp $
3  * $DragonFly: src/contrib/tcsh/Attic/ed.term.c,v 1.2 2003/10/13 21:24:29 dillon Exp $
4  */
5 /*
6  * ed.term.c: Low level terminal interface
7  */
8 /*-
9  * Copyright (c) 1980, 1991 The Regents of the University of California.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 #include "sh.h"
37 #ifndef WINNT_NATIVE
38
39 RCSID("$Id: ed.term.c,v 1.28 2002/07/06 22:28:13 christos Exp $")
40
41 #include "ed.h"
42
43 int didsetty = 0;
44 ttyperm_t ttylist = {   
45     {
46 #if defined(POSIX) || defined(TERMIO)
47         { "iflag:", ICRNL, (INLCR|IGNCR) },
48         { "oflag:", (OPOST|ONLCR), ONLRET },
49         { "cflag:", 0, 0 },
50         { "lflag:", (ISIG|ICANON|ECHO|ECHOE|ECHOCTL|IEXTEN),
51                     (NOFLSH|ECHONL|EXTPROC|FLUSHO|IDEFAULT) },
52 #else /* GSTTY */
53         { "nrmal:", (ECHO|CRMOD|ANYP), (CBREAK|RAW|LCASE|VTDELAY|ALLDELAY) },
54         { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) },
55 #endif /* POSIX || TERMIO */
56         { "chars:",     0, 0 },
57     },
58     {
59 #if defined(POSIX) || defined(TERMIO)
60         { "iflag:", (INLCR|ICRNL), IGNCR },
61         { "oflag:", (OPOST|ONLCR), ONLRET },
62         { "cflag:", 0, 0 },
63         { "lflag:", ISIG,
64                     (NOFLSH|ICANON|ECHO|ECHOK|ECHONL|EXTPROC|IEXTEN|FLUSHO|
65                      IDEFAULT) },
66 #else /* GSTTY */
67         { "nrmal:", (CBREAK|CRMOD|ANYP), (RAW|ECHO|LCASE|VTDELAY|ALLDELAY) },
68         { "local:", (LCRTBS|LCRTERA|LCRTKIL), (LPRTERA|LFLUSHO) },
69 #endif /* POSIX || TERMIO */
70         { "chars:", (C_SH(C_MIN)|C_SH(C_TIME)|C_SH(C_SWTCH)|C_SH(C_DSWTCH)|
71                      C_SH(C_WERASE)|C_SH(C_REPRINT)|C_SH(C_SUSP)|C_SH(C_DSUSP)|
72                      C_SH(C_EOF)|C_SH(C_EOL)|C_SH(C_DISCARD)|C_SH(C_PGOFF)|
73                      C_SH(C_KILL2)|C_SH(C_PAGE)|C_SH(C_STATUS)|C_SH(C_CHECKPT)|
74                      C_SH(C_LNEXT)),
75                      0 }
76     },
77     {
78 #if defined(POSIX) || defined(TERMIO)
79         { "iflag:", 0, IXON | IXOFF },
80         { "oflag:", 0, 0 },
81         { "cflag:", 0, 0 },
82         { "lflag:", 0, ISIG | IEXTEN },
83 #else /* GSTTY */
84         { "nrmal:", RAW, CBREAK },
85         { "local:", 0, 0 },
86 #endif /* POSIX || TERMIO */
87         { "chars:", 0, 0 },
88     }
89 };
90
91 static struct tcshmodes {
92     char *m_name;
93 #ifdef SOLARIS2
94     unsigned long m_value;
95 #else /* !SOLARIS2 */
96     int   m_value;
97 #endif /* SOLARIS2 */
98     int   m_type;
99 } modelist[] = {
100 #if defined(POSIX) || defined(TERMIO)
101
102 # ifdef IGNBRK
103     { "ignbrk", IGNBRK, M_INPUT },
104 # endif /* IGNBRK */
105 # ifdef BRKINT
106     { "brkint", BRKINT, M_INPUT },
107 # endif /* BRKINT */
108 # ifdef IGNPAR
109     { "ignpar", IGNPAR, M_INPUT },
110 # endif /* IGNPAR */
111 # ifdef PARMRK
112     { "parmrk", PARMRK, M_INPUT },
113 # endif /* PARMRK */
114 # ifdef INPCK
115     { "inpck",  INPCK,  M_INPUT },
116 # endif /* INPCK */
117 # ifdef ISTRIP
118     { "istrip", ISTRIP, M_INPUT },
119 # endif /* ISTRIP */
120 # ifdef INLCR
121     { "inlcr",  INLCR,  M_INPUT },
122 # endif /* INLCR */
123 # ifdef IGNCR
124     { "igncr",  IGNCR,  M_INPUT },
125 # endif /* IGNCR */
126 # ifdef ICRNL
127     { "icrnl",  ICRNL,  M_INPUT },
128 # endif /* ICRNL */
129 # ifdef IUCLC
130     { "iuclc",  IUCLC,  M_INPUT },
131 # endif /* IUCLC */
132 # ifdef IXON
133     { "ixon",   IXON,   M_INPUT },
134 # endif /* IXON */
135 # ifdef IXANY
136     { "ixany",  IXANY,  M_INPUT },
137 # endif /* IXANY */
138 # ifdef IXOFF
139     { "ixoff",  IXOFF,  M_INPUT },
140 # endif /* IXOFF */
141 # ifdef  IMAXBEL
142     { "imaxbel",IMAXBEL,M_INPUT },
143 # endif /* IMAXBEL */
144 # ifdef  IDELETE
145     { "idelete",IDELETE,M_INPUT },
146 # endif /* IDELETE */
147
148 # ifdef OPOST
149     { "opost",  OPOST,  M_OUTPUT },
150 # endif /* OPOST */
151 # ifdef OLCUC
152     { "olcuc",  OLCUC,  M_OUTPUT },
153 # endif /* OLCUC */
154 # ifdef ONLCR
155     { "onlcr",  ONLCR,  M_OUTPUT },
156 # endif /* ONLCR */
157 # ifdef OCRNL
158     { "ocrnl",  OCRNL,  M_OUTPUT },
159 # endif /* OCRNL */
160 # ifdef ONOCR
161     { "onocr",  ONOCR,  M_OUTPUT },
162 # endif /* ONOCR */
163 # ifdef ONOEOT
164     { "onoeot", ONOEOT, M_OUTPUT },
165 # endif /* ONOEOT */
166 # ifdef ONLRET
167     { "onlret", ONLRET, M_OUTPUT },
168 # endif /* ONLRET */
169 # ifdef OFILL
170     { "ofill",  OFILL,  M_OUTPUT },
171 # endif /* OFILL */
172 # ifdef OFDEL
173     { "ofdel",  OFDEL,  M_OUTPUT },
174 # endif /* OFDEL */
175 # ifdef NLDLY
176     { "nldly",  NLDLY,  M_OUTPUT },
177 # endif /* NLDLY */
178 # ifdef CRDLY
179     { "crdly",  CRDLY,  M_OUTPUT },
180 # endif /* CRDLY */
181 # ifdef TABDLY
182     { "tabdly", TABDLY, M_OUTPUT },
183 # endif /* TABDLY */
184 # ifdef XTABS
185     { "xtabs",  XTABS,  M_OUTPUT },
186 # endif /* XTABS */
187 # ifdef BSDLY
188     { "bsdly",  BSDLY,  M_OUTPUT },
189 # endif /* BSDLY */
190 # ifdef VTDLY
191     { "vtdly",  VTDLY,  M_OUTPUT },
192 # endif /* VTDLY */
193 # ifdef FFDLY
194     { "ffdly",  FFDLY,  M_OUTPUT },
195 # endif /* FFDLY */
196 # ifdef PAGEOUT
197     { "pageout",PAGEOUT,M_OUTPUT },
198 # endif /* PAGEOUT */
199 # ifdef WRAP
200     { "wrap",   WRAP,   M_OUTPUT },
201 # endif /* WRAP */
202
203 # ifdef CIGNORE
204     { "cignore",CIGNORE,M_CONTROL },
205 # endif /* CBAUD */
206 # ifdef CBAUD
207     { "cbaud",  CBAUD,  M_CONTROL },
208 # endif /* CBAUD */
209 # ifdef CSTOPB
210     { "cstopb", CSTOPB, M_CONTROL },
211 # endif /* CSTOPB */
212 # ifdef CREAD
213     { "cread",  CREAD,  M_CONTROL },
214 # endif /* CREAD */
215 # ifdef PARENB
216     { "parenb", PARENB, M_CONTROL },
217 # endif /* PARENB */
218 # ifdef PARODD
219     { "parodd", PARODD, M_CONTROL },
220 # endif /* PARODD */
221 # ifdef HUPCL
222     { "hupcl",  HUPCL,  M_CONTROL },
223 # endif /* HUPCL */
224 # ifdef CLOCAL
225     { "clocal", CLOCAL, M_CONTROL },
226 # endif /* CLOCAL */
227 # ifdef LOBLK
228     { "loblk",  LOBLK,  M_CONTROL },
229 # endif /* LOBLK */
230 # ifdef CIBAUD
231     { "cibaud", CIBAUD, M_CONTROL },
232 # endif /* CIBAUD */
233 # ifdef CRTSCTS
234 #  ifdef CCTS_OFLOW
235     { "ccts_oflow",CCTS_OFLOW,M_CONTROL },
236 #  else
237     { "crtscts",CRTSCTS,M_CONTROL },
238 #  endif /* CCTS_OFLOW */
239 # endif /* CRTSCTS */
240 # ifdef CRTS_IFLOW
241     { "crts_iflow",CRTS_IFLOW,M_CONTROL },
242 # endif /* CRTS_IFLOW */
243 # ifdef MDMBUF
244     { "mdmbuf", MDMBUF, M_CONTROL },
245 # endif /* MDMBUF */
246 # ifdef RCV1EN
247     { "rcv1en", RCV1EN, M_CONTROL },
248 # endif /* RCV1EN */
249 # ifdef XMT1EN
250     { "xmt1en", XMT1EN, M_CONTROL },
251 # endif /* XMT1EN */
252
253 # ifdef ISIG
254     { "isig",   ISIG,   M_LINED },
255 # endif /* ISIG */
256 # ifdef ICANON
257     { "icanon", ICANON, M_LINED },
258 # endif /* ICANON */
259 # ifdef XCASE
260     { "xcase",  XCASE,  M_LINED },
261 # endif /* XCASE */
262 # ifdef ECHO
263     { "echo",   ECHO,   M_LINED },
264 # endif /* ECHO */
265 # ifdef ECHOE
266     { "echoe",  ECHOE,  M_LINED },
267 # endif /* ECHOE */
268 # ifdef ECHOK
269     { "echok",  ECHOK,  M_LINED },
270 # endif /* ECHOK */
271 # ifdef ECHONL
272     { "echonl", ECHONL, M_LINED },
273 # endif /* ECHONL */
274 # ifdef NOFLSH
275     { "noflsh", NOFLSH, M_LINED },
276 # endif /* NOFLSH */
277 # ifdef TOSTOP
278     { "tostop", TOSTOP, M_LINED },
279 # endif /* TOSTOP */
280 # ifdef ECHOCTL
281     { "echoctl",ECHOCTL,M_LINED },
282 # endif /* ECHOCTL */
283 # ifdef ECHOPRT
284     { "echoprt",ECHOPRT,M_LINED },
285 # endif /* ECHOPRT */
286 # ifdef ECHOKE
287     { "echoke", ECHOKE, M_LINED },
288 # endif /* ECHOKE */
289 # ifdef DEFECHO
290     { "defecho",DEFECHO,M_LINED },
291 # endif /* DEFECHO */
292 # ifdef FLUSHO
293     { "flusho", FLUSHO, M_LINED },
294 # endif /* FLUSHO */
295 # ifdef PENDIN
296     { "pendin", PENDIN, M_LINED },
297 # endif /* PENDIN */
298 # ifdef IEXTEN
299     { "iexten", IEXTEN, M_LINED },
300 # endif /* IEXTEN */
301 # ifdef NOKERNINFO
302     { "nokerninfo",NOKERNINFO,M_LINED },
303 # endif /* NOKERNINFO */
304 # ifdef ALTWERASE
305     { "altwerase",ALTWERASE,M_LINED },
306 # endif /* ALTWERASE */
307 # ifdef EXTPROC
308     { "extproc",EXTPROC,M_LINED },
309 # endif /* EXTPROC */
310 # ifdef IDEFAULT
311     { "idefault",IDEFAULT,M_LINED },
312 # endif /* IDEFAULT */
313
314 #else /* GSTTY */
315
316 # ifdef TANDEM
317     { "tandem", TANDEM, M_CONTROL },
318 # endif /* TANDEM */
319 # ifdef CBREAK
320     { "cbreak", CBREAK, M_CONTROL },
321 # endif /* CBREAK */
322 # ifdef LCASE
323     { "lcase",  LCASE,  M_CONTROL },
324 # endif /* LCASE */
325 # ifdef ECHO
326     { "echo",   ECHO,   M_CONTROL },
327 # endif /* ECHO */      
328 # ifdef CRMOD
329     { "crmod",  CRMOD,  M_CONTROL },
330 # endif /* CRMOD */
331 # ifdef RAW
332     { "raw",    RAW,    M_CONTROL },
333 # endif /* RAW */
334 # ifdef ODDP
335     { "oddp",   ODDP,   M_CONTROL },
336 # endif /* ODDP */
337 # ifdef EVENP
338     { "evenp",  EVENP,  M_CONTROL },
339 # endif /* EVENP */
340 # ifdef ANYP
341     { "anyp",   ANYP,   M_CONTROL },
342 # endif /* ANYP */
343 # ifdef NLDELAY
344     { "nldelay",NLDELAY,M_CONTROL },
345 # endif /* NLDELAY */
346 # ifdef TBDELAY
347     { "tbdelay",TBDELAY,M_CONTROL },
348 # endif /* TBDELAY */
349 # ifdef XTABS
350     { "xtabs",  XTABS,  M_CONTROL },
351 # endif /* XTABS */
352 # ifdef CRDELAY
353     { "crdelay",CRDELAY,M_CONTROL },
354 # endif /* CRDELAY */
355 # ifdef VTDELAY
356     { "vtdelay",VTDELAY,M_CONTROL },
357 # endif /* VTDELAY */
358 # ifdef BSDELAY
359     { "bsdelay",BSDELAY,M_CONTROL },
360 # endif /* BSDELAY */
361 # ifdef CRTBS
362     { "crtbs",  CRTBS,  M_CONTROL },
363 # endif /* CRTBS */
364 # ifdef PRTERA
365     { "prtera", PRTERA, M_CONTROL },
366 # endif /* PRTERA */
367 # ifdef CRTERA
368     { "crtera", CRTERA, M_CONTROL },
369 # endif /* CRTERA */
370 # ifdef TILDE
371     { "tilde",  TILDE,  M_CONTROL },
372 # endif /* TILDE */
373 # ifdef MDMBUF
374     { "mdmbuf", MDMBUF, M_CONTROL },
375 # endif /* MDMBUF */
376 # ifdef LITOUT
377     { "litout", LITOUT, M_CONTROL },
378 # endif /* LITOUT */
379 # ifdef TOSTOP
380     { "tostop", TOSTOP, M_CONTROL },
381 # endif /* TOSTOP */
382 # ifdef FLUSHO
383     { "flusho", FLUSHO, M_CONTROL },
384 # endif /* FLUSHO */
385 # ifdef NOHANG
386     { "nohang", NOHANG, M_CONTROL },
387 # endif /* NOHANG */
388 # ifdef L001000
389     { "l001000",L001000,M_CONTROL },
390 # endif /* L001000 */
391 # ifdef CRTKIL
392     { "crtkil", CRTKIL, M_CONTROL },
393 # endif /* CRTKIL */
394 # ifdef PASS8
395     { "pass8",  PASS8,  M_CONTROL },
396 # endif /* PASS8 */
397 # ifdef CTLECH
398     { "ctlech", CTLECH, M_CONTROL },
399 # endif /* CTLECH */
400 # ifdef PENDIN
401     { "pendin", PENDIN, M_CONTROL },
402 # endif /* PENDIN */
403 # ifdef DECCTQ
404     { "decctq", DECCTQ, M_CONTROL },
405 # endif /* DECCTQ */
406 # ifdef NOFLSH
407     { "noflsh", NOFLSH, M_CONTROL },
408 # endif /* NOFLSH */
409
410 # ifdef LCRTBS
411     { "lcrtbs", LCRTBS, M_LOCAL },
412 # endif /* LCRTBS */
413 # ifdef LPRTERA
414     { "lprtera",LPRTERA,M_LOCAL },
415 # endif /* LPRTERA */
416 # ifdef LCRTERA
417     { "lcrtera",LCRTERA,M_LOCAL },
418 # endif /* LCRTERA */
419 # ifdef LTILDE
420     { "ltilde", LTILDE, M_LOCAL },
421 # endif /* LTILDE */
422 # ifdef LMDMBUF
423     { "lmdmbuf",LMDMBUF,M_LOCAL },
424 # endif /* LMDMBUF */
425 # ifdef LLITOUT
426     { "llitout",LLITOUT,M_LOCAL },
427 # endif /* LLITOUT */
428 # ifdef LTOSTOP
429     { "ltostop",LTOSTOP,M_LOCAL },
430 # endif /* LTOSTOP */
431 # ifdef LFLUSHO
432     { "lflusho",LFLUSHO,M_LOCAL },
433 # endif /* LFLUSHO */
434 # ifdef LNOHANG
435     { "lnohang",LNOHANG,M_LOCAL },
436 # endif /* LNOHANG */
437 # ifdef LCRTKIL
438     { "lcrtkil",LCRTKIL,M_LOCAL },
439 # endif /* LCRTKIL */
440 # ifdef LPASS8
441     { "lpass8", LPASS8, M_LOCAL },
442 # endif /* LPASS8 */    
443 # ifdef LCTLECH
444     { "lctlech",LCTLECH,M_LOCAL },
445 # endif /* LCTLECH */
446 # ifdef LPENDIN
447     { "lpendin",LPENDIN,M_LOCAL },
448 # endif /* LPENDIN */
449 # ifdef LDECCTQ
450     { "ldecctq",LDECCTQ,M_LOCAL },
451 # endif /* LDECCTQ */
452 # ifdef LNOFLSH
453     { "lnoflsh",LNOFLSH,M_LOCAL },
454 # endif /* LNOFLSH */
455
456 #endif /* POSIX || TERMIO */
457 # if defined(VINTR) || defined(TIOCGETC)
458     { "intr",           C_SH(C_INTR),   M_CHAR },
459 # endif /* VINTR */
460 # if defined(VQUIT) || defined(TIOCGETC)
461     { "quit",           C_SH(C_QUIT),   M_CHAR },
462 # endif /* VQUIT */
463 # if defined(VERASE) || defined(TIOCGETP)
464     { "erase",          C_SH(C_ERASE),  M_CHAR },
465 # endif /* VERASE */
466 # if defined(VKILL) || defined(TIOCGETP)
467     { "kill",           C_SH(C_KILL),   M_CHAR },
468 # endif /* VKILL */
469 # if defined(VEOF) || defined(TIOCGETC)
470     { "eof",            C_SH(C_EOF),    M_CHAR },
471 # endif /* VEOF */
472 # if defined(VEOL)
473     { "eol",            C_SH(C_EOL),    M_CHAR },
474 # endif /* VEOL */
475 # if defined(VEOL2)
476     { "eol2",           C_SH(C_EOL2),   M_CHAR },
477 # endif  /* VEOL2 */
478 # if defined(VSWTCH)
479     { "swtch",          C_SH(C_SWTCH),  M_CHAR },
480 # endif /* VSWTCH */
481 # if defined(VDSWTCH)
482     { "dswtch",         C_SH(C_DSWTCH), M_CHAR },
483 # endif /* VDSWTCH */
484 # if defined(VERASE2)
485     { "erase2",         C_SH(C_ERASE2), M_CHAR },
486 # endif /* VERASE2 */
487 # if defined(VSTART) || defined(TIOCGETC)
488     { "start",          C_SH(C_START),  M_CHAR },
489 # endif /* VSTART */
490 # if defined(VSTOP) || defined(TIOCGETC)
491     { "stop",           C_SH(C_STOP),   M_CHAR },
492 # endif /* VSTOP */
493 # if defined(VWERASE) || defined(TIOCGLTC)
494     { "werase",         C_SH(C_WERASE), M_CHAR },
495 # endif /* VWERASE */
496 # if defined(VSUSP) || defined(TIOCGLTC)
497     { "susp",           C_SH(C_SUSP),   M_CHAR },
498 # endif /* VSUSP */
499 # if defined(VDSUSP) || defined(TIOCGLTC)
500     { "dsusp",          C_SH(C_DSUSP),  M_CHAR },
501 # endif /* VDSUSP */
502 # if defined(VREPRINT) || defined(TIOCGLTC)
503     { "reprint",        C_SH(C_REPRINT),M_CHAR },
504 # endif /* WREPRINT */
505 # if defined(VDISCARD) || defined(TIOCGLTC)
506     { "discard",        C_SH(C_DISCARD),M_CHAR },
507 # endif /* VDISCARD */
508 # if defined(VLNEXT) || defined(TIOCGLTC)
509     { "lnext",          C_SH(C_LNEXT),  M_CHAR },
510 # endif /* VLNEXT */
511 # if defined(VSTATUS) || defined(TIOCGPAGE)
512     { "status",         C_SH(C_STATUS), M_CHAR },
513 # endif /* VSTATUS */
514 # if defined(VCHECKPT) || defined(TIOCGPAGE)
515     { "ckpt",           C_SH(C_CHECKPT),M_CHAR },
516 # endif /* VSTATUS */
517 # if defined(VPAGE) || defined(TIOCGPAGE)
518     { "page",           C_SH(C_PAGE),   M_CHAR },
519 # endif /* VPAGE */
520 # if defined(VPGOFF) || defined(TIOCGPAGE)
521     { "pgoff",          C_SH(C_PGOFF),  M_CHAR },
522 # endif /* VPGOFF */
523 # if defined(VKILL2) 
524     { "kill2",          C_SH(C_KILL2),  M_CHAR },
525 # endif /* VKILL2 */
526 # if defined(VBRK) || defined(TIOCGETC)
527     { "brk",            C_SH(C_BRK),    M_CHAR },
528 # endif /* VBRK */
529 # if defined(VMIN)
530     { "min",            C_SH(C_MIN),    M_CHAR },
531 # endif /* VMIN */
532 # if defined(VTIME)
533     { "time",           C_SH(C_TIME),   M_CHAR },
534 # endif /* VTIME */
535     { NULL, 0, -1 },
536 };
537
538 /*
539  * If EAGAIN and/or EWOULDBLOCK are defined, we can't just return -1 in all
540  * situations where ioctl() does.
541  * 
542  * On AIX 4.1.5 (and presumably some other versions and OSes), as you
543  * perform the manual test suite in the README, if you 'bg' vi immediately
544  * after suspending it, all is well, but if you wait a few seconds,
545  * usually ioctl() will return -1, which previously caused tty_setty() to
546  * return -1, causing Rawmode() to return -1, causing Inputl() to return
547  * 0, causing bgetc() to return -1, causing readc() to set doneinp to 1,
548  * causing process() to break out of the main loop, causing tcsh to exit
549  * prematurely.
550  * 
551  * If ioctl()'s errno is EAGAIN/EWOULDBLOCK ("Resource temporarily
552  * unavailable"), apparently the tty is being messed with by the OS and we
553  * need to try again.  In my testing, ioctl() was never called more than
554  * twice in a row.
555  *
556  * -- Dan Harkless <dan@wave.eng.uci.edu>
557  *
558  * So, I retry all ioctl's in case others happen to fail too (christos)
559  */
560
561 #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
562 # define OKERROR(e) (((e) == EAGAIN) || ((e) == EWOULDBLOCK) || ((e) == EINTR))
563 #elif defined(EGAIN)
564 # define OKERROR(e) (((e) == EAGAIN) || ((e) == EINTR))
565 #elif defined(EWOULDBLOCK)
566 # define OKERROR(e) (((e) == EWOULDBLOCK) || ((e) == EINTR))
567 #else
568 # define OKERROR(e) ((e) == EINTR)
569 #endif
570
571 #ifdef __NetBSD__
572 #define KLUDGE (errno == ENOTTY && count < 10)
573 #else
574 #define KLUDGE 0
575 #endif
576
577 /* Retry a system call */
578 static int count;
579 #define RETRY(x) \
580    for (count = 0;; count++) \
581         if ((x) == -1) { \
582             if (OKERROR(errno) || KLUDGE) \
583                 continue; \
584             else \
585                 return -1; \
586         } \
587         else \
588            break \
589
590 /*ARGSUSED*/
591 void
592 dosetty(v, t)
593     Char **v;
594     struct command *t;
595 {
596     struct tcshmodes *m;
597     char x, *d;
598     int aflag = 0;
599     Char *s;
600     int z = EX_IO;
601     char cmdname[BUFSIZE];
602
603     USE(t);
604     setname(strcpy(cmdname, short2str(*v++)));
605
606     while (v && *v && v[0][0] == '-' && v[0][2] == '\0') 
607         switch (v[0][1]) {
608         case 'a':
609             aflag++;
610             v++;
611             break;
612         case 'd':
613             v++;
614             z = ED_IO;
615             break;
616         case 'x':
617             v++;
618             z = EX_IO;
619             break;
620         case 'q':
621             v++;
622             z = QU_IO;
623             break;
624         default:
625             stderror(ERR_NAME | ERR_SYSTEM, short2str(v[0]), 
626                      CGETS(8, 1, "Unknown switch"));
627             break;
628         }
629
630     didsetty = 1;
631     if (!v || !*v) {
632         int i = -1;
633         int len = 0, st = 0, cu;
634         for (m = modelist; m->m_name; m++) {
635             if (m->m_type != i) {
636                 xprintf("%s%s", i != -1 ? "\n" : "", 
637                         ttylist[z][m->m_type].t_name);
638                 i = m->m_type;
639                 st = len = strlen(ttylist[z][m->m_type].t_name);
640             }
641
642             x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0';
643             x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x;
644
645             if (x != '\0' || aflag) {
646                 cu = strlen(m->m_name) + (x != '\0') + 1;
647                 if (len + cu >= T_Cols) {
648                     xprintf("\n%*s", st, "");
649                     len = st + cu;
650                 }
651                 else 
652                     len += cu;
653                 if (x != '\0')
654                     xprintf("%c%s ", x, m->m_name);
655                 else
656                     xprintf("%s ", m->m_name);
657             }
658         }
659         xputchar('\n');
660         return;
661     }
662     while (v && (s = *v++)) {
663         switch (*s) {
664         case '+':
665         case '-':
666             x = *s++;
667             break;
668         default:
669             x = '\0';
670             break;
671         }
672         d = short2str(s);
673         for (m = modelist; m->m_name; m++)
674             if (strcmp(m->m_name, d) == 0)
675                 break;
676         if (!m->m_name) 
677             stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument"));
678
679         switch (x) {
680         case '+':
681             ttylist[z][m->m_type].t_setmask |= m->m_value;
682             ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
683             break;
684         case '-':
685             ttylist[z][m->m_type].t_setmask &= ~m->m_value;
686             ttylist[z][m->m_type].t_clrmask |= m->m_value;
687             break;
688         default:
689             ttylist[z][m->m_type].t_setmask &= ~m->m_value;
690             ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
691             break;
692         }
693     }
694 } /* end dosetty */
695
696 int
697 tty_getty(fd, td)
698    int fd;
699    ttydata_t *td;
700 {
701 #ifdef POSIX
702     RETRY(tcgetattr(fd, &td->d_t));
703 #else /* TERMIO || GSTTY */
704 # ifdef TERMIO
705     RETRY(ioctl(fd, TCGETA,    (ioctl_t) &td->d_t));
706 # else /* GSTTY */
707 #  ifdef TIOCGETP
708     RETRY(ioctl(fd, TIOCGETP,  (ioctl_t) &td->d_t));
709 #  endif /* TIOCGETP */
710 #  ifdef TIOCGETC
711     RETRY(ioctl(fd, TIOCGETC,  (ioctl_t) &td->d_tc));
712 #  endif /* TIOCGETC */
713 #  ifdef TIOCGPAGE
714     RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc));
715 #  endif /* TIOCGPAGE */
716 #  ifdef TIOCLGET
717     RETRY(ioctl(fd, TIOCLGET,  (ioctl_t) &td->d_lb));
718 #  endif /* TIOCLGET */
719 # endif /* TERMIO */
720 #endif /* POSIX */
721
722 #ifdef TIOCGLTC
723     RETRY(ioctl(fd, TIOCGLTC,  (ioctl_t) &td->d_ltc));
724 #endif /* TIOCGLTC */
725
726     return 0;
727 }
728
729 int
730 tty_setty(fd, td)
731    int fd;
732    ttydata_t *td;
733 {
734 #ifdef POSIX
735     RETRY(tcsetattr(fd, TCSADRAIN, &td->d_t)); 
736 #else
737 # ifdef TERMIO
738     RETRY(ioctl(fd, TCSETAW,    (ioctl_t) &td->d_t));
739 # else
740 #  ifdef TIOCSETN
741     RETRY(ioctl(fd, TIOCSETN,  (ioctl_t) &td->d_t));
742 #  endif /* TIOCSETN */
743 #  ifdef TIOCGETC
744     RETRY(ioctl(fd, TIOCSETC,  (ioctl_t) &td->d_tc));
745 #  endif /* TIOCGETC */
746 #  ifdef TIOCGPAGE
747     RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc));
748 #  endif /* TIOCGPAGE */
749 #  ifdef TIOCLGET
750     RETRY(ioctl(fd, TIOCLSET,  (ioctl_t) &td->d_lb));
751 #  endif /* TIOCLGET */
752 # endif /* TERMIO */
753 #endif /* POSIX */
754
755 #ifdef TIOCGLTC
756     RETRY(ioctl(fd, TIOCSLTC,  (ioctl_t) &td->d_ltc));
757 #endif /* TIOCGLTC */
758
759     return 0;
760 }
761
762 void
763 tty_getchar(td, s)
764     ttydata_t *td;
765     unsigned char *s;
766 {   
767 #ifdef TIOCGLTC
768     {
769         struct ltchars *n = &td->d_ltc;
770
771         s[C_SUSP]       = n->t_suspc;
772         s[C_DSUSP]      = n->t_dsuspc;
773         s[C_REPRINT]    = n->t_rprntc;
774         s[C_DISCARD]    = n->t_flushc;
775         s[C_WERASE]     = n->t_werasc;
776         s[C_LNEXT]      = n->t_lnextc;
777     }
778 #endif /* TIOCGLTC */
779
780 #if defined(POSIX) || defined(TERMIO)
781     {
782 # ifdef POSIX
783         struct termios *n = &td->d_t;
784 # else
785         struct termio *n = &td->d_t;
786 # endif /* POSIX */
787
788 # ifdef VINTR
789         s[C_INTR]       = n->c_cc[VINTR];
790 # endif /* VINTR */
791 # ifdef VQUIT
792         s[C_QUIT]       = n->c_cc[VQUIT];
793 # endif /* VQUIT */
794 # ifdef VERASE
795         s[C_ERASE]      = n->c_cc[VERASE];
796 # endif /* VERASE */
797 # ifdef VKILL
798         s[C_KILL]       = n->c_cc[VKILL];
799 # endif /* VKILL */
800 # ifdef VEOF
801         s[C_EOF]        = n->c_cc[VEOF];
802 # endif /* VEOF */
803 # ifdef VEOL
804         s[C_EOL]        = n->c_cc[VEOL];
805 # endif /* VEOL */
806 # ifdef VEOL2
807         s[C_EOL2]       = n->c_cc[VEOL2];
808 # endif  /* VEOL2 */
809 # ifdef VSWTCH
810         s[C_SWTCH]      = n->c_cc[VSWTCH];
811 # endif /* VSWTCH */
812 # ifdef VDSWTCH
813         s[C_DSWTCH]     = n->c_cc[VDSWTCH];
814 # endif /* VDSWTCH */
815 # ifdef VERASE2
816         s[C_ERASE2]     = n->c_cc[VERASE2];
817 # endif /* VERASE2 */
818 # ifdef VSTART
819         s[C_START]      = n->c_cc[VSTART];
820 # endif /* VSTART */
821 # ifdef VSTOP
822         s[C_STOP]       = n->c_cc[VSTOP];
823 # endif /* VSTOP */
824 # ifdef VWERASE
825         s[C_WERASE]     = n->c_cc[VWERASE];
826 # endif /* VWERASE */
827 # ifdef VSUSP
828         s[C_SUSP]       = n->c_cc[VSUSP];
829 # endif /* VSUSP */
830 # ifdef VDSUSP
831         s[C_DSUSP]      = n->c_cc[VDSUSP];
832 # endif /* VDSUSP */
833 # ifdef VREPRINT
834         s[C_REPRINT]    = n->c_cc[VREPRINT];
835 # endif /* WREPRINT */
836 # ifdef VDISCARD
837         s[C_DISCARD]    = n->c_cc[VDISCARD];
838 # endif /* VDISCARD */
839 # ifdef VLNEXT
840         s[C_LNEXT]      = n->c_cc[VLNEXT];
841 # endif /* VLNEXT */
842 # ifdef VSTATUS
843         s[C_STATUS]     = n->c_cc[VSTATUS];
844 # endif /* VSTATUS */
845 # ifdef VCHECKPT
846         s[C_CHECKPT]    = n->c_cc[VCHECKPT];
847 # endif /* VCHECKPT */
848 # ifdef VPAGE
849         s[C_PAGE]       = n->c_cc[VPAGE];
850 # endif /* VPAGE */
851 # ifdef VPGOFF
852         s[C_PGOFF]      = n->c_cc[VPGOFF];
853 # endif /* VPGOFF */
854 # ifdef VKILL2
855         s[C_KILL2]      = n->c_cc[VKILL2];
856 # endif /* KILL2 */
857 # ifdef VMIN
858         s[C_MIN]        = n->c_cc[VMIN];
859 # endif /* VMIN */
860 # ifdef VTIME
861         s[C_TIME]       = n->c_cc[VTIME];
862 # endif /* VTIME */
863     }
864
865 #else /* SGTTY */
866
867 # ifdef TIOCGPAGE
868     {
869         struct ttypagestat *n = &td->d_pc;
870
871         s[C_STATUS]     = n->tps_statc;
872         s[C_CHECKPT]    = n->tps_checkp;
873         s[C_PAGE]       = n->tps_pagec;
874         s[C_PGOFF]      = n->tps_pgoffc;
875     }
876 # endif /* TIOCGPAGE */
877
878 # ifdef TIOCGETC
879     {
880         struct tchars *n = &td->d_tc;
881
882         s[C_INTR]       = n->t_intrc;
883         s[C_QUIT]       = n->t_quitc;
884         s[C_START]      = n->t_startc;
885         s[C_STOP]       = n->t_stopc;
886         s[C_EOF]        = n->t_eofc;
887         s[C_BRK]        = n->t_brkc;
888     }
889 # endif /* TIOCGETC */
890
891 # ifdef TIOCGETP
892     {
893         struct sgttyb *n = &td->d_t;
894
895         s[C_ERASE]      = n->sg_erase;
896         s[C_KILL]       = n->sg_kill;
897     }
898 # endif /* TIOCGETP */
899 #endif /* !POSIX || TERMIO */
900
901 } /* tty_getchar */
902
903
904 void
905 tty_setchar(td, s)
906     ttydata_t *td;
907     unsigned char *s;
908 {   
909 #ifdef TIOCGLTC
910     {
911         struct ltchars *n = &td->d_ltc; 
912
913         n->t_suspc              = s[C_SUSP];
914         n->t_dsuspc             = s[C_DSUSP];
915         n->t_rprntc             = s[C_REPRINT];
916         n->t_flushc             = s[C_DISCARD];
917         n->t_werasc             = s[C_WERASE];
918         n->t_lnextc             = s[C_LNEXT];
919     }
920 #endif /* TIOCGLTC */
921
922 #if defined(POSIX) || defined(TERMIO)
923     {
924 # ifdef POSIX
925         struct termios *n = &td->d_t;
926 # else
927         struct termio *n = &td->d_t;
928 # endif /* POSIX */
929
930 # ifdef VINTR
931         n->c_cc[VINTR]          = s[C_INTR];
932 # endif /* VINTR */
933 # ifdef VQUIT
934         n->c_cc[VQUIT]          = s[C_QUIT];
935 # endif /* VQUIT */
936 # ifdef VERASE
937         n->c_cc[VERASE]         = s[C_ERASE];
938 # endif /* VERASE */
939 # ifdef VKILL
940         n->c_cc[VKILL]          = s[C_KILL];
941 # endif /* VKILL */
942 # ifdef VEOF
943         n->c_cc[VEOF]           = s[C_EOF];
944 # endif /* VEOF */
945 # ifdef VEOL
946         n->c_cc[VEOL]           = s[C_EOL];
947 # endif /* VEOL */
948 # ifdef VEOL2
949         n->c_cc[VEOL2]          = s[C_EOL2];
950 # endif  /* VEOL2 */
951 # ifdef VSWTCH
952         n->c_cc[VSWTCH]         = s[C_SWTCH];
953 # endif /* VSWTCH */
954 # ifdef VDSWTCH
955         n->c_cc[VDSWTCH]        = s[C_DSWTCH];
956 # endif /* VDSWTCH */
957 # ifdef VERASE2
958         n->c_cc[VERASE2]        = s[C_ERASE2];
959 # endif /* VERASE2 */
960 # ifdef VSTART
961         n->c_cc[VSTART]         = s[C_START];
962 # endif /* VSTART */
963 # ifdef VSTOP
964         n->c_cc[VSTOP]          = s[C_STOP];
965 # endif /* VSTOP */
966 # ifdef VWERASE
967         n->c_cc[VWERASE]        = s[C_WERASE];
968 # endif /* VWERASE */
969 # ifdef VSUSP
970         n->c_cc[VSUSP]          = s[C_SUSP];
971 # endif /* VSUSP */
972 # ifdef VDSUSP
973         n->c_cc[VDSUSP]         = s[C_DSUSP];
974 # endif /* VDSUSP */
975 # ifdef VREPRINT
976         n->c_cc[VREPRINT]       = s[C_REPRINT];
977 # endif /* WREPRINT */
978 # ifdef VDISCARD
979         n->c_cc[VDISCARD]       = s[C_DISCARD];
980 # endif /* VDISCARD */
981 # ifdef VLNEXT
982         n->c_cc[VLNEXT]         = s[C_LNEXT];
983 # endif /* VLNEXT */
984 # ifdef VSTATUS
985         n->c_cc[VSTATUS]        = s[C_STATUS];
986 # endif /* VSTATUS */
987 # ifdef VCHECKPT
988         n->c_cc[VCHECKPT]       = s[C_CHECKPT];
989 # endif /* VCHECKPT */
990 # ifdef VPAGE
991         n->c_cc[VPAGE]          = s[C_PAGE];
992 # endif /* VPAGE */
993 # ifdef VPGOFF
994         n->c_cc[VPGOFF]         = s[C_PGOFF];
995 # endif /* VPGOFF */
996 # ifdef VKILL2
997         n->c_cc[VKILL2]         = s[C_KILL2];
998 # endif /* VKILL2 */
999 # ifdef VMIN
1000         n->c_cc[VMIN]           = s[C_MIN];
1001 # endif /* VMIN */
1002 # ifdef VTIME
1003         n->c_cc[VTIME]          = s[C_TIME];
1004 # endif /* VTIME */
1005     }
1006
1007 #else /* GSTTY */
1008
1009 # ifdef TIOCGPAGE
1010     {
1011         struct ttypagestat *n = &td->d_pc;
1012
1013         n->tps_length           = 0;
1014         n->tps_lpos             = 0;
1015         n->tps_statc            = s[C_STATUS];
1016         n->tps_pagec            = s[C_PAGE];
1017         n->tps_pgoffc           = s[C_PGOFF];
1018         n->tps_flag             = 0;
1019     }
1020 # endif /* TIOCGPAGE */
1021
1022 # ifdef TIOCGETC
1023     {
1024         struct tchars *n = &td->d_tc;
1025         n->t_intrc              = s[C_INTR];
1026         n->t_quitc              = s[C_QUIT];
1027         n->t_startc             = s[C_START];
1028         n->t_stopc              = s[C_STOP];
1029         n->t_eofc               = s[C_EOF];
1030         n->t_brkc               = s[C_BRK];
1031     }
1032 # endif /* TIOCGETC */
1033
1034 # ifdef TIOCGETP
1035     {
1036         struct sgttyb *n = &td->d_t;
1037
1038         n->sg_erase             = s[C_ERASE];
1039         n->sg_kill              = s[C_KILL];
1040     }
1041 # endif /* TIOCGETP */
1042 #endif /* !POSIX || TERMIO */
1043
1044 } /* tty_setchar */
1045
1046 speed_t
1047 tty_getspeed(td)
1048     ttydata_t *td;
1049 {
1050     speed_t spd;
1051
1052 #ifdef POSIX
1053     if ((spd = cfgetispeed(&td->d_t)) == 0)
1054         spd = cfgetospeed(&td->d_t);
1055 #else /* ! POSIX */
1056 # ifdef TERMIO
1057 #  ifdef CBAUD
1058     spd = td->d_t.c_cflag & CBAUD;
1059 #  else 
1060     spd = 0;
1061 #  endif 
1062 # else /* SGTTY */
1063     spd = td->d_t.sg_ispeed;
1064 # endif /* TERMIO */
1065 #endif /* POSIX */
1066
1067     return spd;
1068 } /* end tty_getspeed */
1069
1070 int
1071 tty_gettabs(td)
1072     ttydata_t *td;
1073 {
1074 #if defined(POSIX) || defined(TERMIO)
1075     return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1;
1076 #else /* SGTTY */
1077     return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1;
1078 #endif /* POSIX || TERMIO */
1079 } /* end tty_gettabs */
1080
1081 int
1082 tty_geteightbit(td)
1083     ttydata_t *td;
1084 {
1085 #if defined(POSIX) || defined(TERMIO)
1086     return (td->d_t.c_cflag & CSIZE) == CS8;
1087 #else /* SGTTY */
1088     return td->d_lb & (LPASS8 | LLITOUT);
1089 #endif /* POSIX || TERMIO */
1090 } /* end tty_geteightbit */
1091
1092 int
1093 tty_cooked_mode(td)
1094     ttydata_t *td;
1095 {
1096 #if defined(POSIX) || defined(TERMIO)
1097     return (td->d_t.c_lflag & ICANON);
1098 #else /* SGTTY */
1099     return !(td->d_t.sg_flags & (RAW | CBREAK));
1100 #endif /* POSIX || TERMIO */
1101 } /* end tty_cooked_mode */
1102
1103 #ifdef _IBMR2
1104 void
1105 tty_setdisc(fd, dis)
1106     int fd;
1107     int dis;
1108 {
1109     static bool edit_discipline = 0;
1110     static union txname tx_disc;
1111     extern char strPOSIX[];
1112
1113     switch (dis) {
1114     case EX_IO:
1115         if (edit_discipline) {
1116             if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1)
1117                 return;
1118             edit_discipline = 0;
1119         }
1120         return;
1121
1122     case ED_IO:
1123         tx_disc.tx_which = 0;
1124         if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1)
1125             return;
1126         if (strcmp(tx_disc.tx_name, strPOSIX) != 0) {
1127             edit_discipline = 1;
1128             if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1)
1129             return;
1130         }
1131         return;
1132
1133     default:
1134         return;
1135     }
1136 } /* end tty_setdisc */
1137 #endif /* _IBMR2 */
1138
1139 #ifdef DEBUG_TTY
1140 static void
1141 tty_printchar(s)
1142     unsigned char *s;
1143 {
1144     struct tcshmodes *m;
1145     int i;
1146
1147     for (i = 0; i < C_NCC; i++) {
1148         for (m = modelist; m->m_name; m++) 
1149             if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
1150                 break;
1151         if (m->m_name)
1152             xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1);
1153         if (i % 5 == 0)
1154             xputchar('\n');
1155     }
1156     xputchar('\n');
1157 }
1158 #endif /* DEBUG_TTY */
1159 #else /* WINNT_NATIVE */
1160 int
1161 tty_cooked_mode(td)
1162     void *td;
1163 {
1164     return do_nt_check_cooked_mode();
1165 }
1166 #endif /* !WINNT_NATIVE */