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