1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved */
29/*-
30 * Copyright (c) 1982, 1986, 1991, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)tty_compat.c 8.1 (Berkeley) 6/10/93
62 */
63
64/*
65 * Compatibility routines for BSD 4.3 tty ioctl() commands
66 *
67 * The only function externalized from this file is ttcompat() and it is
68 * externalized as private extern to prevent exporting of the symbol when
69 * KEXTs link against the kernel.
70 *
71 * Locks: All functions in this file assume that the tty_lock()
72 * is held on the tty structure before these functions are
73 * called.
74 */
75
76#include <sys/param.h>
77#include <sys/systm.h>
78#include <sys/ioctl.h>
79#include <sys/proc_internal.h>
80#include <sys/tty.h>
81#include <sys/termios.h>
82#include <sys/file_internal.h>
83#include <sys/conf.h>
84#include <sys/kernel.h>
85#include <sys/sysctl.h>
86#include <sys/syslog.h>
87
88static int ttcompatgetflags(struct tty *tp);
89static void ttcompatsetflags(struct tty *tp, struct termios *t);
90static void ttcompatsetlflags(struct tty *tp, struct termios *t);
91static int ttcompatspeedtab(int speed, struct speedtab *table);
92
93/*
94 * These two tables encode baud rate to speed code and speed code to
95 * baud rate information. They are a mapping between the <sys/termios.h>
96 * baud rate constants and the <sys/ttydev.h> baud rate constants. We
97 * cannot use those constants directly here because they occupy the same
98 * name space.
99 */
100static struct speedtab compatspeeds[] = {
101#define MAX_SPEED 17
102 { 115200, 17 },
103 { 57600, 16 },
104 { 38400, 15 },
105 { 19200, 14 },
106 { 9600, 13 },
107 { 4800, 12 },
108 { 2400, 11 },
109 { 1800, 10 },
110 { 1200, 9 },
111 { 600, 8 },
112 { 300, 7 },
113 { 200, 6 },
114 { 150, 5 },
115 { 134, 4 },
116 { 110, 3 },
117 { 75, 2 },
118 { 50, 1 },
119 { 0, 0 },
120 { -1, -1 },
121};
122static int compatspcodes[] = {
123 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
124 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
125};
126
127/*
128 * ttcompatspeedtab
129 *
130 * Description: Given a baud rate value as an integer, and a speed table,
131 * convert the baud rate to a speed code, according to the
132 * contents of the table. This effectively changes termios.h
133 * baud rate values into ttydev.h baud rate codes.
134 *
135 * Parameters: int speed Baud rate, as an integer
136 * struct speedtab *table Baud rate table to speed code table
137 *
138 * Returns: 1 B50 speed code; returned if we can
139 * not find an answer in the table.
140 * 0 If a 0 was requested in order to
141 * trigger a hangup (250ms of line
142 * silence, per Bell 103C standard).
143 * * A speed code matching the requested
144 * baud rate (potentially rounded down,
145 * if there is no exact match).
146 *
147 * Notes: This function is used for TIOCGETP, TIOCSETP, and TIOCSETN.
148 */
149static int
150ttcompatspeedtab(int speed, struct speedtab *table)
151{
152 if (speed == 0)
153 return (0); /* hangup */
154 for ( ; table->sp_speed > 0; table++)
155 if (table->sp_speed <= speed) /* nearest one, rounded down */
156 return (table->sp_code);
157 return (1); /* 50, min and not hangup */
158}
159
160
161/*
162 * ttsetcompat
163 *
164 * Description: Convert backward compatability set command arguments as
165 * follows:
166 *
167 * TIOCSETP -> TIOSETAF
168 * TIOCSETN -> TIOCSETA
169 * TIOCSETC -> TIOCSETA
170 * TIOCSLTC -> TIOCSETA
171 * TIOCLBIS -> TIOCSETA
172 * TIOCLBIC -> TIOCSETA
173 * TIOCLSET -> TIOCSETA
174 *
175 * The converted command argument and potentially modified 'term'
176 * argument are returned to ttcompat(), which will then call
177 * ttioctl_locked(), if this function returns successfully.
178 *
179 * Parameters struct tty *tp The tty on which the operation is
180 * being performed.
181 * u_long *com A pointer to the terminal input/output
182 * command being requested; its contents
183 * will be modified per the table above,
184 * on a non-error return.
185 * caddr_t data Command specific parameter data; this
186 * data is read but not modified.
187 * struct termios *term A local stack termios structure from
188 * ttcompat(), whose contents are to be
189 * modified based on *com and *data.
190 *
191 * Returns: EINVAL An input speed or output speed is
192 * outside the allowable range for a
193 * TIOCSETP or TIOCSETN command.
194 * 0 All other cases return 0.
195 *
196 * Notes: This function may modify the contents of the tp->t_flags
197 * field in a successful call to TIOCSETP, TIOCSETN, TIOCLBIS,
198 * TIOCLBIC, or TIOCLSET.
199 *
200 * All other tp fields will remain unmodifed, since the struct
201 * termios is a local stack copy from ttcompat(), and not the
202 * real thing. A subsequent call to ttioctl_locked() in
203 * ttcompat(), however, may result in subsequent changes.
204 *
205 * WARNING: This compatibility code is not 6/432 clean; it will only
206 * work for 32 bit processes on 32 bit kernels or 64 bit
207 * processes on 64 bit kernels. We are not addressing this
208 * due to <rdar://6904053>.
209 */
210static int
211ttsetcompat(struct tty *tp, u_long *com, caddr_t data, struct termios *term)
212{
213 switch (*com) {
214 case TIOCSETP:
215 /*
216 * Wait for all characters queued for output to drain, then
217 * Discard all characters queued for input, and then set
218 * the input and output speeds and device flags, per the
219 * contents of the struct sgttyb that 'data' points to.
220 */
221 case TIOCSETN:
222 /*
223 * Same as TIOCSETP, but the output is not drained, and any
224 * pending input is not discarded.
225 */
226 {
227 struct sgttyb *sg = (struct sgttyb *)data;
228 int speed;
229
230 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
231 return(EINVAL);
232 else if (speed != ttcompatspeedtab(tp->t_ispeed, compatspeeds))
233 term->c_ispeed = compatspcodes[speed];
234 else
235 term->c_ispeed = tp->t_ispeed;
236 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
237 return(EINVAL);
238 else if (speed != ttcompatspeedtab(tp->t_ospeed, compatspeeds))
239 term->c_ospeed = compatspcodes[speed];
240 else
241 term->c_ospeed = tp->t_ospeed;
242 term->c_cc[VERASE] = sg->sg_erase;
243 term->c_cc[VKILL] = sg->sg_kill;
244 tp->t_flags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff);
245 ttcompatsetflags(tp, term);
246 *com = (*com == TIOCSETP) ? TIOCSETAF : TIOCSETA;
247 break;
248 }
249 case TIOCSETC:
250 /*
251 * Set the terminal control characters per the contents of
252 * the struct tchars that 'data' points to.
253 */
254 {
255 struct tchars *tc = (struct tchars *)data;
256 cc_t *cc;
257
258 cc = term->c_cc;
259 cc[VINTR] = tc->t_intrc;
260 cc[VQUIT] = tc->t_quitc;
261 cc[VSTART] = tc->t_startc;
262 cc[VSTOP] = tc->t_stopc;
263 cc[VEOF] = tc->t_eofc;
264 cc[VEOL] = tc->t_brkc;
265 if (tc->t_brkc == -1)
266 cc[VEOL2] = _POSIX_VDISABLE;
267 *com = TIOCSETA;
268 break;
269 }
270 case TIOCSLTC:
271 /*
272 * Set the terminal control characters per the contents of
273 * the struct ltchars that 'data' points to.
274 */
275 {
276 struct ltchars *ltc = (struct ltchars *)data;
277 cc_t *cc;
278
279 cc = term->c_cc;
280 cc[VSUSP] = ltc->t_suspc;
281 cc[VDSUSP] = ltc->t_dsuspc;
282 cc[VREPRINT] = ltc->t_rprntc;
283 cc[VDISCARD] = ltc->t_flushc;
284 cc[VWERASE] = ltc->t_werasc;
285 cc[VLNEXT] = ltc->t_lnextc;
286 *com = TIOCSETA;
287 break;
288 }
289 case TIOCLBIS:
290 /*
291 * Set the bits in the terminal state local flags word
292 * (16 bits) for the terminal to the current bits OR
293 * those in the 16 bit value pointed to by 'data'.
294 */
295 case TIOCLBIC:
296 /*
297 * Clear the bits in the terminal state local flags word
298 * for the terminal to the current bits AND those bits NOT
299 * in the 16 bit value pointed to by 'data'.
300 */
301 case TIOCLSET:
302 /*
303 * Set the terminal state local flags word to exactly those
304 * bits that correspond to the 16 bit value pointed to by
305 * 'data'.
306 */
307 if (*com == TIOCLSET)
308 tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
309 else {
310 tp->t_flags =
311 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
312 if (*com == TIOCLBIS)
313 tp->t_flags |= *(int *)data<<16;
314 else
315 tp->t_flags &= ~(*(int *)data<<16);
316 }
317 ttcompatsetlflags(tp, term);
318 *com = TIOCSETA;
319 break;
320 }
321 return 0;
322}
323
324/*
325 * ttcompat
326 *
327 * Description: For 'set' commands, convert the command and arguments as
328 * necessary, and call ttioctl_locked(), returning the result
329 * as our result; for 'get' commands, obtain the requested data
330 * from the appropriate source, and return it in the expected
331 * format. If the command is not recognized, return EINVAL.
332 *
333 * Parameters struct tty *tp The tty on which the operation is
334 * being performed.
335 * u_long com The terminal input/output command
336 * being requested.
337 * caddr_t data The pointer to the user data argument
338 * provided with the command.
339 * int flag The file open flags (e.g. FREAD).
340 * struct proc *p The current process pointer for the
341 * operation.
342 *
343 * Returns: 0 Most 'get' operations can't fail, and
344 * therefore return this.
345 * ENOTTY TIOCGSID may return this when you
346 * attempt to get the session ID for a
347 * terminal with no associated session,
348 * or for which there is a session, but
349 * no session leader.
350 * ENOTTY If the command cannot be handled at
351 * this layer, this will be returned.
352 * * Any value returned by ttioctl_locked(),
353 * if a set command is requested.
354 *
355 * Notes: The process pointer may be a proxy on whose behalf we are
356 * operating, so it is not safe to simply use current_process()
357 * instead.
358 */
359/*ARGSUSED*/
360__private_extern__ int
361ttcompat(struct tty *tp, u_long com, caddr_t data, int flag, struct proc *p)
362{
363 switch (com) {
364 case TIOCSETP:
365 case TIOCSETN:
366 case TIOCSETC:
367 case TIOCSLTC:
368 case TIOCLBIS:
369 case TIOCLBIC:
370 case TIOCLSET:
371 /*
372 * See ttsetcompat() for a full description of these command
373 * values and their meanings.
374 */
375 {
376 struct termios term;
377 int error;
378
379 term = tp->t_termios;
380 if ((error = ttsetcompat(tp, &com, data, &term)) != 0)
381 return error;
382 return ttioctl_locked(tp, com, (caddr_t) &term, flag, p);
383 }
384 case TIOCGETP:
385 /*
386 * Get the current input and output speeds, and device
387 * flags, into the structure pointed to by 'data'.
388 */
389 {
390 struct sgttyb *sg = (struct sgttyb *)data;
391 cc_t *cc = tp->t_cc;
392
393 sg->sg_ospeed = ttcompatspeedtab(tp->t_ospeed, compatspeeds);
394 if (tp->t_ispeed == 0)
395 sg->sg_ispeed = sg->sg_ospeed;
396 else
397 sg->sg_ispeed = ttcompatspeedtab(tp->t_ispeed, compatspeeds);
398 sg->sg_erase = cc[VERASE];
399 sg->sg_kill = cc[VKILL];
400 sg->sg_flags = tp->t_flags = ttcompatgetflags(tp);
401 break;
402 }
403 case TIOCGETC:
404 /*
405 * Get the terminal control characters into the struct
406 * tchars that 'data' points to.
407 */
408 {
409 struct tchars *tc = (struct tchars *)data;
410 cc_t *cc = tp->t_cc;
411
412 tc->t_intrc = cc[VINTR];
413 tc->t_quitc = cc[VQUIT];
414 tc->t_startc = cc[VSTART];
415 tc->t_stopc = cc[VSTOP];
416 tc->t_eofc = cc[VEOF];
417 tc->t_brkc = cc[VEOL];
418 break;
419 }
420 case TIOCGLTC:
421 /*
422 * Get the terminal control characters into the struct
423 * ltchars that 'data' points to.
424 */
425 {
426 struct ltchars *ltc = (struct ltchars *)data;
427 cc_t *cc = tp->t_cc;
428
429 ltc->t_suspc = cc[VSUSP];
430 ltc->t_dsuspc = cc[VDSUSP];
431 ltc->t_rprntc = cc[VREPRINT];
432 ltc->t_flushc = cc[VDISCARD];
433 ltc->t_werasc = cc[VWERASE];
434 ltc->t_lnextc = cc[VLNEXT];
435 break;
436 }
437 case TIOCLGET:
438 /*
439 * Get the terminal state local flags word into the 16 bit
440 * value pointed to by 'data'.
441 */
442 tp->t_flags =
443 (ttcompatgetflags(tp) & 0xffff0000UL)
444 | (tp->t_flags & 0xffff);
445 *(int *)data = tp->t_flags>>16;
446 break;
447
448 case OTIOCGETD:
449 /*
450 * Get the current line discipline into the int pointed to
451 * by 'data'.
452 */
453 *(int *)data = tp->t_line ? tp->t_line : 2;
454 break;
455
456 case OTIOCSETD:
457 /*
458 * Set the current line discipline based on the value of the
459 * int pointed to by 'data'.
460 */
461 {
462 int ldisczero = 0;
463
464 return (ttioctl_locked(tp, TIOCSETD,
465 *(int *)data == 2 ? (caddr_t)&ldisczero : data, flag, p));
466 }
467
468 case OTIOCCONS:
469 /*
470 * Become the console device.
471 */
472 *(int *)data = 1;
473 return (ttioctl_locked(tp, TIOCCONS, data, flag, p));
474
475 case TIOCGSID:
476 /*
477 * Get the current session ID (controlling process' PID).
478 */
479 if (tp->t_session == NULL)
480 return ENOTTY;
481
482 if (tp->t_session->s_leader == NULL)
483 return ENOTTY;
484
485 *(int *) data = tp->t_session->s_leader->p_pid;
486 break;
487
488 default:
489 /*
490 * This ioctl is not handled at this layer.
491 */
492 return (ENOTTY);
493 }
494
495 /*
496 * Successful 'get' operation.
497 */
498 return (0);
499}
500
501/*
502 * ttcompatgetflags
503 *
504 * Description: Get the terminal state local flags, device flags, and current
505 * speed code for the device (all 32 bits are returned).
506 *
507 * Parameters struct tty *tp The tty on which the operation is
508 * being performed.
509 *
510 * Returns: * Integer value corresponding to the
511 * current terminal state local flags
512 * word.
513 *
514 * Notes: Caller is responsible for breaking these bits back out into
515 * separate 16 bit filelds, if that's what was actually desired.
516 */
517static int
518ttcompatgetflags(struct tty *tp)
519{
520 tcflag_t iflag = tp->t_iflag;
521 tcflag_t lflag = tp->t_lflag;
522 tcflag_t oflag = tp->t_oflag;
523 tcflag_t cflag = tp->t_cflag;
524 int flags = 0;
525
526 if (iflag&IXOFF)
527 flags |= TANDEM;
528 if (iflag&ICRNL || oflag&ONLCR)
529 flags |= CRMOD;
530 if ((cflag&CSIZE) == CS8) {
531 flags |= PASS8;
532 if (iflag&ISTRIP)
533 flags |= ANYP;
534 }
535 else if (cflag&PARENB) {
536 if (iflag&INPCK) {
537 if (cflag&PARODD)
538 flags |= ODDP;
539 else
540 flags |= EVENP;
541 } else
542 flags |= EVENP | ODDP;
543 }
544
545 if ((lflag&ICANON) == 0) {
546 /* fudge */
547 if (iflag&(INPCK|ISTRIP|IXON) || lflag&(IEXTEN|ISIG)
548 || (cflag&(CSIZE|PARENB)) != CS8)
549 flags |= CBREAK;
550 else
551 flags |= RAW;
552 }
553 if (!(flags&RAW) && !(oflag&OPOST) && (cflag&(CSIZE|PARENB)) == CS8)
554 flags |= LITOUT;
555 if (cflag&MDMBUF)
556 flags |= MDMBUF;
557 if ((cflag&HUPCL) == 0)
558 flags |= NOHANG;
559 if (oflag&OXTABS)
560 flags |= XTABS;
561 if (lflag&ECHOE)
562 flags |= CRTERA|CRTBS;
563 if (lflag&ECHOKE)
564 flags |= CRTKIL|CRTBS;
565 if (lflag&ECHOPRT)
566 flags |= PRTERA;
567 if (lflag&ECHOCTL)
568 flags |= CTLECH;
569 if ((iflag&IXANY) == 0)
570 flags |= DECCTQ;
571 flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
572 return (flags);
573}
574
575/*
576 * ttcompatsetflags
577 *
578 * Description: Given a set of compatability flags, convert the compatability
579 * flags in the terminal flags fields into canonical flags in the
580 * provided termios struct.
581 *
582 * Parameters: struct tty *tp The tty on which the operation is
583 * being performed.
584 * struct termios *t The termios structure into which to
585 * return the converted flags.
586 *
587 * Returns: void (implicit: *t, modified)
588 */
589static void
590ttcompatsetflags(struct tty *tp, struct termios *t)
591{
592 int flags = tp->t_flags;
593 tcflag_t iflag = t->c_iflag;
594 tcflag_t oflag = t->c_oflag;
595 tcflag_t lflag = t->c_lflag;
596 tcflag_t cflag = t->c_cflag;
597
598 if (flags & RAW) {
599 iflag = IGNBRK;
600 lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
601 } else {
602 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
603 iflag |= BRKINT|IXON|IMAXBEL;
604 lflag |= ISIG|IEXTEN|ECHOCTL; /* XXX was echoctl on ? */
605 if (flags & XTABS)
606 oflag |= OXTABS;
607 else
608 oflag &= ~OXTABS;
609 if (flags & CBREAK)
610 lflag &= ~ICANON;
611 else
612 lflag |= ICANON;
613 if (flags&CRMOD) {
614 iflag |= ICRNL;
615 oflag |= ONLCR;
616 } else {
617 iflag &= ~ICRNL;
618 oflag &= ~ONLCR;
619 }
620 }
621 if (flags&ECHO)
622 lflag |= ECHO;
623 else
624 lflag &= ~ECHO;
625
626 cflag &= ~(CSIZE|PARENB);
627 if (flags&(RAW|LITOUT|PASS8)) {
628 cflag |= CS8;
629 if (!(flags&(RAW|PASS8))
630 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
631 iflag |= ISTRIP;
632 else
633 iflag &= ~ISTRIP;
634 if (flags&(RAW|LITOUT))
635 oflag &= ~OPOST;
636 else
637 oflag |= OPOST;
638 } else {
639 cflag |= CS7|PARENB;
640 iflag |= ISTRIP;
641 oflag |= OPOST;
642 }
643 /* XXX don't set INPCK if RAW or PASS8? */
644 if ((flags&(EVENP|ODDP)) == EVENP) {
645 iflag |= INPCK;
646 cflag &= ~PARODD;
647 } else if ((flags&(EVENP|ODDP)) == ODDP) {
648 iflag |= INPCK;
649 cflag |= PARODD;
650 } else
651 iflag &= ~INPCK;
652 if (flags&TANDEM)
653 iflag |= IXOFF;
654 else
655 iflag &= ~IXOFF;
656 if ((flags&DECCTQ) == 0)
657 iflag |= IXANY;
658 else
659 iflag &= ~IXANY;
660 t->c_iflag = iflag;
661 t->c_oflag = oflag;
662 t->c_lflag = lflag;
663 t->c_cflag = cflag;
664}
665
666/*
667 * ttcompatsetlflags
668 *
669 * Description: Given a set of compatability terminal state local flags,
670 * convert the compatability flags in the terminal flags
671 * fields into canonical flags in the provided termios struct.
672 *
673 * Parameters: struct tty *tp The tty on which the operation is
674 * being performed.
675 * struct termios *t The termios structure into which to
676 * return the converted local flags.
677 *
678 * Returns: void (implicit: *t, modified)
679 */
680static void
681ttcompatsetlflags(struct tty *tp, struct termios *t)
682{
683 int flags = tp->t_flags;
684 tcflag_t iflag = t->c_iflag;
685 tcflag_t oflag = t->c_oflag;
686 tcflag_t lflag = t->c_lflag;
687 tcflag_t cflag = t->c_cflag;
688
689 iflag &= ~(PARMRK|IGNPAR|IGNCR|INLCR);
690 if (flags&CRTERA)
691 lflag |= ECHOE;
692 else
693 lflag &= ~ECHOE;
694 if (flags&CRTKIL)
695 lflag |= ECHOKE;
696 else
697 lflag &= ~ECHOKE;
698 if (flags&PRTERA)
699 lflag |= ECHOPRT;
700 else
701 lflag &= ~ECHOPRT;
702 if (flags&CTLECH)
703 lflag |= ECHOCTL;
704 else
705 lflag &= ~ECHOCTL;
706 if (flags&TANDEM)
707 iflag |= IXOFF;
708 else
709 iflag &= ~IXOFF;
710 if ((flags&DECCTQ) == 0)
711 iflag |= IXANY;
712 else
713 iflag &= ~IXANY;
714 if (flags & MDMBUF)
715 cflag |= MDMBUF;
716 else
717 cflag &= ~MDMBUF;
718 if (flags&NOHANG)
719 cflag &= ~HUPCL;
720 else
721 cflag |= HUPCL;
722 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
723 lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
724
725 /*
726 * The next if-else statement is copied from above so don't bother
727 * checking it separately. We could avoid fiddlling with the
728 * character size if the mode is already RAW or if neither the
729 * LITOUT bit or the PASS8 bit is being changed, but the delta of
730 * the change is not available here and skipping the RAW case would
731 * make the code different from above.
732 */
733 cflag &= ~(CSIZE|PARENB);
734 if (flags&(RAW|LITOUT|PASS8)) {
735 cflag |= CS8;
736 if (!(flags&(RAW|PASS8))
737 || (flags&(RAW|PASS8|ANYP)) == (PASS8|ANYP))
738 iflag |= ISTRIP;
739 else
740 iflag &= ~ISTRIP;
741 if (flags&(RAW|LITOUT))
742 oflag &= ~OPOST;
743 else
744 oflag |= OPOST;
745 } else {
746 cflag |= CS7|PARENB;
747 iflag |= ISTRIP;
748 oflag |= OPOST;
749 }
750 t->c_iflag = iflag;
751 t->c_oflag = oflag;
752 t->c_lflag = lflag;
753 t->c_cflag = cflag;
754}
755