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