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