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