xref: /freebsd/contrib/tcsh/ed.term.c (revision fcb560670601b2a4d87bb31d7531c8dcc37ee71b)
1 /* $Header: /p/tcsh/cvsroot/tcsh/ed.term.c,v 1.38 2011/02/25 23:58:34 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.38 2011/02/25 23:58:34 christos Exp $")
37 #include <assert.h>
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 	    assert(i != -1);
637 
638 	    x = (ttylist[z][i].t_setmask & m->m_value) ? '+' : '\0';
639 	    x = (ttylist[z][i].t_clrmask & m->m_value) ? '-' : x;
640 
641 	    if (x != '\0' || aflag) {
642 		cu = strlen(m->m_name) + (x != '\0') + 1;
643 		if (len + cu >= TermH) {
644 		    xprintf("\n%*s", st, "");
645 		    len = st + cu;
646 		}
647 		else
648 		    len += cu;
649 		if (x != '\0')
650 		    xprintf("%c%s ", x, m->m_name);
651 		else
652 		    xprintf("%s ", m->m_name);
653 	    }
654 	}
655 	xputchar('\n');
656 	cleanup_until(cmdname);
657 	return;
658     }
659     while (v && (s = *v++)) {
660 	switch (*s) {
661 	case '+':
662 	case '-':
663 	    x = *s++;
664 	    break;
665 	default:
666 	    x = '\0';
667 	    break;
668 	}
669 	d = short2str(s);
670 	for (m = modelist; m->m_name; m++)
671 	    if (strcmp(m->m_name, d) == 0)
672 		break;
673 	if (!m->m_name)
674 	    stderror(ERR_NAME | ERR_SYSTEM, d, CGETS(8, 2, "Invalid argument"));
675 
676 	switch (x) {
677 	case '+':
678 	    ttylist[z][m->m_type].t_setmask |= m->m_value;
679 	    ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
680 	    break;
681 	case '-':
682 	    ttylist[z][m->m_type].t_setmask &= ~m->m_value;
683 	    ttylist[z][m->m_type].t_clrmask |= m->m_value;
684 	    break;
685 	default:
686 	    ttylist[z][m->m_type].t_setmask &= ~m->m_value;
687 	    ttylist[z][m->m_type].t_clrmask &= ~m->m_value;
688 	    break;
689 	}
690     }
691     cleanup_until(cmdname);
692 } /* end dosetty */
693 
694 int
695 tty_getty(int fd, ttydata_t *td)
696 {
697 #ifdef POSIX
698     RETRY(tcgetattr(fd, &td->d_t));
699 #else /* TERMIO || GSTTY */
700 # ifdef TERMIO
701     RETRY(ioctl(fd, TCGETA,    (ioctl_t) &td->d_t));
702 # else /* GSTTY */
703 #  ifdef TIOCGETP
704     RETRY(ioctl(fd, TIOCGETP,  (ioctl_t) &td->d_t));
705 #  endif /* TIOCGETP */
706 #  ifdef TIOCGETC
707     RETRY(ioctl(fd, TIOCGETC,  (ioctl_t) &td->d_tc));
708 #  endif /* TIOCGETC */
709 #  ifdef TIOCGPAGE
710     RETRY(ioctl(fd, TIOCGPAGE, (ioctl_t) &td->d_pc));
711 #  endif /* TIOCGPAGE */
712 #  ifdef TIOCLGET
713     RETRY(ioctl(fd, TIOCLGET,  (ioctl_t) &td->d_lb));
714 #  endif /* TIOCLGET */
715 # endif /* TERMIO */
716 #endif /* POSIX */
717 
718 #ifdef TIOCGLTC
719     RETRY(ioctl(fd, TIOCGLTC,  (ioctl_t) &td->d_ltc));
720 #endif /* TIOCGLTC */
721 
722     return 0;
723 }
724 
725 int
726 tty_setty(int fd, ttydata_t *td)
727 {
728 #ifdef POSIX
729     RETRY(xtcsetattr(fd, TCSADRAIN, &td->d_t));
730 #else
731 # ifdef TERMIO
732     RETRY(ioctl(fd, TCSETAW,    (ioctl_t) &td->d_t));
733 # else
734 #  ifdef TIOCSETN
735     RETRY(ioctl(fd, TIOCSETN,  (ioctl_t) &td->d_t));
736 #  endif /* TIOCSETN */
737 #  ifdef TIOCGETC
738     RETRY(ioctl(fd, TIOCSETC,  (ioctl_t) &td->d_tc));
739 #  endif /* TIOCGETC */
740 #  ifdef TIOCGPAGE
741     RETRY(ioctl(fd, TIOCSPAGE, (ioctl_t) &td->d_pc));
742 #  endif /* TIOCGPAGE */
743 #  ifdef TIOCLGET
744     RETRY(ioctl(fd, TIOCLSET,  (ioctl_t) &td->d_lb));
745 #  endif /* TIOCLGET */
746 # endif /* TERMIO */
747 #endif /* POSIX */
748 
749 #ifdef TIOCGLTC
750     RETRY(ioctl(fd, TIOCSLTC,  (ioctl_t) &td->d_ltc));
751 #endif /* TIOCGLTC */
752 
753     return 0;
754 }
755 
756 void
757 tty_getchar(ttydata_t *td, unsigned char *s)
758 {
759 #ifdef TIOCGLTC
760     {
761 	struct ltchars *n = &td->d_ltc;
762 
763 	s[C_SUSP]	= n->t_suspc;
764 	s[C_DSUSP]	= n->t_dsuspc;
765 	s[C_REPRINT]	= n->t_rprntc;
766 	s[C_DISCARD]	= n->t_flushc;
767 	s[C_WERASE]	= n->t_werasc;
768 	s[C_LNEXT]	= n->t_lnextc;
769     }
770 #endif /* TIOCGLTC */
771 
772 #if defined(POSIX) || defined(TERMIO)
773     {
774 # ifdef POSIX
775 	struct termios *n = &td->d_t;
776 # else
777 	struct termio *n = &td->d_t;
778 # endif /* POSIX */
779 
780 # ifdef VINTR
781 	s[C_INTR]	= n->c_cc[VINTR];
782 # endif /* VINTR */
783 # ifdef VQUIT
784 	s[C_QUIT]	= n->c_cc[VQUIT];
785 # endif /* VQUIT */
786 # ifdef VERASE
787 	s[C_ERASE]	= n->c_cc[VERASE];
788 # endif /* VERASE */
789 # ifdef VKILL
790 	s[C_KILL]	= n->c_cc[VKILL];
791 # endif /* VKILL */
792 # ifdef VEOF
793 	s[C_EOF]	= n->c_cc[VEOF];
794 # endif /* VEOF */
795 # ifdef VEOL
796 	s[C_EOL]	= n->c_cc[VEOL];
797 # endif /* VEOL */
798 # ifdef VEOL2
799 	s[C_EOL2]	= n->c_cc[VEOL2];
800 # endif  /* VEOL2 */
801 # ifdef VSWTCH
802 	s[C_SWTCH]	= n->c_cc[VSWTCH];
803 # endif /* VSWTCH */
804 # ifdef VDSWTCH
805 	s[C_DSWTCH]	= n->c_cc[VDSWTCH];
806 # endif /* VDSWTCH */
807 # ifdef VERASE2
808 	s[C_ERASE2]	= n->c_cc[VERASE2];
809 # endif /* VERASE2 */
810 # ifdef VSTART
811 	s[C_START]	= n->c_cc[VSTART];
812 # endif /* VSTART */
813 # ifdef VSTOP
814 	s[C_STOP]	= n->c_cc[VSTOP];
815 # endif /* VSTOP */
816 # ifdef VWERASE
817 	s[C_WERASE]	= n->c_cc[VWERASE];
818 # endif /* VWERASE */
819 # ifdef VSUSP
820 	s[C_SUSP]	= n->c_cc[VSUSP];
821 # endif /* VSUSP */
822 # ifdef VDSUSP
823 	s[C_DSUSP]	= n->c_cc[VDSUSP];
824 # endif /* VDSUSP */
825 # ifdef VREPRINT
826 	s[C_REPRINT]	= n->c_cc[VREPRINT];
827 # endif /* WREPRINT */
828 # ifdef VDISCARD
829 	s[C_DISCARD]	= n->c_cc[VDISCARD];
830 # endif /* VDISCARD */
831 # ifdef VLNEXT
832 	s[C_LNEXT]	= n->c_cc[VLNEXT];
833 # endif /* VLNEXT */
834 # ifdef VSTATUS
835 	s[C_STATUS]	= n->c_cc[VSTATUS];
836 # endif /* VSTATUS */
837 # ifdef VPAGE
838 	s[C_PAGE]	= n->c_cc[VPAGE];
839 # endif /* VPAGE */
840 # ifdef VPGOFF
841 	s[C_PGOFF]	= n->c_cc[VPGOFF];
842 # endif /* VPGOFF */
843 # ifdef VKILL2
844 	s[C_KILL2]	= n->c_cc[VKILL2];
845 # endif /* KILL2 */
846 # ifdef VMIN
847 	s[C_MIN]	= n->c_cc[VMIN];
848 # endif /* VMIN */
849 # ifdef VTIME
850 	s[C_TIME]	= n->c_cc[VTIME];
851 # endif /* VTIME */
852     }
853 
854 #else /* SGTTY */
855 
856 # ifdef TIOCGPAGE
857     {
858 	struct ttypagestat *n = &td->d_pc;
859 
860 	s[C_STATUS]	= n->tps_statc;
861 	s[C_PAGE]	= n->tps_pagec;
862 	s[C_PGOFF]	= n->tps_pgoffc;
863     }
864 # endif /* TIOCGPAGE */
865 
866 # ifdef TIOCGETC
867     {
868 	struct tchars *n = &td->d_tc;
869 
870 	s[C_INTR]	= n->t_intrc;
871 	s[C_QUIT]	= n->t_quitc;
872 	s[C_START]	= n->t_startc;
873 	s[C_STOP]	= n->t_stopc;
874 	s[C_EOF]	= n->t_eofc;
875 	s[C_BRK]	= n->t_brkc;
876     }
877 # endif /* TIOCGETC */
878 
879 # ifdef TIOCGETP
880     {
881 	struct sgttyb *n = &td->d_t;
882 
883 	s[C_ERASE]	= n->sg_erase;
884 	s[C_KILL]	= n->sg_kill;
885     }
886 # endif /* TIOCGETP */
887 #endif /* !POSIX || TERMIO */
888 
889 } /* tty_getchar */
890 
891 
892 void
893 tty_setchar(ttydata_t *td, unsigned char *s)
894 {
895 #ifdef TIOCGLTC
896     {
897 	struct ltchars *n = &td->d_ltc;
898 
899 	n->t_suspc 		= s[C_SUSP];
900 	n->t_dsuspc		= s[C_DSUSP];
901 	n->t_rprntc		= s[C_REPRINT];
902 	n->t_flushc		= s[C_DISCARD];
903 	n->t_werasc		= s[C_WERASE];
904 	n->t_lnextc		= s[C_LNEXT];
905     }
906 #endif /* TIOCGLTC */
907 
908 #if defined(POSIX) || defined(TERMIO)
909     {
910 # ifdef POSIX
911 	struct termios *n = &td->d_t;
912 # else
913 	struct termio *n = &td->d_t;
914 # endif /* POSIX */
915 
916 # ifdef VINTR
917 	n->c_cc[VINTR]		= s[C_INTR];
918 # endif /* VINTR */
919 # ifdef VQUIT
920 	n->c_cc[VQUIT]		= s[C_QUIT];
921 # endif /* VQUIT */
922 # ifdef VERASE
923 	n->c_cc[VERASE]		= s[C_ERASE];
924 # endif /* VERASE */
925 # ifdef VKILL
926 	n->c_cc[VKILL]		= s[C_KILL];
927 # endif /* VKILL */
928 # ifdef VEOF
929 	n->c_cc[VEOF]		= s[C_EOF];
930 # endif /* VEOF */
931 # ifdef VEOL
932 	n->c_cc[VEOL]		= s[C_EOL];
933 # endif /* VEOL */
934 # ifdef VEOL2
935 	n->c_cc[VEOL2]		= s[C_EOL2];
936 # endif  /* VEOL2 */
937 # ifdef VSWTCH
938 	n->c_cc[VSWTCH]		= s[C_SWTCH];
939 # endif /* VSWTCH */
940 # ifdef VDSWTCH
941 	n->c_cc[VDSWTCH]	= s[C_DSWTCH];
942 # endif /* VDSWTCH */
943 # ifdef VERASE2
944 	n->c_cc[VERASE2]	= s[C_ERASE2];
945 # endif /* VERASE2 */
946 # ifdef VSTART
947 	n->c_cc[VSTART]		= s[C_START];
948 # endif /* VSTART */
949 # ifdef VSTOP
950 	n->c_cc[VSTOP]		= s[C_STOP];
951 # endif /* VSTOP */
952 # ifdef VWERASE
953 	n->c_cc[VWERASE]	= s[C_WERASE];
954 # endif /* VWERASE */
955 # ifdef VSUSP
956 	n->c_cc[VSUSP]		= s[C_SUSP];
957 # endif /* VSUSP */
958 # ifdef VDSUSP
959 	n->c_cc[VDSUSP]		= s[C_DSUSP];
960 # endif /* VDSUSP */
961 # ifdef VREPRINT
962 	n->c_cc[VREPRINT]	= s[C_REPRINT];
963 # endif /* WREPRINT */
964 # ifdef VDISCARD
965 	n->c_cc[VDISCARD]	= s[C_DISCARD];
966 # endif /* VDISCARD */
967 # ifdef VLNEXT
968 	n->c_cc[VLNEXT]		= s[C_LNEXT];
969 # endif /* VLNEXT */
970 # ifdef VSTATUS
971 	n->c_cc[VSTATUS]	= s[C_STATUS];
972 # endif /* VSTATUS */
973 # ifdef VPAGE
974 	n->c_cc[VPAGE]		= s[C_PAGE];
975 # endif /* VPAGE */
976 # ifdef VPGOFF
977 	n->c_cc[VPGOFF]		= s[C_PGOFF];
978 # endif /* VPGOFF */
979 # ifdef VKILL2
980 	n->c_cc[VKILL2]		= s[C_KILL2];
981 # endif /* VKILL2 */
982 # ifdef VMIN
983 	n->c_cc[VMIN]		= s[C_MIN];
984 # endif /* VMIN */
985 # ifdef VTIME
986 	n->c_cc[VTIME]		= s[C_TIME];
987 # endif /* VTIME */
988     }
989 
990 #else /* GSTTY */
991 
992 # ifdef TIOCGPAGE
993     {
994 	struct ttypagestat *n = &td->d_pc;
995 
996 	n->tps_length		= 0;
997 	n->tps_lpos		= 0;
998 	n->tps_statc		= s[C_STATUS];
999 	n->tps_pagec		= s[C_PAGE];
1000 	n->tps_pgoffc		= s[C_PGOFF];
1001 	n->tps_flag		= 0;
1002     }
1003 # endif /* TIOCGPAGE */
1004 
1005 # ifdef TIOCGETC
1006     {
1007 	struct tchars *n = &td->d_tc;
1008 	n->t_intrc		= s[C_INTR];
1009 	n->t_quitc		= s[C_QUIT];
1010 	n->t_startc		= s[C_START];
1011 	n->t_stopc		= s[C_STOP];
1012 	n->t_eofc		= s[C_EOF];
1013 	n->t_brkc		= s[C_BRK];
1014     }
1015 # endif /* TIOCGETC */
1016 
1017 # ifdef TIOCGETP
1018     {
1019 	struct sgttyb *n = &td->d_t;
1020 
1021 	n->sg_erase		= s[C_ERASE];
1022 	n->sg_kill		= s[C_KILL];
1023     }
1024 # endif /* TIOCGETP */
1025 #endif /* !POSIX || TERMIO */
1026 
1027 } /* tty_setchar */
1028 
1029 speed_t
1030 tty_getspeed(ttydata_t *td)
1031 {
1032     speed_t spd;
1033 
1034 #ifdef POSIX
1035     if ((spd = cfgetispeed(&td->d_t)) == 0)
1036 	spd = cfgetospeed(&td->d_t);
1037 #else /* ! POSIX */
1038 # ifdef TERMIO
1039 #  ifdef CBAUD
1040     spd = td->d_t.c_cflag & CBAUD;
1041 #  else
1042     spd = 0;
1043 #  endif
1044 # else /* SGTTY */
1045     spd = td->d_t.sg_ispeed;
1046 # endif /* TERMIO */
1047 #endif /* POSIX */
1048 
1049     return spd;
1050 } /* end tty_getspeed */
1051 
1052 int
1053 tty_gettabs(ttydata_t *td)
1054 {
1055 #if defined(POSIX) || defined(TERMIO)
1056     return ((td->d_t.c_oflag & TAB3) == TAB3) ? 0 : 1;
1057 #else /* SGTTY */
1058     return (td->d_t.sg_flags & XTABS) == XTABS ? 0 : 1;
1059 #endif /* POSIX || TERMIO */
1060 } /* end tty_gettabs */
1061 
1062 int
1063 tty_geteightbit(ttydata_t *td)
1064 {
1065 #if defined(POSIX) || defined(TERMIO)
1066     return (td->d_t.c_cflag & CSIZE) == CS8;
1067 #else /* SGTTY */
1068     return td->d_lb & (LPASS8 | LLITOUT);
1069 #endif /* POSIX || TERMIO */
1070 } /* end tty_geteightbit */
1071 
1072 int
1073 tty_cooked_mode(ttydata_t *td)
1074 {
1075 #if defined(POSIX) || defined(TERMIO)
1076     return (td->d_t.c_lflag & ICANON);
1077 #else /* SGTTY */
1078     return !(td->d_t.sg_flags & (RAW | CBREAK));
1079 #endif /* POSIX || TERMIO */
1080 } /* end tty_cooked_mode */
1081 
1082 #ifdef _IBMR2
1083 void
1084 tty_setdisc(int fd, int dis)
1085 {
1086     static int edit_discipline = 0;
1087     static union txname tx_disc;
1088     extern char strPOSIX[];
1089 
1090     switch (dis) {
1091     case EX_IO:
1092 	if (edit_discipline) {
1093 	    if (ioctl(fd, TXSETLD, (ioctl_t) & tx_disc) == -1)
1094 		return;
1095 	    edit_discipline = 0;
1096 	}
1097 	return;
1098 
1099     case ED_IO:
1100 	tx_disc.tx_which = 0;
1101 	if (ioctl(fd, TXGETLD, (ioctl_t) & tx_disc) == -1)
1102 	    return;
1103 	if (strcmp(tx_disc.tx_name, strPOSIX) != 0) {
1104 	    edit_discipline = 1;
1105 	    if (ioctl(fd, TXSETLD, (ioctl_t) strPOSIX) == -1)
1106 	    return;
1107 	}
1108 	return;
1109 
1110     default:
1111 	return;
1112     }
1113 } /* end tty_setdisc */
1114 #endif /* _IBMR2 */
1115 
1116 #ifdef DEBUG_TTY
1117 static void
1118 tty_printchar(unsigned char *s)
1119 {
1120     struct tcshmodes *m;
1121     int i;
1122 
1123     for (i = 0; i < C_NCC; i++) {
1124 	for (m = modelist; m->m_name; m++)
1125 	    if (m->m_type == M_CHAR && C_SH(i) == m->m_value)
1126 		break;
1127 	if (m->m_name)
1128 	    xprintf("%s ^%c ", m->m_name, s[i] + 'A' - 1);
1129 	if (i % 5 == 0)
1130 	    xputchar('\n');
1131     }
1132     xputchar('\n');
1133 }
1134 #endif /* DEBUG_TTY */
1135 #else /* WINNT_NATIVE */
1136 int
1137 tty_cooked_mode(void *td)
1138 {
1139     return do_nt_check_cooked_mode();
1140 }
1141 #endif /* !WINNT_NATIVE */
1142