2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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.
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
36 static char sccsid[] = "@(#)hack.tty.c 8.1 (Berkeley) 5/31/93";
38 static const char rcsid[] =
42 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
43 /* hack.tty.c - version 1.0.3 */
44 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
45 arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
51 * The distinctions here are not BSD - rest but rather USG - rest, as
52 * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
61 * Some systems may have getchar() return EOF for various reasons, and
62 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
72 #define termstruct termio
73 #define kill_sym c_cc[VKILL]
74 #define erase_sym c_cc[VERASE]
76 #define tabflgs c_oflag
77 #define echoflgs c_lflag
78 #define cbrkflgs c_lflag
79 #define CBRKMASK ICANON
80 #define CBRKON ! /* reverse condition */
81 #define OSPEED(x) ((x).c_cflag & CBAUD)
82 #define GTTY(x) (ioctl(0, TCGETA, x))
83 #define STTY(x) (ioctl(0, TCSETA, x)) /* TCSETAF? TCSETAW? */
88 #define termstruct sgttyb
89 #define kill_sym sg_kill
90 #define erase_sym sg_erase
92 #define tabflgs sg_flags
93 #define echoflgs sg_flags
94 #define cbrkflgs sg_flags
95 #define CBRKMASK CBREAK
96 #define CBRKON /* empty */
97 #define OSPEED(x) (x).sg_ospeed
98 #define GTTY(x) (gtty(0, x))
99 #define STTY(x) (stty(0, x))
106 static char erase_char, kill_char;
107 static boolean settty_needed = FALSE;
108 struct termstruct inittyb, curttyb;
111 * Get initial state of terminal, set ospeed (for termcap routines)
112 * and switch off tab expansion if necessary.
113 * Called by startup() in termcap.c and after returning from ! or ^Z
116 if(GTTY(&inittyb) < 0)
117 perror("Hack (gettty)");
120 ospeed = OSPEED(inittyb);
122 erase_char = inittyb.erase_sym;
123 kill_char = inittyb.kill_sym;
126 /* do not expand tabs - they might be needed inside a cm sequence */
127 if(curttyb.tabflgs & EXTABS) {
128 curttyb.tabflgs &= ~EXTABS;
131 settty_needed = TRUE;
134 /* reset terminal to original state */
139 (void) fflush(stdout);
140 if(STTY(&inittyb) < 0)
141 perror("Hack (settty)");
142 flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
143 flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
148 if(STTY(&curttyb) < 0)
149 perror("Hack (setctty)");
154 int ef = 0; /* desired value of flags & ECHO */
155 int cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */
159 /* Should use (ECHO|CRMOD) here instead of ECHO */
160 if((curttyb.echoflgs & ECHO) != ef){
161 curttyb.echoflgs &= ~ECHO;
162 /* curttyb.echoflgs |= ef; */
165 if((curttyb.cbrkflgs & CBRKMASK) != cf){
166 curttyb.cbrkflgs &= ~CBRKMASK;
167 curttyb.cbrkflgs |= cf;
169 /* be satisfied with one character; no timeout */
170 curttyb.c_cc[VMIN] = 1; /* was VEOF */
171 curttyb.c_cc[VTIME] = 0; /* was VEOL */
184 error(s,x,y) char *s; {
193 * Read a line closed with '\n' into the array char bufp[BUFSZ].
194 * (The '\n' is not stored. The string is closed with a '\0'.)
195 * Reading can be interrupted by an escape ('\033') - now the
196 * resulting string is "\033".
204 flags.toplin = 2; /* nonempty, no --More-- required */
206 (void) fflush(stdout);
207 if((c = getchar()) == EOF) {
216 if(c == erase_char || c == '\b') {
219 putstr("\b \b"); /* putsym converts \b */
221 } else if(c == '\n') {
224 } else if(' ' <= c && c < '\177') {
225 /* avoid isprint() - some people don't have it
226 ' ' is not always a printing char */
230 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
232 } else if(c == kill_char || c == '\177') { /* Robert Viduya */
233 /* this test last - @ might be the kill_char */
234 while(bufp != obufp) {
254 putstr(flags.cbreak ? "space" : "return");
255 putstr(" to continue: ");
261 char morc; /* tell the outside world what char he used */
264 char *s; /* chars allowed besides space or return */
270 while((c = readchar()) != '\n') {
273 if(s && index(s,c)) {
285 static char inputline[COLNO];
289 if(!Invisible) curs_on_u(); else home();
290 while((foo = readchar()) >= '0' && foo <= '9')
291 multi = 10*multi+foo-'0';
298 if(foo == 'f' || foo == 'F'){
299 inputline[1] = getchar();
301 if(inputline[1] == foo) inputline[2] = getchar(); else
305 if(foo == 'm' || foo == 'M'){
306 inputline[1] = getchar();
317 (void) fflush(stdout);
318 if((sym = getchar()) == EOF)
321 * Some SYSV systems seem to return EOFs for various reasons
322 * (?like when one hits break or for interrupted systemcalls?),
323 * and we must see several before we quit.
325 int cnt = NR_OF_EOFS;
327 clearerr(stdin); /* omit if clearerr is undefined */
328 if((sym = getchar()) != EOF) goto noteof;
336 if(flags.toplin == 1)
343 settty("End of input?\n");