tty_43.c revision 1.25 1 /* $NetBSD: tty_43.c,v 1.25 2008/04/23 13:44:46 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /*-
37 * Copyright (c) 1982, 1986, 1991, 1993
38 * The Regents of the University of California. All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)tty_compat.c 8.2 (Berkeley) 1/9/95
65 */
66
67 /*
68 * mapping routines for old line discipline (yuck)
69 */
70
71 #include <sys/cdefs.h>
72 __KERNEL_RCSID(0, "$NetBSD: tty_43.c,v 1.25 2008/04/23 13:44:46 ad Exp $");
73
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/ioctl.h>
77 #include <sys/proc.h>
78 #include <sys/conf.h>
79 #include <sys/tty.h>
80 #include <sys/termios.h>
81 #include <sys/file.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84 #include <sys/ioctl_compat.h>
85
86 /*
87 * XXX libcompat files should be included with config attributes
88 */
89 #ifdef COMPAT_OLDTTY
90
91 int ttydebug = 0;
92
93 static const struct speedtab compatspeeds[] = {
94 #define MAX_SPEED 17
95 { 115200, 17 },
96 { 57600, 16 },
97 { 38400, 15 },
98 { 19200, 14 },
99 { 9600, 13 },
100 { 4800, 12 },
101 { 2400, 11 },
102 { 1800, 10 },
103 { 1200, 9 },
104 { 600, 8 },
105 { 300, 7 },
106 { 200, 6 },
107 { 150, 5 },
108 { 134, 4 },
109 { 110, 3 },
110 { 75, 2 },
111 { 50, 1 },
112 { 0, 0 },
113 { -1, -1 },
114 };
115 static const int compatspcodes[] = {
116 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
117 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200
118 };
119
120 static int ttcompatgetflags(struct tty *);
121 static void ttcompatsetflags(struct tty *, struct termios *);
122 static void ttcompatsetlflags(struct tty *, struct termios *);
123
124 /*ARGSUSED*/
125 int
126 ttcompat(struct tty *tp, u_long com, void *data, int flag, struct lwp *l)
127 {
128
129 switch (com) {
130 case TIOCGETP: {
131 struct sgttyb *sg = (struct sgttyb *)data;
132 u_char *cc;
133 int speed;
134
135 mutex_spin_enter(&tty_lock);
136 cc = tp->t_cc;
137 speed = ttspeedtab(tp->t_ospeed, compatspeeds);
138 sg->sg_ospeed = (speed == -1) ? MAX_SPEED : speed;
139 if (tp->t_ispeed == 0)
140 sg->sg_ispeed = sg->sg_ospeed;
141 else {
142 speed = ttspeedtab(tp->t_ispeed, compatspeeds);
143 sg->sg_ispeed = (speed == -1) ? MAX_SPEED : speed;
144 }
145 sg->sg_erase = cc[VERASE];
146 sg->sg_kill = cc[VKILL];
147 sg->sg_flags = ttcompatgetflags(tp);
148 mutex_spin_exit(&tty_lock);
149 break;
150 }
151
152 case TIOCSETP:
153 case TIOCSETN: {
154 struct sgttyb *sg = (struct sgttyb *)data;
155 struct termios term;
156 int speed;
157
158 mutex_spin_enter(&tty_lock);
159 term = tp->t_termios;
160 if ((speed = sg->sg_ispeed) > MAX_SPEED || speed < 0)
161 term.c_ispeed = speed;
162 else
163 term.c_ispeed = compatspcodes[speed];
164 if ((speed = sg->sg_ospeed) > MAX_SPEED || speed < 0)
165 term.c_ospeed = speed;
166 else
167 term.c_ospeed = compatspcodes[speed];
168 term.c_cc[VERASE] = sg->sg_erase;
169 term.c_cc[VKILL] = sg->sg_kill;
170 tp->t_flags = (ttcompatgetflags(tp)&0xffff0000) | (sg->sg_flags&0xffff);
171 ttcompatsetflags(tp, &term);
172 mutex_spin_exit(&tty_lock);
173 return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
174 (void *)&term, flag, l));
175 }
176
177 case TIOCGETC: {
178 struct tchars *tc = (struct tchars *)data;
179 u_char *cc = tp->t_cc;
180
181 tc->t_intrc = cc[VINTR];
182 tc->t_quitc = cc[VQUIT];
183 tc->t_startc = cc[VSTART];
184 tc->t_stopc = cc[VSTOP];
185 tc->t_eofc = cc[VEOF];
186 tc->t_brkc = cc[VEOL];
187 break;
188 }
189 case TIOCSETC: {
190 struct tchars *tc = (struct tchars *)data;
191 u_char *cc = tp->t_cc;
192
193 cc[VINTR] = tc->t_intrc;
194 cc[VQUIT] = tc->t_quitc;
195 cc[VSTART] = tc->t_startc;
196 cc[VSTOP] = tc->t_stopc;
197 cc[VEOF] = tc->t_eofc;
198 cc[VEOL] = tc->t_brkc;
199 if (tc->t_brkc == (char)-1)
200 cc[VEOL2] = _POSIX_VDISABLE;
201 break;
202 }
203 case TIOCSLTC: {
204 struct ltchars *ltc = (struct ltchars *)data;
205 u_char *cc = tp->t_cc;
206
207 cc[VSUSP] = ltc->t_suspc;
208 cc[VDSUSP] = ltc->t_dsuspc;
209 cc[VREPRINT] = ltc->t_rprntc;
210 cc[VDISCARD] = ltc->t_flushc;
211 cc[VWERASE] = ltc->t_werasc;
212 cc[VLNEXT] = ltc->t_lnextc;
213 break;
214 }
215 case TIOCGLTC: {
216 struct ltchars *ltc = (struct ltchars *)data;
217 u_char *cc = tp->t_cc;
218
219 ltc->t_suspc = cc[VSUSP];
220 ltc->t_dsuspc = cc[VDSUSP];
221 ltc->t_rprntc = cc[VREPRINT];
222 ltc->t_flushc = cc[VDISCARD];
223 ltc->t_werasc = cc[VWERASE];
224 ltc->t_lnextc = cc[VLNEXT];
225 break;
226 }
227 case TIOCLBIS:
228 case TIOCLBIC:
229 case TIOCLSET: {
230 struct termios term;
231 int flags;
232
233 mutex_spin_enter(&tty_lock);
234 term = tp->t_termios;
235 flags = ttcompatgetflags(tp);
236 switch (com) {
237 case TIOCLSET:
238 tp->t_flags = (flags&0xffff) | (*(int *)data<<16);
239 break;
240 case TIOCLBIS:
241 tp->t_flags = flags | (*(int *)data<<16);
242 break;
243 case TIOCLBIC:
244 tp->t_flags = flags & ~(*(int *)data<<16);
245 break;
246 }
247 ttcompatsetlflags(tp, &term);
248 mutex_spin_exit(&tty_lock);
249 return (ttioctl(tp, TIOCSETA, (void *)&term, flag, l));
250 }
251 case TIOCLGET:
252 mutex_spin_enter(&tty_lock);
253 *(int *)data = ttcompatgetflags(tp)>>16;
254 mutex_spin_exit(&tty_lock);
255 if (ttydebug)
256 printf("CLGET: returning %x\n", *(int *)data);
257 break;
258
259 case OTIOCGETD:
260 mutex_spin_enter(&tty_lock);
261 *(int *)data = (tp->t_linesw == NULL) ?
262 2 /* XXX old NTTYDISC */ : tp->t_linesw->l_no;
263 mutex_spin_exit(&tty_lock);
264 break;
265
266 case OTIOCSETD: {
267 int ldisczero = 0;
268
269 return (ttioctl(tp, TIOCSETD,
270 *(int *)data == 2 ? (void *)&ldisczero : data, flag,
271 l));
272 }
273
274 case OTIOCCONS:
275 *(int *)data = 1;
276 return (ttioctl(tp, TIOCCONS, data, flag, l));
277
278 case TIOCHPCL:
279 mutex_spin_enter(&tty_lock);
280 SET(tp->t_cflag, HUPCL);
281 mutex_spin_exit(&tty_lock);
282 break;
283
284 case TIOCGSID:
285 mutex_enter(&proclist_lock);
286 if (tp->t_session == NULL) {
287 mutex_exit(&proclist_lock);
288 return ENOTTY;
289 }
290 if (tp->t_session->s_leader == NULL) {
291 mutex_exit(&proclist_lock);
292 return ENOTTY;
293 }
294 *(int *) data = tp->t_session->s_leader->p_pid;
295 mutex_exit(&proclist_lock);
296 break;
297
298 default:
299 return (EPASSTHROUGH);
300 }
301 return (0);
302 }
303
304 static int
305 ttcompatgetflags(struct tty *tp)
306 {
307 tcflag_t iflag = tp->t_iflag;
308 tcflag_t lflag = tp->t_lflag;
309 tcflag_t oflag = tp->t_oflag;
310 tcflag_t cflag = tp->t_cflag;
311 int flags = 0;
312
313 KASSERT(mutex_owned(&tty_lock));
314
315 if (ISSET(iflag, IXOFF))
316 SET(flags, TANDEM);
317 if (ISSET(iflag, ICRNL) || ISSET(oflag, ONLCR))
318 SET(flags, CRMOD);
319 if (ISSET(cflag, PARENB)) {
320 if (ISSET(iflag, INPCK)) {
321 if (ISSET(cflag, PARODD))
322 SET(flags, ODDP);
323 else
324 SET(flags, EVENP);
325 } else
326 SET(flags, ANYP);
327 }
328
329 if (!ISSET(lflag, ICANON)) {
330 /* fudge */
331 if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) ||
332 ISSET(cflag, PARENB))
333 SET(flags, CBREAK);
334 else
335 SET(flags, RAW);
336 }
337
338 if (ISSET(flags, RAW))
339 SET(flags, ISSET(tp->t_flags, LITOUT|PASS8));
340 else if (ISSET(cflag, CSIZE) == CS8) {
341 if (!ISSET(oflag, OPOST))
342 SET(flags, LITOUT);
343 if (!ISSET(iflag, ISTRIP))
344 SET(flags, PASS8);
345 }
346
347 if (ISSET(cflag, MDMBUF))
348 SET(flags, MDMBUF);
349 if (!ISSET(cflag, HUPCL))
350 SET(flags, NOHANG);
351 if (ISSET(oflag, OXTABS))
352 SET(flags, XTABS);
353 if (ISSET(lflag, ECHOE))
354 SET(flags, CRTERA|CRTBS);
355 if (ISSET(lflag, ECHOKE))
356 SET(flags, CRTKIL|CRTBS);
357 if (ISSET(lflag, ECHOPRT))
358 SET(flags, PRTERA);
359 if (ISSET(lflag, ECHOCTL))
360 SET(flags, CTLECH);
361 if (!ISSET(iflag, IXANY))
362 SET(flags, DECCTQ);
363 SET(flags, ISSET(lflag, ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH));
364 if (ttydebug)
365 printf("getflags: %x\n", flags);
366 return (flags);
367 }
368
369 static void
370 ttcompatsetflags(struct tty *tp, struct termios *t)
371 {
372 int flags = tp->t_flags;
373
374 KASSERT(mutex_owned(&tty_lock));
375
376 tcflag_t iflag = t->c_iflag;
377 tcflag_t oflag = t->c_oflag;
378 tcflag_t lflag = t->c_lflag;
379 tcflag_t cflag = t->c_cflag;
380
381 if (ISSET(flags, TANDEM))
382 SET(iflag, IXOFF);
383 else
384 CLR(iflag, IXOFF);
385 if (ISSET(flags, ECHO))
386 SET(lflag, ECHO);
387 else
388 CLR(lflag, ECHO);
389 if (ISSET(flags, CRMOD)) {
390 SET(iflag, ICRNL);
391 SET(oflag, ONLCR);
392 } else {
393 CLR(iflag, ICRNL);
394 CLR(oflag, ONLCR);
395 }
396 if (ISSET(flags, XTABS))
397 SET(oflag, OXTABS);
398 else
399 CLR(oflag, OXTABS);
400
401
402 if (ISSET(flags, RAW)) {
403 iflag &= IXOFF;
404 CLR(lflag, ISIG|ICANON|IEXTEN);
405 CLR(cflag, PARENB);
406 } else {
407 SET(iflag, BRKINT|IXON|IMAXBEL);
408 SET(lflag, ISIG|IEXTEN);
409 if (ISSET(flags, CBREAK))
410 CLR(lflag, ICANON);
411 else
412 SET(lflag, ICANON);
413 switch (ISSET(flags, ANYP)) {
414 case 0:
415 CLR(cflag, PARENB);
416 break;
417 case ANYP:
418 SET(cflag, PARENB);
419 CLR(iflag, INPCK);
420 break;
421 case EVENP:
422 SET(cflag, PARENB);
423 SET(iflag, INPCK);
424 CLR(cflag, PARODD);
425 break;
426 case ODDP:
427 SET(cflag, PARENB);
428 SET(iflag, INPCK);
429 SET(cflag, PARODD);
430 break;
431 }
432 }
433
434 if (ISSET(flags, RAW|LITOUT|PASS8)) {
435 CLR(cflag, CSIZE);
436 SET(cflag, CS8);
437 if (!ISSET(flags, RAW|PASS8))
438 SET(iflag, ISTRIP);
439 else
440 CLR(iflag, ISTRIP);
441 if (!ISSET(flags, RAW|LITOUT))
442 SET(oflag, OPOST);
443 else
444 CLR(oflag, OPOST);
445 } else {
446 CLR(cflag, CSIZE);
447 SET(cflag, CS7);
448 SET(iflag, ISTRIP);
449 SET(oflag, OPOST);
450 }
451
452 t->c_iflag = iflag;
453 t->c_oflag = oflag;
454 t->c_lflag = lflag;
455 t->c_cflag = cflag;
456 }
457
458 static void
459 ttcompatsetlflags(struct tty *tp, struct termios *t)
460 {
461 int flags = tp->t_flags;
462 tcflag_t iflag = t->c_iflag;
463 tcflag_t oflag = t->c_oflag;
464 tcflag_t lflag = t->c_lflag;
465 tcflag_t cflag = t->c_cflag;
466
467 KASSERT(mutex_owned(&tty_lock));
468
469 /* Nothing we can do with CRTBS. */
470 if (ISSET(flags, PRTERA))
471 SET(lflag, ECHOPRT);
472 else
473 CLR(lflag, ECHOPRT);
474 if (ISSET(flags, CRTERA))
475 SET(lflag, ECHOE);
476 else
477 CLR(lflag, ECHOE);
478 /* Nothing we can do with TILDE. */
479 if (ISSET(flags, MDMBUF))
480 SET(cflag, MDMBUF);
481 else
482 CLR(cflag, MDMBUF);
483 if (ISSET(flags, NOHANG))
484 CLR(cflag, HUPCL);
485 else
486 SET(cflag, HUPCL);
487 if (ISSET(flags, CRTKIL))
488 SET(lflag, ECHOKE);
489 else
490 CLR(lflag, ECHOKE);
491 if (ISSET(flags, CTLECH))
492 SET(lflag, ECHOCTL);
493 else
494 CLR(lflag, ECHOCTL);
495 if (!ISSET(flags, DECCTQ))
496 SET(iflag, IXANY);
497 else
498 CLR(iflag, IXANY);
499 CLR(lflag, TOSTOP|FLUSHO|PENDIN|NOFLSH);
500 SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH));
501
502 if (ISSET(flags, RAW|LITOUT|PASS8)) {
503 CLR(cflag, CSIZE);
504 SET(cflag, CS8);
505 if (!ISSET(flags, RAW|PASS8))
506 SET(iflag, ISTRIP);
507 else
508 CLR(iflag, ISTRIP);
509 if (!ISSET(flags, RAW|LITOUT))
510 SET(oflag, OPOST);
511 else
512 CLR(oflag, OPOST);
513 } else {
514 CLR(cflag, CSIZE);
515 SET(cflag, CS7);
516 SET(iflag, ISTRIP);
517 SET(oflag, OPOST);
518 }
519
520 t->c_iflag = iflag;
521 t->c_oflag = oflag;
522 t->c_lflag = lflag;
523 t->c_cflag = cflag;
524 }
525
526 #endif /* COMPAT_OLDTTY */
527