xref: /original-bsd/sys/kern/tty_compat.c (revision d272e02a)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)tty_compat.c	7.7 (Berkeley) 02/15/91
7  */
8 
9 /*
10  * mapping routines for old line discipline (yuck)
11  */
12 #ifdef COMPAT_43
13 
14 #include "param.h"
15 #include "systm.h"
16 #include "user.h"
17 #include "ioctl.h"
18 #include "tty.h"
19 #include "termios.h"
20 #include "proc.h"
21 #include "file.h"
22 #include "conf.h"
23 #include "dkstat.h"
24 #include "uio.h"
25 #include "kernel.h"
26 #include "syslog.h"
27 
28 #include "machine/reg.h"
29 
30 int ttydebug = 0;
31 
32 static struct speedtab compatspeeds[] = {
33 	38400,	15,
34 	19200,	14,
35 	9600,	13,
36 	4800,	12,
37 	2400,	11,
38 	1800,	10,
39 	1200,	9,
40 	600,	8,
41 	300,	7,
42 	200,	6,
43 	150,	5,
44 	134,	4,
45 	110,	3,
46 	75,	2,
47 	50,	1,
48 	0,	0,
49 	-1,	-1,
50 };
51 static int compatspcodes[16] = {
52 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
53 	1800, 2400, 4800, 9600, 19200, 38400,
54 };
55 
56 ttspeedtab(speed, table)
57 	register struct speedtab *table;
58 {
59 
60 	for ( ; table->sp_speed != -1; table++)
61 		if (table->sp_speed == speed)
62 			return (table->sp_code);
63 	return (-1);
64 }
65 
66 /*ARGSUSED*/
67 ttcompat(tp, com, data, flag)
68 	register struct tty *tp;
69 	caddr_t data;
70 {
71 
72 	switch (com) {
73 	case TIOCGETP: {
74 		register struct sgttyb *sg = (struct sgttyb *)data;
75 		register u_char *cc = tp->t_cc;
76 		register speed;
77 
78 		speed = ttspeedtab(tp->t_ospeed, compatspeeds);
79 		sg->sg_ospeed = (speed == -1) ? 15 : speed;
80 		if (tp->t_ispeed == 0)
81 			sg->sg_ispeed = sg->sg_ospeed;
82 		else {
83 			speed = ttspeedtab(tp->t_ispeed, compatspeeds);
84 			sg->sg_ispeed = (speed == -1) ? 15 : speed;
85 		}
86 		sg->sg_erase = cc[VERASE];
87 		sg->sg_kill = cc[VKILL];
88 		sg->sg_flags = ttcompatgetflags(tp);
89 		break;
90 	}
91 
92 	case TIOCSETP:
93 	case TIOCSETN: {
94 		register struct sgttyb *sg = (struct sgttyb *)data;
95 		struct termios term;
96 		int speed;
97 
98 		term = tp->t_termios;
99 		if ((speed = sg->sg_ispeed) > 15 || speed < 0)
100 			term.c_ispeed = speed;
101 		else
102 			term.c_ispeed = compatspcodes[speed];
103 		if ((speed = sg->sg_ospeed) > 15 || speed < 0)
104 			term.c_ospeed = speed;
105 		else
106 			term.c_ospeed = compatspcodes[speed];
107 		term.c_cc[VERASE] = sg->sg_erase;
108 		term.c_cc[VKILL] = sg->sg_kill;
109 		tp->t_flags = tp->t_flags&0xffff0000 | sg->sg_flags&0xffff;
110 		ttcompatsetflags(tp, &term);
111 		return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
112 			&term, flag));
113 	}
114 
115 	case TIOCGETC: {
116 		struct tchars *tc = (struct tchars *)data;
117 		register u_char *cc = tp->t_cc;
118 
119 		tc->t_intrc = cc[VINTR];
120 		tc->t_quitc = cc[VQUIT];
121 		tc->t_startc = cc[VSTART];
122 		tc->t_stopc = cc[VSTOP];
123 		tc->t_eofc = cc[VEOF];
124 		tc->t_brkc = cc[VEOL];
125 		break;
126 	}
127 	case TIOCSETC: {
128 		struct tchars *tc = (struct tchars *)data;
129 		register u_char *cc = tp->t_cc;
130 
131 		cc[VINTR] = tc->t_intrc;
132 		cc[VQUIT] = tc->t_quitc;
133 		cc[VSTART] = tc->t_startc;
134 		cc[VSTOP] = tc->t_stopc;
135 		cc[VEOF] = tc->t_eofc;
136 		cc[VEOL] = tc->t_brkc;
137 		if (tc->t_brkc == -1)
138 			cc[VEOL2] = _POSIX_VDISABLE;
139 		break;
140 	}
141 	case TIOCSLTC: {
142 		struct ltchars *ltc = (struct ltchars *)data;
143 		register u_char *cc = tp->t_cc;
144 
145 		cc[VSUSP] = ltc->t_suspc;
146 		cc[VDSUSP] = ltc->t_dsuspc;
147 		cc[VREPRINT] = ltc->t_rprntc;
148 		cc[VDISCARD] = ltc->t_flushc;
149 		cc[VWERASE] = ltc->t_werasc;
150 		cc[VLNEXT] = ltc->t_lnextc;
151 		break;
152 	}
153 	case TIOCGLTC: {
154 		struct ltchars *ltc = (struct ltchars *)data;
155 		register u_char *cc = tp->t_cc;
156 
157 		ltc->t_suspc = cc[VSUSP];
158 		ltc->t_dsuspc = cc[VDSUSP];
159 		ltc->t_rprntc = cc[VREPRINT];
160 		ltc->t_flushc = cc[VDISCARD];
161 		ltc->t_werasc = cc[VWERASE];
162 		ltc->t_lnextc = cc[VLNEXT];
163 		break;
164 	}
165 	case TIOCLBIS:
166 	case TIOCLBIC:
167 	case TIOCLSET: {
168 		struct termios term;
169 
170 		term = tp->t_termios;
171 		if (com == TIOCLSET)
172 			tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
173 		else {
174 			tp->t_flags =
175 			 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
176 			if (com == TIOCLBIS)
177 				tp->t_flags |= *(int *)data<<16;
178 			else
179 				tp->t_flags &= ~(*(int *)data<<16);
180 		}
181 		ttcompatsetlflags(tp, &term);
182 		return (ttioctl(tp, TIOCSETA, &term, flag));
183 	}
184 	case TIOCLGET:
185 		*(int *)data = ttcompatgetflags(tp)>>16;
186 		if (ttydebug)
187 			printf("CLGET: returning %x\n", *(int *)data);
188 		break;
189 
190 	case OTIOCGETD:
191 		*(int *)data = tp->t_line ? tp->t_line : 2;
192 		break;
193 
194 	case OTIOCSETD: {
195 		int ldisczero = 0;
196 
197 		return (ttioctl(tp, TIOCSETD,
198 			*(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
199 	    }
200 
201 	case OTIOCCONS:
202 		*(int *)data = 1;
203 		return (ttioctl(tp, TIOCCONS, data, flag));
204 
205 	default:
206 		return (-1);
207 	}
208 	return (0);
209 }
210 
211 ttcompatgetflags(tp)
212 	register struct tty *tp;
213 {
214 	register long iflag = tp->t_iflag;
215 	register long lflag = tp->t_lflag;
216 	register long oflag = tp->t_oflag;
217 	register long cflag = tp->t_cflag;
218 	register flags = 0;
219 
220 	if (iflag&IXOFF)
221 		flags |= TANDEM;
222 	if (iflag&ICRNL || oflag&ONLCR)
223 		flags |= CRMOD;
224 	if (cflag&PARENB) {
225 		if (iflag&INPCK) {
226 			if (cflag&PARODD)
227 				flags |= ODDP;
228 			else
229 				flags |= EVENP;
230 		} else
231 			flags |= EVENP | ODDP;
232 	} else {
233 		if ((tp->t_flags&LITOUT) && !(oflag&OPOST))
234 			flags |= LITOUT;
235 		if (tp->t_flags&PASS8)
236 			flags |= PASS8;
237 	}
238 
239 	if ((lflag&ICANON) == 0) {
240 		/* fudge */
241 		if (iflag&IXON || lflag&ISIG || lflag&IEXTEN || cflag&PARENB)
242 			flags |= CBREAK;
243 		else
244 			flags |= RAW;
245 	}
246 	if (oflag&OXTABS)
247 		flags |= XTABS;
248 	if (lflag&ECHOE)
249 		flags |= CRTERA|CRTBS;
250 	if (lflag&ECHOKE)
251 		flags |= CRTKIL|CRTBS;
252 	if (lflag&ECHOPRT)
253 		flags |= PRTERA;
254 	if (lflag&ECHOCTL)
255 		flags |= CTLECH;
256 	if ((iflag&IXANY) == 0)
257 		flags |= DECCTQ;
258 	flags |= lflag&(ECHO|MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
259 if (ttydebug)
260 	printf("getflags: %x\n", flags);
261 	return (flags);
262 }
263 
264 ttcompatsetflags(tp, t)
265 	register struct tty *tp;
266 	register struct termios *t;
267 {
268 	register flags = tp->t_flags;
269 	register long iflag = t->c_iflag;
270 	register long oflag = t->c_oflag;
271 	register long lflag = t->c_lflag;
272 	register long cflag = t->c_cflag;
273 
274 	if (flags & RAW) {
275 		iflag &= IXOFF;
276 		oflag &= ~OPOST;
277 		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
278 	} else {
279 		iflag |= BRKINT|IXON|IMAXBEL;
280 		oflag |= OPOST;
281 		lflag |= ISIG|IEXTEN|ECHOCTL;	/* XXX was echoctl on ? */
282 		if (flags & XTABS)
283 			oflag |= OXTABS;
284 		else
285 			oflag &= ~OXTABS;
286 		if (flags & CBREAK)
287 			lflag &= ~ICANON;
288 		else
289 			lflag |= ICANON;
290 		if (flags&CRMOD) {
291 			iflag |= ICRNL;
292 			oflag |= ONLCR;
293 		} else {
294 			iflag &= ~ICRNL;
295 			oflag &= ~ONLCR;
296 		}
297 	}
298 	if (flags&ECHO)
299 		lflag |= ECHO;
300 	else
301 		lflag &= ~ECHO;
302 
303 	if (flags&(RAW|LITOUT|PASS8)) {
304 		cflag &= ~(CSIZE|PARENB);
305 		cflag |= CS8;
306 		if ((flags&(RAW|PASS8)) == 0)
307 			iflag |= ISTRIP;
308 		else
309 			iflag &= ~ISTRIP;
310 	} else {
311 		cflag &= ~CSIZE;
312 		cflag |= CS7|PARENB;
313 		iflag |= ISTRIP;
314 	}
315 	if ((flags&(EVENP|ODDP)) == EVENP) {
316 		iflag |= INPCK;
317 		cflag &= ~PARODD;
318 	} else if ((flags&(EVENP|ODDP)) == ODDP) {
319 		iflag |= INPCK;
320 		cflag |= PARODD;
321 	} else
322 		iflag &= ~INPCK;
323 	if (flags&LITOUT)
324 		oflag &= ~OPOST;	/* move earlier ? */
325 	if (flags&TANDEM)
326 		iflag |= IXOFF;
327 	else
328 		iflag &= ~IXOFF;
329 	t->c_iflag = iflag;
330 	t->c_oflag = oflag;
331 	t->c_lflag = lflag;
332 	t->c_cflag = cflag;
333 }
334 
335 ttcompatsetlflags(tp, t)
336 	register struct tty *tp;
337 	register struct termios *t;
338 {
339 	register flags = tp->t_flags;
340 	register long iflag = t->c_iflag;
341 	register long oflag = t->c_oflag;
342 	register long lflag = t->c_lflag;
343 	register long cflag = t->c_cflag;
344 
345 	if (flags&CRTERA)
346 		lflag |= ECHOE;
347 	else
348 		lflag &= ~ECHOE;
349 	if (flags&CRTKIL)
350 		lflag |= ECHOKE;
351 	else
352 		lflag &= ~ECHOKE;
353 	if (flags&PRTERA)
354 		lflag |= ECHOPRT;
355 	else
356 		lflag &= ~ECHOPRT;
357 	if (flags&CTLECH)
358 		lflag |= ECHOCTL;
359 	else
360 		lflag &= ~ECHOCTL;
361 	if ((flags&DECCTQ) == 0)
362 		lflag |= IXANY;
363 	else
364 		lflag &= ~IXANY;
365 	lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
366 	lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
367 	if (flags&(LITOUT|PASS8)) {
368 		iflag &= ~ISTRIP;
369 		cflag &= ~(CSIZE|PARENB);
370 		cflag |= CS8;
371 		if (flags&LITOUT)
372 			oflag &= ~OPOST;
373 		if ((flags&(PASS8|RAW)) == 0)
374 			iflag |= ISTRIP;
375 	} else if ((flags&RAW) == 0) {
376 		cflag &= ~CSIZE;
377 		cflag |= CS7|PARENB;
378 		oflag |= OPOST;
379 	}
380 	t->c_iflag = iflag;
381 	t->c_oflag = oflag;
382 	t->c_lflag = lflag;
383 	t->c_cflag = cflag;
384 }
385 #endif	/* COMPAT_43 */
386