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