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