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