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