1 /*-
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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
34 #ifndef lint
35 static char sccsid[] = "@(#)hack.tty.c 5.3 (Berkeley) 5/13/91";
36 #endif /* not lint */
37
38 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
39 /* hack.tty.c - version 1.0.3 */
40 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
41 arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
42
43 #include "hack.h"
44 #include <stdio.h>
45
46 /*
47 * The distinctions here are not BSD - rest but rather USG - rest, as
48 * BSD still has the old sgttyb structure, but SYSV has termio. Thus:
49 */
50 #ifdef BSD
51 #define V7
52 #else
53 #define USG
54 #endif BSD
55
56 /*
57 * Some systems may have getchar() return EOF for various reasons, and
58 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
59 */
60 #ifndef BSD
61 #define NR_OF_EOFS 20
62 #endif BSD
63
64
65 #ifdef USG
66
67 #include <termio.h>
68 #define termstruct termio
69 #define kill_sym c_cc[VKILL]
70 #define erase_sym c_cc[VERASE]
71 #define EXTABS TAB3
72 #define tabflgs c_oflag
73 #define echoflgs c_lflag
74 #define cbrkflgs c_lflag
75 #define CBRKMASK ICANON
76 #define CBRKON ! /* reverse condition */
77 #define OSPEED(x) ((x).c_cflag & CBAUD)
78 #define GTTY(x) (ioctl(0, TCGETA, x))
79 #define STTY(x) (ioctl(0, TCSETA, x)) /* TCSETAF? TCSETAW? */
80
81 #else /* V7 */
82
83 #include <sgtty.h>
84 #define termstruct sgttyb
85 #define kill_sym sg_kill
86 #define erase_sym sg_erase
87 #define EXTABS XTABS
88 #define tabflgs sg_flags
89 #define echoflgs sg_flags
90 #define cbrkflgs sg_flags
91 #define CBRKMASK CBREAK
92 #define CBRKON /* empty */
93 #define OSPEED(x) (x).sg_ospeed
94 #define GTTY(x) (gtty(0, x))
95 #define STTY(x) (stty(0, x))
96
97 #endif USG
98
99 extern short ospeed;
100 static char erase_char, kill_char;
101 static boolean settty_needed = FALSE;
102 struct termstruct inittyb, curttyb;
103
104 /*
105 * Get initial state of terminal, set ospeed (for termcap routines)
106 * and switch off tab expansion if necessary.
107 * Called by startup() in termcap.c and after returning from ! or ^Z
108 */
gettty()109 gettty(){
110 if(GTTY(&inittyb) < 0)
111 perror("Hack (gettty)");
112 curttyb = inittyb;
113 ospeed = OSPEED(inittyb);
114 erase_char = inittyb.erase_sym;
115 kill_char = inittyb.kill_sym;
116 getioctls();
117
118 /* do not expand tabs - they might be needed inside a cm sequence */
119 if(curttyb.tabflgs & EXTABS) {
120 curttyb.tabflgs &= ~EXTABS;
121 setctty();
122 }
123 settty_needed = TRUE;
124 }
125
126 /* reset terminal to original state */
settty(s)127 settty(s) char *s; {
128 clear_screen();
129 end_screen();
130 if(s) printf(s);
131 (void) fflush(stdout);
132 if(STTY(&inittyb) < 0)
133 perror("Hack (settty)");
134 flags.echo = (inittyb.echoflgs & ECHO) ? ON : OFF;
135 flags.cbreak = (CBRKON(inittyb.cbrkflgs & CBRKMASK)) ? ON : OFF;
136 setioctls();
137 }
138
setctty()139 setctty(){
140 if(STTY(&curttyb) < 0)
141 perror("Hack (setctty)");
142 }
143
144
setftty()145 setftty(){
146 register int ef = 0; /* desired value of flags & ECHO */
147 register int cf = CBRKON(CBRKMASK); /* desired value of flags & CBREAK */
148 register int change = 0;
149 flags.cbreak = ON;
150 flags.echo = OFF;
151 /* Should use (ECHO|CRMOD) here instead of ECHO */
152 if((curttyb.echoflgs & ECHO) != ef){
153 curttyb.echoflgs &= ~ECHO;
154 /* curttyb.echoflgs |= ef; */
155 change++;
156 }
157 if((curttyb.cbrkflgs & CBRKMASK) != cf){
158 curttyb.cbrkflgs &= ~CBRKMASK;
159 curttyb.cbrkflgs |= cf;
160 #ifdef USG
161 /* be satisfied with one character; no timeout */
162 curttyb.c_cc[VMIN] = 1; /* was VEOF */
163 curttyb.c_cc[VTIME] = 0; /* was VEOL */
164 #endif USG
165 change++;
166 }
167 if(change){
168 setctty();
169 }
170 start_screen();
171 }
172
173
174 /* fatal error */
175 /*VARARGS1*/
error(s,x,y)176 error(s,x,y) char *s; {
177 if(settty_needed)
178 settty((char *) 0);
179 printf(s,x,y);
180 putchar('\n');
181 exit(1);
182 }
183
184 /*
185 * Read a line closed with '\n' into the array char bufp[BUFSZ].
186 * (The '\n' is not stored. The string is closed with a '\0'.)
187 * Reading can be interrupted by an escape ('\033') - now the
188 * resulting string is "\033".
189 */
getlin(bufp)190 getlin(bufp)
191 register char *bufp;
192 {
193 register char *obufp = bufp;
194 register int c;
195
196 flags.toplin = 2; /* nonempty, no --More-- required */
197 for(;;) {
198 (void) fflush(stdout);
199 if((c = getchar()) == EOF) {
200 *bufp = 0;
201 return;
202 }
203 if(c == '\033') {
204 *obufp = c;
205 obufp[1] = 0;
206 return;
207 }
208 if(c == erase_char || c == '\b') {
209 if(bufp != obufp) {
210 bufp--;
211 putstr("\b \b"); /* putsym converts \b */
212 } else bell();
213 } else if(c == '\n') {
214 *bufp = 0;
215 return;
216 } else if(' ' <= c && c < '\177') {
217 /* avoid isprint() - some people don't have it
218 ' ' is not always a printing char */
219 *bufp = c;
220 bufp[1] = 0;
221 putstr(bufp);
222 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
223 bufp++;
224 } else if(c == kill_char || c == '\177') { /* Robert Viduya */
225 /* this test last - @ might be the kill_char */
226 while(bufp != obufp) {
227 bufp--;
228 putstr("\b \b");
229 }
230 } else
231 bell();
232 }
233 }
234
getret()235 getret() {
236 cgetret("");
237 }
238
cgetret(s)239 cgetret(s)
240 register char *s;
241 {
242 putsym('\n');
243 if(flags.standout)
244 standoutbeg();
245 putstr("Hit ");
246 putstr(flags.cbreak ? "space" : "return");
247 putstr(" to continue: ");
248 if(flags.standout)
249 standoutend();
250 xwaitforspace(s);
251 }
252
253 char morc; /* tell the outside world what char he used */
254
xwaitforspace(s)255 xwaitforspace(s)
256 register char *s; /* chars allowed besides space or return */
257 {
258 register int c;
259
260 morc = 0;
261
262 while((c = readchar()) != '\n') {
263 if(flags.cbreak) {
264 if(c == ' ') break;
265 if(s && index(s,c)) {
266 morc = c;
267 break;
268 }
269 bell();
270 }
271 }
272 }
273
274 char *
parse()275 parse()
276 {
277 static char inputline[COLNO];
278 register foo;
279
280 flags.move = 1;
281 if(!Invisible) curs_on_u(); else home();
282 while((foo = readchar()) >= '0' && foo <= '9')
283 multi = 10*multi+foo-'0';
284 if(multi) {
285 multi--;
286 save_cm = inputline;
287 }
288 inputline[0] = foo;
289 inputline[1] = 0;
290 if(foo == 'f' || foo == 'F'){
291 inputline[1] = getchar();
292 #ifdef QUEST
293 if(inputline[1] == foo) inputline[2] = getchar(); else
294 #endif QUEST
295 inputline[2] = 0;
296 }
297 if(foo == 'm' || foo == 'M'){
298 inputline[1] = getchar();
299 inputline[2] = 0;
300 }
301 clrlin();
302 return(inputline);
303 }
304
305 char
readchar()306 readchar() {
307 register int sym;
308
309 (void) fflush(stdout);
310 if((sym = getchar()) == EOF)
311 #ifdef NR_OF_EOFS
312 { /*
313 * Some SYSV systems seem to return EOFs for various reasons
314 * (?like when one hits break or for interrupted systemcalls?),
315 * and we must see several before we quit.
316 */
317 register int cnt = NR_OF_EOFS;
318 while (cnt--) {
319 clearerr(stdin); /* omit if clearerr is undefined */
320 if((sym = getchar()) != EOF) goto noteof;
321 }
322 end_of_input();
323 noteof: ;
324 }
325 #else
326 end_of_input();
327 #endif NR_OF_EOFS
328 if(flags.toplin == 1)
329 flags.toplin = 2;
330 return((char) sym);
331 }
332
end_of_input()333 end_of_input()
334 {
335 settty("End of input?\n");
336 clearlocks();
337 exit(0);
338 }
339