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