]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/tty_compat.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / kern / tty_compat.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
26/*-
27 * Copyright (c) 1982, 1986, 1991, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93
59 */
60
61/*
62 * mapping routines for old line discipline (yuck)
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/ioctl.h>
68#include <sys/proc.h>
69#include <sys/tty.h>
70#include <sys/termios.h>
71#include <sys/file.h>
72#include <sys/conf.h>
73#include <sys/kernel.h>
74#include <sys/sysctl.h>
75#include <sys/syslog.h>
76
77/* NeXT Move define down here cause COMPAT_43 not valid earlier */
78#if COMPAT_43 || defined(COMPAT_SUNOS)
79
80static int ttcompatgetflags __P((struct tty *tp));
81static void ttcompatsetflags __P((struct tty *tp, struct termios *t));
82static void ttcompatsetlflags __P((struct tty *tp, struct termios *t));
83static int ttcompatspeedtab __P((int speed, struct speedtab *table));
84
85
86static int ttydebug = 0;
87
88#ifndef NeXT
89SYSCTL_INT(_debug, OID_AUTO, ttydebug, CTLFLAG_RW, &ttydebug, 0, "");
90#endif
91
92static struct speedtab compatspeeds[] = {
93#define MAX_SPEED 17
94 { 115200, 17 },
95 { 57600, 16 },
96 { 38400, 15 },
97 { 19200, 14 },
98 { 9600, 13 },
99 { 4800, 12 },
100 { 2400, 11 },
101 { 1800, 10 },
102 { 1200, 9 },
103 { 600, 8 },
104 { 300, 7 },
105 { 200, 6 },
106 { 150, 5 },
107 { 134, 4 },
108 { 110, 3 },
109 { 75, 2 },
110 { 50, 1 },
111 { 0, 0 },
112 { -1, -1 },
113};
114static int compatspcodes[] = {
115 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
116 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
117};
118
119static int
120ttcompatspeedtab(speed, table)
121 int speed;
122 register struct speedtab *table;
123{
124 if (speed == 0)
125 return (0); /* hangup */
126 for ( ; table->sp_speed > 0; table++)
127 if (table->sp_speed <= speed) /* nearest one, rounded down */
128 return (table->sp_code);
129 return (1); /* 50, min and not hangup */
130}
131
132#ifndef NeXT
133int
134ttsetcompat(tp, com, data, term)
135 register struct tty *tp;
136 int *com;
137 caddr_t data;
138 struct termios *term;
139#else
140__private_extern__ int
141ttsetcompat(tp, com, data, term)
142 register struct tty *tp;
143 u_long *com;
144 caddr_t data;
145 struct termios *term;
146#endif /* !NeXT */
147{
148 switch (*com) {
149 case TIOCSETP:
150 case TIOCSETN: {
151 register struct sgttyb *sg = (struct sgttyb *)data;
152 int speed;
153
154 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
155 return(EINVAL);
156 else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds))
157 term->c_ispeed = compatspcodes[speed];
158 else
159 term->c_ispeed = tp->t_ispeed;
160 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
161 return(EINVAL);
162 else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds))
163 term->c_ospeed = compatspcodes[speed];
164 else
165 term->c_ospeed = tp->t_ospeed;
166 term->c_cc[VERASE] = sg->sg_erase;
167 term->c_cc[VKILL] = sg->sg_kill;
168 tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
169 ttcompatsetflags(tp, term);
170 *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA;
171 break;
172 }
173 case TIOCSETC: {
174 struct tchars *tc = (struct tchars *)data;
175 register cc_t *cc;
176
177 cc = term->c_cc;
178 cc[VINTR] = tc->t_intrc;
179 cc[VQUIT] = tc->t_quitc;
180 cc[VSTART] = tc->t_startc;
181 cc[VSTOP] = tc->t_stopc;
182 cc[VEOF] = tc->t_eofc;
183 cc[VEOL] = tc->t_brkc;
184 if (tc->t_brkc == -1)
185 cc[VEOL2] = _POSIX_VDISABLE;
186 *com = TIOCSETA;
187 break;
188 }
189 case TIOCSLTC: {
190 struct ltchars *ltc = (struct ltchars *)data;
191 register cc_t *cc;
192
193 cc = term->c_cc;
194 cc[VSUSP] = ltc->t_suspc;
195 cc[VDSUSP] = ltc->t_dsuspc;
196 cc[VREPRINT] = ltc->t_rprntc;
197 cc[VDISCARD] = ltc->t_flushc;
198 cc[VWERASE] = ltc->t_werasc;
199 cc[VLNEXT] = ltc->t_lnextc;
200 *com = TIOCSETA;
201 break;
202 }
203 case TIOCLBIS:
204 case TIOCLBIC:
205 case TIOCLSET:
206 if (*com == TIOCLSET)
207 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
208 else {
209 tp->t_flags =
210 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
211 if (*com == TIOCLBIS)
212 tp->t_flags |= *(int *)data<<16;
213 else
214 tp->t_flags &= ~(*(int *)data<<16);
215 }
216 ttcompatsetlflags(tp, term);
217 *com = TIOCSETA;
218 break;
219 }
220 return 0;
221}
222
223/*ARGSUSED*/
224#ifndef NeXT
225int
226ttcompat(tp, com, data, flag)
227 register struct tty *tp;
228 int com;
229 caddr_t data;
230 int flag;
231#else
232__private_extern__ int
233ttcompat(tp, com, data, flag, p)
234 register struct tty *tp;
235 u_long com;
236 caddr_t data;
237 int flag;
238 struct proc *p;
239#endif /* !NeXT */
240{
241 switch (com) {
242 case TIOCSETP:
243 case TIOCSETN:
244 case TIOCSETC:
245 case TIOCSLTC:
246 case TIOCLBIS:
247 case TIOCLBIC:
248 case TIOCLSET: {
249 struct termios term;
250 int error;
251
252 term = tp->t_termios;
253 if ((error = ttsetcompat(tp, &com, data, &term)) != 0)
254 return error;
255#ifdef NeXT
256 return ttioctl(tp, com, (caddr_t) &term, flag, p);
257#else
258 return ttioctl(tp, com, &term, flag);
259#endif
260 }
261 case TIOCGETP: {
262 register struct sgttyb *sg = (struct sgttyb *)data;
263 register cc_t *cc = tp->t_cc;
264
265 sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds);
266 if (tp->t_ispeed == 0)
267 sg->sg_ispeed = sg->sg_ospeed;
268 else
269 sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds);
270 sg->sg_erase = cc[VERASE];
271 sg->sg_kill = cc[VKILL];
272 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
273 break;
274 }
275 case TIOCGETC: {
276 struct tchars *tc = (struct tchars *)data;
277 register cc_t *cc = tp->t_cc;
278
279 tc->t_intrc = cc[VINTR];
280 tc->t_quitc = cc[VQUIT];
281 tc->t_startc = cc[VSTART];
282 tc->t_stopc = cc[VSTOP];
283 tc->t_eofc = cc[VEOF];
284 tc->t_brkc = cc[VEOL];
285 break;
286 }
287 case TIOCGLTC: {
288 struct ltchars *ltc = (struct ltchars *)data;
289 register cc_t *cc = tp->t_cc;
290
291 ltc->t_suspc = cc[VSUSP];
292 ltc->t_dsuspc = cc[VDSUSP];
293 ltc->t_rprntc = cc[VREPRINT];
294 ltc->t_flushc = cc[VDISCARD];
295 ltc->t_werasc = cc[VWERASE];
296 ltc->t_lnextc = cc[VLNEXT];
297 break;
298 }
299 case TIOCLGET:
300 tp->t_flags =
301 (ttcompatgetflags(tp) & 0xffff0000UL)
302 | (tp->t_flags & 0xffff);
303 *(int *)data = tp->t_flags>>16;
304#ifndef NeXT
305 if (ttydebug)
306 printf("CLGET: returning %x\n", *(int *)data);
307#endif
308 break;
309
310 case OTIOCGETD:
311 *(int *)data = tp->t_line ? tp->t_line : 2;
312 break;
313
314#ifndef NeXT
315 case OTIOCSETD: {
316 int ldisczero = 0;
317
318 return (ttioctl(tp, TIOCSETD,
319 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
320 }
321
322 case OTIOCCONS:
323 *(int *)data = 1;
324 return (ttioctl(tp, TIOCCONS, data, flag));
325#else
326 case OTIOCSETD: {
327 int ldisczero = 0;
328
329 return (ttioctl(tp, TIOCSETD,
330 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag, p));
331 }
332
333 case OTIOCCONS:
334 *(int *)data = 1;
335 return (ttioctl(tp, TIOCCONS, data, flag, p));
336
337 case TIOCGSID:
338 if (tp->t_session == NULL)
339 return ENOTTY;
340
341 if (tp->t_session->s_leader == NULL)
342 return ENOTTY;
343
344 *(int *) data = tp->t_session->s_leader->p_pid;
345 break;
346#endif /* NeXT */
347
348 default:
349 return (-1);
350 }
351 return (0);
352}
353
354static int
355ttcompatgetflags(tp)
356 register struct tty *tp;
357{
358 register tcflag_t iflag = tp->t_iflag;
359 register tcflag_t lflag = tp->t_lflag;
360 register tcflag_t oflag = tp->t_oflag;
361 register tcflag_t cflag = tp->t_cflag;
362 register flags = 0;
363
364 if (iflag&IXOFF)
365 flags |= TANDEM;
366 if (iflag&ICRNL || oflag&ONLCR)
367 flags |= CRMOD;
368 if ((cflag&CSIZE) == CS8) {
369 flags |= PASS8;
370 if (iflag&ISTRIP)
371 flags |= ANYP;
372 }
373 else if (cflag&PARENB) {
374 if (iflag&INPCK) {
375 if (cflag&PARODD)
376 flags |= ODDP;
377 else
378 flags |= EVENP;
379 } else
380 flags |= EVENP | ODDP;
381 }
382
383 if ((lflag&ICANON) == 0) {
384 /* fudge */
385 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
386 || cflag&(CSIZE|PARENB) != CS8)
387 flags |= CBREAK;
388 else
389 flags |= RAW;
390 }
391 if (!(flags&RAW) && !(oflag&OPOST) && cflag&(CSIZE|PARENB) == CS8)
392 flags |= LITOUT;
393 if (cflag&MDMBUF)
394 flags |= MDMBUF;
395 if ((cflag&HUPCL) == 0)
396 flags |= NOHANG;
397 if (oflag&OXTABS)
398 flags |= XTABS;
399 if (lflag&ECHOE)
400 flags |= CRTERA|CRTBS;
401 if (lflag&ECHOKE)
402 flags |= CRTKIL|CRTBS;
403 if (lflag&ECHOPRT)
404 flags |= PRTERA;
405 if (lflag&ECHOCTL)
406 flags |= CTLECH;
407 if ((iflag&IXANY) == 0)
408 flags |= DECCTQ;
409 flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
410#ifndef NeXT
411 if (ttydebug)
412 printf("getflags: %x\n", flags);
413#endif
414 return (flags);
415}
416
417static void
418ttcompatsetflags(tp, t)
419 register struct tty *tp;
420 register struct termios *t;
421{
422 register flags = tp->t_flags;
423 register tcflag_t iflag = t->c_iflag;
424 register tcflag_t oflag = t->c_oflag;
425 register tcflag_t lflag = t->c_lflag;
426 register tcflag_t cflag = t->c_cflag;
427
428 if (flags & RAW) {
429 iflag = IGNBRK;
430 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
431 } else {
432 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
433 iflag |= BRKINT|IXON|IMAXBEL;
434 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */
435 if (flags & XTABS)
436 oflag |= OXTABS;
437 else
438 oflag &= ~OXTABS;
439 if (flags & CBREAK)
440 lflag &= ~ICANON;
441 else
442 lflag |= ICANON;
443 if (flags&CRMOD) {
444 iflag |= ICRNL;
445 oflag |= ONLCR;
446 } else {
447 iflag &= ~ICRNL;
448 oflag &= ~ONLCR;
449 }
450 }
451 if (flags&ECHO)
452 lflag |= ECHO;
453 else
454 lflag &= ~ECHO;
455
456 cflag &= ~(CSIZE|PARENB);
457 if (flags&(RAW|LITOUT|PASS8)) {
458 cflag |= CS8;
459 if (!(flags&(RAW|PASS8))
460 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
461 iflag |= ISTRIP;
462 else
463 iflag &= ~ISTRIP;
464 if (flags&(RAW|LITOUT))
465 oflag &= ~OPOST;
466 else
467 oflag |= OPOST;
468 } else {
469 cflag |= CS7|PARENB;
470 iflag |= ISTRIP;
471 oflag |= OPOST;
472 }
473 /* XXX don't set INPCK if RAW or PASS8? */
474 if ((flags&(EVENP|ODDP)) == EVENP) {
475 iflag |= INPCK;
476 cflag &= ~PARODD;
477 } else if ((flags&(EVENP|ODDP)) == ODDP) {
478 iflag |= INPCK;
479 cflag |= PARODD;
480 } else
481 iflag &= ~INPCK;
482 if (flags&TANDEM)
483 iflag |= IXOFF;
484 else
485 iflag &= ~IXOFF;
486 if ((flags&DECCTQ) == 0)
487 iflag |= IXANY;
488 else
489 iflag &= ~IXANY;
490 t->c_iflag = iflag;
491 t->c_oflag = oflag;
492 t->c_lflag = lflag;
493 t->c_cflag = cflag;
494}
495
496static void
497ttcompatsetlflags(tp, t)
498 register struct tty *tp;
499 register struct termios *t;
500{
501 register flags = tp->t_flags;
502 register tcflag_t iflag = t->c_iflag;
503 register tcflag_t oflag = t->c_oflag;
504 register tcflag_t lflag = t->c_lflag;
505 register tcflag_t cflag = t->c_cflag;
506
507 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
508 if (flags&CRTERA)
509 lflag |= ECHOE;
510 else
511 lflag &= ~ECHOE;
512 if (flags&CRTKIL)
513 lflag |= ECHOKE;
514 else
515 lflag &= ~ECHOKE;
516 if (flags&PRTERA)
517 lflag |= ECHOPRT;
518 else
519 lflag &= ~ECHOPRT;
520 if (flags&CTLECH)
521 lflag |= ECHOCTL;
522 else
523 lflag &= ~ECHOCTL;
524 if (flags&TANDEM)
525 iflag |= IXOFF;
526 else
527 iflag &= ~IXOFF;
528 if ((flags&DECCTQ) == 0)
529 iflag |= IXANY;
530 else
531 iflag &= ~IXANY;
532 if (flags & MDMBUF)
533 cflag |= MDMBUF;
534 else
535 cflag &= ~MDMBUF;
536 if (flags&NOHANG)
537 cflag &= ~HUPCL;
538 else
539 cflag |= HUPCL;
540 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
541 lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
542
543 /*
544 * The next if-else statement is copied from above so don't bother
545 * checking it separately. We could avoid fiddlling with the
546 * character size if the mode is already RAW or if neither the
547 * LITOUT bit or the PASS8 bit is being changed, but the delta of
548 * the change is not available here and skipping the RAW case would
549 * make the code different from above.
550 */
551 cflag &= ~(CSIZE|PARENB);
552 if (flags&(RAW|LITOUT|PASS8)) {
553 cflag |= CS8;
554 if (!(flags&(RAW|PASS8))
555 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
556 iflag |= ISTRIP;
557 else
558 iflag &= ~ISTRIP;
559 if (flags&(RAW|LITOUT))
560 oflag &= ~OPOST;
561 else
562 oflag |= OPOST;
563 } else {
564 cflag |= CS7|PARENB;
565 iflag |= ISTRIP;
566 oflag |= OPOST;
567 }
568 t->c_iflag = iflag;
569 t->c_oflag = oflag;
570 t->c_lflag = lflag;
571 t->c_cflag = cflag;
572}
573#endif /* COMPAT_43 || COMPAT_SUNOS */