ed.term.c revision 83098
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
40RCSID("$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
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#ifdef __NetBSD__
570#define KLUDGE (errno == ENOTTY && count < 10)
571#else
572#define KLUDGE 0
573#endif
574
575/* Retry a system call */
576static 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*/
589void
590dosetty(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
694int
695tty_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
727int
728tty_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
760void
761tty_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
898void
899tty_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
1037speed_t
1038tty_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
1061int
1062tty_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
1072int
1073tty_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
1083int
1084tty_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
1095void
1096tty_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
1131static void
1132tty_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 */
1151int
1152tty_cooked_mode(td)
1153    void *td;
1154{
1155    return do_nt_check_cooked_mode();
1156}
1157#endif /* !WINNT_NATIVE */
1158