1*df69c215Sderaadt /* $OpenBSD: hack.tty.c,v 1.16 2019/06/28 13:32:52 deraadt Exp $ */
2d0b779f3Sniklas
3df930be7Sderaadt /*-
4df930be7Sderaadt * Copyright (c) 1988, 1993
5df930be7Sderaadt * The Regents of the University of California. All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt * modification, are permitted provided that the following conditions
9df930be7Sderaadt * are met:
10df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt * documentation and/or other materials provided with the distribution.
157a09557bSmillert * 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt * may be used to endorse or promote products derived from this software
17df930be7Sderaadt * without specific prior written permission.
18df930be7Sderaadt *
19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt * SUCH DAMAGE.
30df930be7Sderaadt */
31df930be7Sderaadt
32d25013f2Scamield /*
33d25013f2Scamield * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
34d25013f2Scamield * Amsterdam
35d25013f2Scamield * All rights reserved.
36d25013f2Scamield *
37d25013f2Scamield * Redistribution and use in source and binary forms, with or without
38d25013f2Scamield * modification, are permitted provided that the following conditions are
39d25013f2Scamield * met:
40d25013f2Scamield *
41d25013f2Scamield * - Redistributions of source code must retain the above copyright notice,
42d25013f2Scamield * this list of conditions and the following disclaimer.
43d25013f2Scamield *
44d25013f2Scamield * - Redistributions in binary form must reproduce the above copyright
45d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
46d25013f2Scamield * documentation and/or other materials provided with the distribution.
47d25013f2Scamield *
48d25013f2Scamield * - Neither the name of the Stichting Centrum voor Wiskunde en
49d25013f2Scamield * Informatica, nor the names of its contributors may be used to endorse or
50d25013f2Scamield * promote products derived from this software without specific prior
51d25013f2Scamield * written permission.
52d25013f2Scamield *
53d25013f2Scamield * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
54d25013f2Scamield * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55d25013f2Scamield * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56d25013f2Scamield * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
57d25013f2Scamield * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60d25013f2Scamield * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61d25013f2Scamield * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62d25013f2Scamield * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63d25013f2Scamield * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64d25013f2Scamield */
65d25013f2Scamield
66d25013f2Scamield /*
67d25013f2Scamield * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
68d25013f2Scamield * All rights reserved.
69d25013f2Scamield *
70d25013f2Scamield * Redistribution and use in source and binary forms, with or without
71d25013f2Scamield * modification, are permitted provided that the following conditions
72d25013f2Scamield * are met:
73d25013f2Scamield * 1. Redistributions of source code must retain the above copyright
74d25013f2Scamield * notice, this list of conditions and the following disclaimer.
75d25013f2Scamield * 2. Redistributions in binary form must reproduce the above copyright
76d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
77d25013f2Scamield * documentation and/or other materials provided with the distribution.
78d25013f2Scamield * 3. The name of the author may not be used to endorse or promote products
79d25013f2Scamield * derived from this software without specific prior written permission.
80d25013f2Scamield *
81d25013f2Scamield * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
82d25013f2Scamield * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
83d25013f2Scamield * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
84d25013f2Scamield * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
85d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
86d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
87d25013f2Scamield * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
88d25013f2Scamield * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
89d25013f2Scamield * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
90d25013f2Scamield * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91d25013f2Scamield */
92d25013f2Scamield
93df930be7Sderaadt /* hack.tty.c - version 1.0.3 */
94df930be7Sderaadt /* With thanks to the people who sent code for SYSV - hpscdi!jon,
95df930be7Sderaadt arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
96df930be7Sderaadt
97df930be7Sderaadt #include <stdio.h>
98d07db98cSpjanzen #include <stdlib.h>
99df930be7Sderaadt #include <termios.h>
100df930be7Sderaadt
101aed906e4Smestre #include "hack.h"
102aed906e4Smestre
103df930be7Sderaadt static char erase_char, kill_char;
104df930be7Sderaadt static boolean settty_needed = FALSE;
105df930be7Sderaadt struct termios inittyb, curttyb;
106df930be7Sderaadt
107aed906e4Smestre static void setctty(void);
1084a5fbbc4Spjanzen
109df930be7Sderaadt /*
1104a5fbbc4Spjanzen * Get initial state of terminal,
111df930be7Sderaadt * and switch off tab expansion if necessary.
112df930be7Sderaadt * Called by startup() in termcap.c and after returning from ! or ^Z
113df930be7Sderaadt */
1144a5fbbc4Spjanzen void
gettty(void)115aed906e4Smestre gettty(void)
1164a5fbbc4Spjanzen {
117*df69c215Sderaadt if(tcgetattr(0, &inittyb) == -1)
118df930be7Sderaadt perror("Hack (gettty)");
119df930be7Sderaadt curttyb = inittyb;
120df930be7Sderaadt erase_char = inittyb.c_cc[VERASE];
121df930be7Sderaadt kill_char = inittyb.c_cc[VKILL];
122df930be7Sderaadt getioctls();
123df930be7Sderaadt
124df930be7Sderaadt /* do not expand tabs - they might be needed inside a cm sequence */
125df930be7Sderaadt if(curttyb.c_oflag & OXTABS) {
126df930be7Sderaadt curttyb.c_oflag &= ~OXTABS;
127df930be7Sderaadt setctty();
128df930be7Sderaadt }
129df930be7Sderaadt settty_needed = TRUE;
130df930be7Sderaadt }
131df930be7Sderaadt
132df930be7Sderaadt /* reset terminal to original state */
1334a5fbbc4Spjanzen void
settty(char * s)1344a5fbbc4Spjanzen settty(char *s)
1354a5fbbc4Spjanzen {
1364a5fbbc4Spjanzen clr_screen();
137df930be7Sderaadt end_screen();
138cff62e3cSpjanzen if(s) printf("%s", s);
139df930be7Sderaadt (void) fflush(stdout);
140*df69c215Sderaadt if(tcsetattr(0, TCSADRAIN, &inittyb) == -1)
141df930be7Sderaadt perror("Hack (settty)");
142df930be7Sderaadt flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
143df930be7Sderaadt flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
144df930be7Sderaadt setioctls();
145df930be7Sderaadt }
146df930be7Sderaadt
1474a5fbbc4Spjanzen static void
setctty(void)148aed906e4Smestre setctty(void)
1494a5fbbc4Spjanzen {
150*df69c215Sderaadt if(tcsetattr(0, TCSADRAIN, &curttyb) == -1)
151df930be7Sderaadt perror("Hack (setctty)");
152df930be7Sderaadt }
153df930be7Sderaadt
1544a5fbbc4Spjanzen void
setftty(void)155aed906e4Smestre setftty(void)
1564a5fbbc4Spjanzen {
1574a5fbbc4Spjanzen int change = 0;
158df930be7Sderaadt flags.cbreak = ON;
159df930be7Sderaadt flags.echo = OFF;
160df930be7Sderaadt /* Should use (ECHO|CRMOD) here instead of ECHO */
161df930be7Sderaadt if(curttyb.c_lflag & ECHO){
162df930be7Sderaadt curttyb.c_lflag &= ~ECHO;
163df930be7Sderaadt change++;
164df930be7Sderaadt }
165df930be7Sderaadt if(curttyb.c_lflag & ICANON){
166df930be7Sderaadt curttyb.c_lflag &= ~ICANON;
167df930be7Sderaadt /* be satisfied with one character; no timeout */
168df930be7Sderaadt curttyb.c_cc[VMIN] = 1;
169df930be7Sderaadt curttyb.c_cc[VTIME] = 0;
1707146b7ceSmillert /* we need to be able to read ^Z */
1717146b7ceSmillert curttyb.c_cc[VSUSP] = _POSIX_VDISABLE;
172df930be7Sderaadt change++;
173df930be7Sderaadt }
174df930be7Sderaadt if(change){
175df930be7Sderaadt setctty();
176df930be7Sderaadt }
177df930be7Sderaadt start_screen();
178df930be7Sderaadt }
179df930be7Sderaadt
180df930be7Sderaadt
181df930be7Sderaadt /* fatal error */
1824a5fbbc4Spjanzen void
error(const char * s,...)183911134d2Sguenther error(const char *s, ...)
1844a5fbbc4Spjanzen {
1854a5fbbc4Spjanzen va_list ap;
1864a5fbbc4Spjanzen
187df930be7Sderaadt if(settty_needed)
188911134d2Sguenther settty(NULL);
1894a5fbbc4Spjanzen va_start(ap, s);
190a55fa95fSderaadt vprintf(s, ap);
1914a5fbbc4Spjanzen va_end(ap);
192df930be7Sderaadt putchar('\n');
193df930be7Sderaadt exit(1);
194df930be7Sderaadt }
195df930be7Sderaadt
196df930be7Sderaadt /*
197df930be7Sderaadt * Read a line closed with '\n' into the array char bufp[BUFSZ].
198df930be7Sderaadt * (The '\n' is not stored. The string is closed with a '\0'.)
199df930be7Sderaadt * Reading can be interrupted by an escape ('\033') - now the
200df930be7Sderaadt * resulting string is "\033".
201df930be7Sderaadt */
2024a5fbbc4Spjanzen void
getlin(char * bufp)2034a5fbbc4Spjanzen getlin(char *bufp)
204df930be7Sderaadt {
2054a5fbbc4Spjanzen char *obufp = bufp;
2064a5fbbc4Spjanzen int c;
207df930be7Sderaadt
208df930be7Sderaadt flags.toplin = 2; /* nonempty, no --More-- required */
209df930be7Sderaadt for(;;) {
210df930be7Sderaadt (void) fflush(stdout);
211df930be7Sderaadt if((c = getchar()) == EOF) {
212df930be7Sderaadt *bufp = 0;
213df930be7Sderaadt return;
214df930be7Sderaadt }
215df930be7Sderaadt if(c == '\033') {
216df930be7Sderaadt *obufp = c;
217df930be7Sderaadt obufp[1] = 0;
218df930be7Sderaadt return;
219df930be7Sderaadt }
220df930be7Sderaadt if(c == erase_char || c == '\b') {
221df930be7Sderaadt if(bufp != obufp) {
222df930be7Sderaadt bufp--;
223df930be7Sderaadt putstr("\b \b"); /* putsym converts \b */
2244a5fbbc4Spjanzen } else hackbell();
225df930be7Sderaadt } else if(c == '\n') {
226df930be7Sderaadt *bufp = 0;
227df930be7Sderaadt return;
228df930be7Sderaadt } else if(' ' <= c && c < '\177') {
229df930be7Sderaadt /* avoid isprint() - some people don't have it
230df930be7Sderaadt ' ' is not always a printing char */
231df930be7Sderaadt *bufp = c;
232df930be7Sderaadt bufp[1] = 0;
233df930be7Sderaadt putstr(bufp);
234df930be7Sderaadt if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
235df930be7Sderaadt bufp++;
236df930be7Sderaadt } else if(c == kill_char || c == '\177') { /* Robert Viduya */
237df930be7Sderaadt /* this test last - @ might be the kill_char */
238df930be7Sderaadt while(bufp != obufp) {
239df930be7Sderaadt bufp--;
240df930be7Sderaadt putstr("\b \b");
241df930be7Sderaadt }
242df930be7Sderaadt } else
2434a5fbbc4Spjanzen hackbell();
244df930be7Sderaadt }
245df930be7Sderaadt }
246df930be7Sderaadt
2474a5fbbc4Spjanzen void
getret(void)248aed906e4Smestre getret(void)
2494a5fbbc4Spjanzen {
250df930be7Sderaadt cgetret("");
251df930be7Sderaadt }
252df930be7Sderaadt
2534a5fbbc4Spjanzen void
cgetret(char * s)2544a5fbbc4Spjanzen cgetret(char *s)
255df930be7Sderaadt {
256df930be7Sderaadt putsym('\n');
257df930be7Sderaadt if(flags.standout)
258df930be7Sderaadt standoutbeg();
259df930be7Sderaadt putstr("Hit ");
260df930be7Sderaadt putstr(flags.cbreak ? "space" : "return");
261df930be7Sderaadt putstr(" to continue: ");
262df930be7Sderaadt if(flags.standout)
263df930be7Sderaadt standoutend();
264df930be7Sderaadt xwaitforspace(s);
265df930be7Sderaadt }
266df930be7Sderaadt
267df930be7Sderaadt char morc; /* tell the outside world what char he used */
268df930be7Sderaadt
2694a5fbbc4Spjanzen /* s: chars allowed besides space or return */
2704a5fbbc4Spjanzen void
xwaitforspace(char * s)2714a5fbbc4Spjanzen xwaitforspace(char *s)
272df930be7Sderaadt {
2734a5fbbc4Spjanzen int c;
274df930be7Sderaadt
275df930be7Sderaadt morc = 0;
276df930be7Sderaadt
277df930be7Sderaadt while((c = readchar()) != '\n') {
278df930be7Sderaadt if(flags.cbreak) {
279df930be7Sderaadt if(c == ' ') break;
280180acc8fSmillert if(s && strchr(s,c)) {
281df930be7Sderaadt morc = c;
282df930be7Sderaadt break;
283df930be7Sderaadt }
2844a5fbbc4Spjanzen hackbell();
285df930be7Sderaadt }
286df930be7Sderaadt }
287df930be7Sderaadt }
288df930be7Sderaadt
289df930be7Sderaadt char *
parse(void)290aed906e4Smestre parse(void)
291df930be7Sderaadt {
292df930be7Sderaadt static char inputline[COLNO];
2934a5fbbc4Spjanzen int foo;
294df930be7Sderaadt
295df930be7Sderaadt flags.move = 1;
296df930be7Sderaadt if(!Invisible) curs_on_u(); else home();
297df930be7Sderaadt while((foo = readchar()) >= '0' && foo <= '9')
298df930be7Sderaadt multi = 10*multi+foo-'0';
299df930be7Sderaadt if(multi) {
300df930be7Sderaadt multi--;
301df930be7Sderaadt save_cm = inputline;
302df930be7Sderaadt }
303df930be7Sderaadt inputline[0] = foo;
304df930be7Sderaadt inputline[1] = 0;
305df930be7Sderaadt if(foo == 'f' || foo == 'F'){
306df930be7Sderaadt inputline[1] = getchar();
307df930be7Sderaadt #ifdef QUEST
308df930be7Sderaadt if(inputline[1] == foo) inputline[2] = getchar(); else
30954da88e4Spjanzen #endif /* QUEST */
310df930be7Sderaadt inputline[2] = 0;
311df930be7Sderaadt }
312df930be7Sderaadt if(foo == 'm' || foo == 'M'){
313df930be7Sderaadt inputline[1] = getchar();
314df930be7Sderaadt inputline[2] = 0;
315df930be7Sderaadt }
316df930be7Sderaadt clrlin();
317df930be7Sderaadt return(inputline);
318df930be7Sderaadt }
319df930be7Sderaadt
320df930be7Sderaadt char
readchar(void)321aed906e4Smestre readchar(void)
3224a5fbbc4Spjanzen {
3234a5fbbc4Spjanzen int sym;
324df930be7Sderaadt
325df930be7Sderaadt (void) fflush(stdout);
326df930be7Sderaadt if((sym = getchar()) == EOF)
327df930be7Sderaadt end_of_input();
328df930be7Sderaadt if(flags.toplin == 1)
329df930be7Sderaadt flags.toplin = 2;
330df930be7Sderaadt return((char) sym);
331df930be7Sderaadt }
332df930be7Sderaadt
3334a5fbbc4Spjanzen void
end_of_input(void)334aed906e4Smestre end_of_input(void)
335df930be7Sderaadt {
336df930be7Sderaadt settty("End of input?\n");
337df930be7Sderaadt clearlocks();
338df930be7Sderaadt exit(0);
339df930be7Sderaadt }
340