adding GNU dc ("desk calculator")
[unix-history] / sys / kern / tty_compat.c
CommitLineData
15637ed4
RG
1/*-
2 * Copyright (c) 1982, 1986, 1991 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 * @(#)tty_compat.c 7.10 (Berkeley) 5/9/91
34 *
35 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
36 * -------------------- ----- ----------------------
37 * CURRENT PATCH LEVEL: 2 00163
38 * -------------------- ----- ----------------------
39 *
40 * 22 Apr 93 David Greenman support for 57600 and 115200 baud
41 * 27 May 93 Andrew A. Chernov Make more compatible with POSIX
42 * 27 May 93 Bruce Evans The work David did above was replaced
43 * by Bruces work plus some more stuff.
44 * (Chernov's fixes from the net edited
45 * by Bruce)
46 * Guido van Rooij Fix a bug caused by Bruces patches.
47 *
48 */
49
50/*
51 * mapping routines for old line discipline (yuck)
52 */
53#ifdef COMPAT_43
54
55#include "param.h"
56#include "systm.h"
57#include "ioctl.h"
58#include "tty.h"
59#include "termios.h"
60#include "proc.h"
61#include "file.h"
62#include "conf.h"
63#include "dkstat.h"
64#include "kernel.h"
65#include "syslog.h"
66
67int ttydebug = 0;
68
69static struct speedtab compatspeeds[] = {
70#define MAX_SPEED 17
71 115200, 17,
72 57600, 16,
73 38400, 15,
74 19200, 14,
75 9600, 13,
76 4800, 12,
77 2400, 11,
78 1800, 10,
79 1200, 9,
80 600, 8,
81 300, 7,
82 200, 6,
83 150, 5,
84 134, 4,
85 110, 3,
86 75, 2,
87 50, 1,
88 0, 0,
89 -1, -1,
90};
91static int compatspcodes[] = {
92 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
93 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
94};
95
96/*ARGSUSED*/
97ttcompat(tp, com, data, flag)
98 register struct tty *tp;
99 caddr_t data;
100{
101
102 switch (com) {
103 case TIOCGETP: {
104 register struct sgttyb *sg = (struct sgttyb *)data;
105 register u_char *cc = tp->t_cc;
106 register speed;
107
108 speed = ttspeedtab(tp->t_ospeed, compatspeeds);
109 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed;
110 if (tp->t_ispeed == 0)
111 sg->sg_ispeed = sg->sg_ospeed;
112 else {
113 speed = ttspeedtab(tp->t_ispeed, compatspeeds);
114 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed;
115 }
116 sg->sg_erase = cc[VERASE];
117 sg->sg_kill = cc[VKILL];
118 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
119 break;
120 }
121
122 case TIOCSETP:
123 case TIOCSETN: {
124 register struct sgttyb *sg = (struct sgttyb *)data;
125 struct termios term;
126 int speed;
127
128 term = tp->t_termios;
129 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
130 term.c_ispeed = speed;
131 else
132 term.c_ispeed = compatspcodes[speed];
133 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
134 term.c_ospeed = speed;
135 else
136 term.c_ospeed = compatspcodes[speed];
137 term.c_cc[VERASE] = sg->sg_erase;
138 term.c_cc[VKILL] = sg->sg_kill;
139 tp->t_flags = tp->t_flags&0xffff0000 | sg->sg_flags&0xffff;
140 ttcompatsetflags(tp, &term);
141 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
142 (caddr_t)&term, flag));
143 }
144
145 case TIOCGETC: {
146 struct tchars *tc = (struct tchars *)data;
147 register u_char *cc = tp->t_cc;
148
149 tc->t_intrc = cc[VINTR];
150 tc->t_quitc = cc[VQUIT];
151 tc->t_startc = cc[VSTART];
152 tc->t_stopc = cc[VSTOP];
153 tc->t_eofc = cc[VEOF];
154 tc->t_brkc = cc[VEOL];
155 break;
156 }
157 case TIOCSETC: {
158 struct tchars *tc = (struct tchars *)data;
159 register u_char *cc = tp->t_cc;
160
161 cc[VINTR] = tc->t_intrc;
162 cc[VQUIT] = tc->t_quitc;
163 cc[VSTART] = tc->t_startc;
164 cc[VSTOP] = tc->t_stopc;
165 cc[VEOF] = tc->t_eofc;
166 cc[VEOL] = tc->t_brkc;
167 if (tc->t_brkc == -1)
168 cc[VEOL2] = _POSIX_VDISABLE;
169 break;
170 }
171 case TIOCSLTC: {
172 struct ltchars *ltc = (struct ltchars *)data;
173 register u_char *cc = tp->t_cc;
174
175 cc[VSUSP] = ltc->t_suspc;
176 cc[VDSUSP] = ltc->t_dsuspc;
177 cc[VREPRINT] = ltc->t_rprntc;
178 cc[VDISCARD] = ltc->t_flushc;
179 cc[VWERASE] = ltc->t_werasc;
180 cc[VLNEXT] = ltc->t_lnextc;
181 break;
182 }
183 case TIOCGLTC: {
184 struct ltchars *ltc = (struct ltchars *)data;
185 register u_char *cc = tp->t_cc;
186
187 ltc->t_suspc = cc[VSUSP];
188 ltc->t_dsuspc = cc[VDSUSP];
189 ltc->t_rprntc = cc[VREPRINT];
190 ltc->t_flushc = cc[VDISCARD];
191 ltc->t_werasc = cc[VWERASE];
192 ltc->t_lnextc = cc[VLNEXT];
193 break;
194 }
195 case TIOCLBIS:
196 case TIOCLBIC:
197 case TIOCLSET: {
198 struct termios term;
199
200 term = tp->t_termios;
201 if (com == TIOCLSET)
202 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
203 else {
204 tp->t_flags =
205 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
206 if (com == TIOCLBIS)
207 tp->t_flags |= *(int *)data<<16;
208 else
209 tp->t_flags &= ~(*(int *)data<<16);
210 }
211 ttcompatsetlflags(tp, &term);
212 return (ttioctl(tp, TIOCSETA, (caddr_t)&term, flag));
213 }
214 case TIOCLGET:
215 tp->t_flags =
216 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
217 *(int *)data = tp->t_flags>>16;
218 if (ttydebug)
219 printf("CLGET: returning %x\n", *(int *)data);
220 break;
221
222 case OTIOCGETD:
223 *(int *)data = tp->t_line ? tp->t_line : 2;
224 break;
225
226 case OTIOCSETD: {
227 int ldisczero = 0;
228
229 return (ttioctl(tp, TIOCSETD,
230 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
231 }
232
233 case OTIOCCONS:
234 *(int *)data = 1;
235 return (ttioctl(tp, TIOCCONS, data, flag));
236
237 default:
238 return (-1);
239 }
240 return (0);
241}
242
243ttcompatgetflags(tp)
244 register struct tty *tp;
245{
246 register long iflag = tp->t_iflag;
247 register long lflag = tp->t_lflag;
248 register long oflag = tp->t_oflag;
249 register long cflag = tp->t_cflag;
250 register flags = 0;
251
252 if (iflag&IXOFF)
253 flags |= TANDEM;
254 if (iflag&ICRNL || oflag&ONLCR)
255 flags |= CRMOD;
256 if ((cflag&CSIZE) == CS8) {
257 flags |= PASS8;
258 if (iflag&ISTRIP)
259 flags |= ANYP;
260 }
261 else if (cflag&PARENB) {
262 if (iflag&INPCK) {
263 if (cflag&PARODD)
264 flags |= ODDP;
265 else
266 flags |= EVENP;
267 }
268 else
269 flags |= EVENP | ODDP;
270 }
271
272 if ((lflag&ICANON) == 0) {
273 /* fudge */
274 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
275 || cflag&(CSIZE|PARENB) != CS8)
276 flags |= CBREAK;
277 else
278 flags |= RAW;
279 }
280 if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8)
281 flags |= LITOUT;
282 if (oflag&OXTABS)
283 flags |= XTABS;
284 if (lflag&ECHOE)
285 flags |= CRTERA|CRTBS;
286 if (lflag&ECHOKE)
287 flags |= CRTKIL|CRTBS;
288 if (lflag&ECHOPRT)
289 flags |= PRTERA;
290 if (lflag&ECHOCTL)
291 flags |= CTLECH;
292 if ((iflag&IXANY) == 0)
293 flags |= DECCTQ;
294 flags |= lflag&(ECHO|MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
295if (ttydebug)
296 printf("getflags: %x\n", flags);
297 return (flags);
298}
299
300ttcompatsetflags(tp, t)
301 register struct tty *tp;
302 register struct termios *t;
303{
304 register flags = tp->t_flags;
305 register long iflag = t->c_iflag;
306 register long oflag = t->c_oflag;
307 register long lflag = t->c_lflag;
308 register long cflag = t->c_cflag;
309
310 if (flags & RAW) {
311 iflag &= IXOFF|IXANY;
312 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
313 } else {
314 iflag |= BRKINT|IXON|IMAXBEL;
315 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */
316 if (flags & XTABS)
317 oflag |= OXTABS;
318 else
319 oflag &= ~OXTABS;
320 if (flags & CBREAK)
321 lflag &= ~ICANON;
322 else
323 lflag |= ICANON;
324 if (flags&CRMOD) {
325 iflag |= ICRNL;
326 oflag |= ONLCR;
327 } else {
328 iflag &= ~ICRNL;
329 oflag &= ~ONLCR;
330 }
331 }
332 if (flags&ECHO)
333 lflag |= ECHO;
334 else
335 lflag &= ~ECHO;
336
337 cflag &= ~(CSIZE|PARENB);
338 if (flags&(RAW|LITOUT|PASS8)) {
339 cflag |= CS8;
340 if (!(flags&(RAW|PASS8))
341 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
342 iflag |= ISTRIP;
343 else
344 iflag &= ~ISTRIP;
345 if (flags&(RAW|LITOUT))
346 oflag &= ~OPOST;
347 else
348 oflag |= OPOST;
349 } else {
350 cflag |= CS7|PARENB;
351 iflag |= ISTRIP;
352 oflag |= OPOST;
353 }
354 if ((flags&(EVENP|ODDP)) == EVENP) {
355 iflag |= INPCK;
356 cflag &= ~PARODD;
357 } else if ((flags&(EVENP|ODDP)) == ODDP) {
358 iflag |= INPCK;
359 cflag |= PARODD;
360 } else
361 iflag &= ~INPCK;
362 if (flags&TANDEM)
363 iflag |= IXOFF;
364 else
365 iflag &= ~IXOFF;
366 t->c_iflag = iflag;
367 t->c_oflag = oflag;
368 t->c_lflag = lflag;
369 t->c_cflag = cflag;
370}
371
372ttcompatsetlflags(tp, t)
373 register struct tty *tp;
374 register struct termios *t;
375{
376 register flags = tp->t_flags;
377 register long iflag = t->c_iflag;
378 register long oflag = t->c_oflag;
379 register long lflag = t->c_lflag;
380 register long cflag = t->c_cflag;
381
382 if (flags&CRTERA)
383 lflag |= ECHOE;
384 else
385 lflag &= ~ECHOE;
386 if (flags&CRTKIL)
387 lflag |= ECHOKE;
388 else
389 lflag &= ~ECHOKE;
390 if (flags&PRTERA)
391 lflag |= ECHOPRT;
392 else
393 lflag &= ~ECHOPRT;
394 if (flags&CTLECH)
395 lflag |= ECHOCTL;
396 else
397 lflag &= ~ECHOCTL;
398 if ((flags&DECCTQ) == 0)
399 lflag |= IXANY;
400 else
401 lflag &= ~IXANY;
402 lflag &= ~(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
403 lflag |= flags&(MDMBUF|TOSTOP|FLUSHO|NOHANG|PENDIN|NOFLSH);
404
405 cflag &= ~(CSIZE|PARENB);
406 /*
407 * The next if-else statement is copied from above so don't bother
408 * checking it separately. We could avoid fiddlling with the
409 * character size if the mode is already RAW or if neither the
410 * LITOUT bit or the PASS8 bit is being changed, but the delta of
411 * the change is not available here and skipping the RAW case would
412 * make the code different from above.
413 */
414 if (flags&(RAW|LITOUT|PASS8)) {
415 cflag |= CS8;
416 if (!(flags&(RAW|PASS8))
417 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
418 iflag |= ISTRIP;
419 else
420 iflag &= ~ISTRIP;
421 if (flags&(RAW|LITOUT))
422 oflag &= ~OPOST;
423 else
424 oflag |= OPOST;
425 } else {
426 cflag |= CS7|PARENB;
427 iflag |= ISTRIP;
428 oflag |= OPOST;
429 }
430 t->c_iflag = iflag;
431 t->c_oflag = oflag;
432 t->c_lflag = lflag;
433 t->c_cflag = cflag;
434}
435#endif /* COMPAT_43 */