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