2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/svr4/svr4_termios.c,v 1.5 1999/12/08 12:00:48 newton Exp $
29 * $DragonFly: src/sys/emulation/svr4/Attic/svr4_termios.c,v 1.3 2003/06/25 03:56:10 dillon Exp $
32 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/filedesc.h>
37 #include <sys/termios.h>
39 #include <sys/sysproto.h>
40 #include <sys/file2.h>
42 #include <svr4/svr4.h>
43 #include <svr4/svr4_util.h>
44 #include <svr4/svr4_ioctl.h>
45 #include <svr4/svr4_termios.h>
49 # define __CONCAT3(a,b,c) a ## b ## c
51 # define __CONCAT3(a,b,c) a/**/b/**/c
55 static u_long bsd_to_svr4_speed __P((u_long, u_long));
56 static u_long svr4_to_bsd_speed __P((u_long, u_long));
57 static void svr4_to_bsd_termios __P((const struct svr4_termios *,
58 struct termios *, int));
59 static void bsd_to_svr4_termios __P((const struct termios *,
60 struct svr4_termios *));
61 static void svr4_termio_to_termios __P((const struct svr4_termio *,
62 struct svr4_termios *));
63 static void svr4_termios_to_termio __P((const struct svr4_termios *,
64 struct svr4_termio *));
66 static void print_svr4_termios __P((const struct svr4_termios *));
67 static void print_bsd_termios __P((const struct termios *));
68 #endif /* DEBUG_SVR4 */
70 #define undefined_char(a,b) /**/
71 #define undefined_flag1(f,a,b) /**/
72 #define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/
73 #define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/
75 #define svr4_to_bsd_char(a,b) \
76 if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
77 if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
78 bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
80 bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
83 #define svr4_to_bsd_flag1(f,a,b) \
84 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
85 if (st->f & __CONCAT3(SVR4_,a,b)) \
86 bt->f |= __CONCAT(a,b); \
88 bt->f &= ~__CONCAT(a,b); \
91 #define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
92 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
93 bt->f &= ~__CONCAT(a,b); \
94 switch (st->f & __CONCAT3(SVR4_,a,b)) { \
95 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
96 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
100 #define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
101 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
102 bt->f &= ~__CONCAT(a,b); \
103 switch (st->f & __CONCAT3(SVR4_,a,b)) { \
104 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
105 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
106 case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
107 case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
112 #define bsd_to_svr4_char(a,b) \
113 if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
114 st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
116 st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
118 #define bsd_to_svr4_flag1(f,a,b) \
119 if (bt->f & __CONCAT(a,b)) \
120 st->f |= __CONCAT3(SVR4_,a,b); \
122 st->f &= ~__CONCAT3(SVR4_,a,b)
124 #define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
125 st->f &= ~__CONCAT(a,b); \
126 switch (bt->f & __CONCAT(a,b)) { \
127 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
128 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
131 #define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
132 st->f &= ~__CONCAT(a,b); \
133 switch (bt->f & __CONCAT(a,b)) { \
134 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
135 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
136 case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
137 case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
142 print_svr4_termios(st)
143 const struct svr4_termios *st;
146 DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
147 st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
149 for (i = 0; i < SVR4_NCCS; i++)
150 DPRINTF(("%o ", st->c_cc[i]));
156 print_bsd_termios(bt)
157 const struct termios *bt;
160 uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
161 bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
163 for (i = 0; i < NCCS; i++)
164 uprintf("%o ", bt->c_cc[i]);
167 #endif /* DEBUG_SVR4 */
170 bsd_to_svr4_speed(sp, mask)
176 #define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b)
195 default: sp = SVR4_B9600; /* XXX */
198 while ((mask & 1) == 0) {
208 svr4_to_bsd_speed(sp, mask)
212 while ((mask & 1) == 0) {
219 #define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b)
238 default: return B9600; /* XXX */
244 svr4_to_bsd_termios(st, bt, new)
245 const struct svr4_termios *st;
249 /* control characters */
251 * We process VMIN and VTIME first,
252 * because they are shared with VEOF and VEOL
254 svr4_to_bsd_char(V,MIN);
255 svr4_to_bsd_char(V,TIME);
257 svr4_to_bsd_char(V,INTR);
258 svr4_to_bsd_char(V,QUIT);
259 svr4_to_bsd_char(V,ERASE);
260 svr4_to_bsd_char(V,KILL);
261 svr4_to_bsd_char(V,EOF);
262 svr4_to_bsd_char(V,EOL);
263 svr4_to_bsd_char(V,EOL2);
264 undefined_char(V,SWTCH);
265 svr4_to_bsd_char(V,START);
266 svr4_to_bsd_char(V,STOP);
267 svr4_to_bsd_char(V,SUSP);
268 svr4_to_bsd_char(V,DSUSP);
269 svr4_to_bsd_char(V,REPRINT);
270 svr4_to_bsd_char(V,DISCARD);
271 svr4_to_bsd_char(V,WERASE);
272 svr4_to_bsd_char(V,LNEXT);
275 svr4_to_bsd_flag1(c_iflag,I,GNBRK);
276 svr4_to_bsd_flag1(c_iflag,B,RKINT);
277 svr4_to_bsd_flag1(c_iflag,I,GNPAR);
278 svr4_to_bsd_flag1(c_iflag,P,ARMRK);
279 svr4_to_bsd_flag1(c_iflag,I,NPCK);
280 svr4_to_bsd_flag1(c_iflag,I,STRIP);
281 svr4_to_bsd_flag1(c_iflag,I,NLCR);
282 svr4_to_bsd_flag1(c_iflag,I,GNCR);
283 svr4_to_bsd_flag1(c_iflag,I,CRNL);
284 undefined_flag1(c_iflag,I,UCLC);
285 svr4_to_bsd_flag1(c_iflag,I,XON);
286 svr4_to_bsd_flag1(c_iflag,I,XANY);
287 svr4_to_bsd_flag1(c_iflag,I,XOFF);
288 svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
289 undefined_flag1(c_iflag,D,OSMODE);
292 svr4_to_bsd_flag1(c_oflag,O,POST);
293 undefined_flag1(c_oflag,O,LCUC);
294 svr4_to_bsd_flag1(c_oflag,O,NLCR);
295 undefined_flag1(c_oflag,O,CRNL);
296 undefined_flag1(c_oflag,O,NOCR);
297 undefined_flag1(c_oflag,O,NLRET);
298 undefined_flag1(c_oflag,O,FILL);
299 undefined_flag1(c_oflag,O,FDEL);
300 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
301 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
302 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
303 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
304 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
305 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
306 undefined_flag1(c_oflag,P,AGEOUT);
307 undefined_flag1(c_oflag,W,RAP);
310 bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
311 svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
312 svr4_to_bsd_flag1(c_cflag,C,STOPB);
313 svr4_to_bsd_flag1(c_cflag,C,READ);
314 svr4_to_bsd_flag1(c_cflag,P,ARENB);
315 svr4_to_bsd_flag1(c_cflag,P,ARODD);
316 svr4_to_bsd_flag1(c_cflag,H,UPCL);
317 svr4_to_bsd_flag1(c_cflag,C,LOCAL);
318 undefined_flag1(c_cflag,R,CV1EN);
319 undefined_flag1(c_cflag,X,MT1EN);
320 undefined_flag1(c_cflag,L,OBLK);
321 undefined_flag1(c_cflag,X,CLUDE);
322 bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
323 undefined_flag1(c_cflag,P,AREXT);
325 /* line discipline modes */
326 svr4_to_bsd_flag1(c_lflag,I,SIG);
327 svr4_to_bsd_flag1(c_lflag,I,CANON);
328 undefined_flag1(c_lflag,X,CASE);
329 svr4_to_bsd_flag1(c_lflag,E,CHO);
330 svr4_to_bsd_flag1(c_lflag,E,CHOE);
331 svr4_to_bsd_flag1(c_lflag,E,CHOK);
332 svr4_to_bsd_flag1(c_lflag,E,CHONL);
333 svr4_to_bsd_flag1(c_lflag,N,OFLSH);
334 svr4_to_bsd_flag1(c_lflag,T,OSTOP);
335 svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
336 svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
337 svr4_to_bsd_flag1(c_lflag,E,CHOKE);
338 undefined_flag1(c_lflag,D,EFECHO);
339 svr4_to_bsd_flag1(c_lflag,F,LUSHO);
340 svr4_to_bsd_flag1(c_lflag,P,ENDIN);
341 svr4_to_bsd_flag1(c_lflag,I,EXTEN);
346 bsd_to_svr4_termios(bt, st)
347 const struct termios *bt;
348 struct svr4_termios *st;
350 /* control characters */
352 * We process VMIN and VTIME first,
353 * because they are shared with VEOF and VEOL
355 bsd_to_svr4_char(V,MIN);
356 bsd_to_svr4_char(V,TIME);
357 bsd_to_svr4_char(V,INTR);
358 bsd_to_svr4_char(V,QUIT);
359 bsd_to_svr4_char(V,ERASE);
360 bsd_to_svr4_char(V,KILL);
361 bsd_to_svr4_char(V,EOF);
362 bsd_to_svr4_char(V,EOL);
363 bsd_to_svr4_char(V,EOL2);
364 undefined_char(V,SWTCH);
365 bsd_to_svr4_char(V,START);
366 bsd_to_svr4_char(V,STOP);
367 bsd_to_svr4_char(V,SUSP);
368 bsd_to_svr4_char(V,DSUSP);
369 bsd_to_svr4_char(V,REPRINT);
370 bsd_to_svr4_char(V,DISCARD);
371 bsd_to_svr4_char(V,WERASE);
372 bsd_to_svr4_char(V,LNEXT);
375 bsd_to_svr4_flag1(c_iflag,I,GNBRK);
376 bsd_to_svr4_flag1(c_iflag,B,RKINT);
377 bsd_to_svr4_flag1(c_iflag,I,GNPAR);
378 bsd_to_svr4_flag1(c_iflag,P,ARMRK);
379 bsd_to_svr4_flag1(c_iflag,I,NPCK);
380 bsd_to_svr4_flag1(c_iflag,I,STRIP);
381 bsd_to_svr4_flag1(c_iflag,I,NLCR);
382 bsd_to_svr4_flag1(c_iflag,I,GNCR);
383 bsd_to_svr4_flag1(c_iflag,I,CRNL);
384 undefined_flag1(c_iflag,I,UCLC);
385 bsd_to_svr4_flag1(c_iflag,I,XON);
386 bsd_to_svr4_flag1(c_iflag,I,XANY);
387 bsd_to_svr4_flag1(c_iflag,I,XOFF);
388 bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
389 undefined_flag1(c_iflag,D,OSMODE);
392 bsd_to_svr4_flag1(c_oflag,O,POST);
393 undefined_flag1(c_oflag,O,LCUC);
394 bsd_to_svr4_flag1(c_oflag,O,NLCR);
395 undefined_flag1(c_oflag,O,CRNL);
396 undefined_flag1(c_oflag,O,NOCR);
397 undefined_flag1(c_oflag,O,NLRET);
398 undefined_flag1(c_oflag,O,FILL);
399 undefined_flag1(c_oflag,O,FDEL);
400 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
401 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
402 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
403 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
404 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
405 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
406 undefined_flag1(c_oflag,P,AGEOUT);
407 undefined_flag1(c_oflag,W,RAP);
410 st->c_cflag &= ~SVR4_CBAUD;
411 st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
412 bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
413 bsd_to_svr4_flag1(c_cflag,C,STOPB);
414 bsd_to_svr4_flag1(c_cflag,C,READ);
415 bsd_to_svr4_flag1(c_cflag,P,ARENB);
416 bsd_to_svr4_flag1(c_cflag,P,ARODD);
417 bsd_to_svr4_flag1(c_cflag,H,UPCL);
418 bsd_to_svr4_flag1(c_cflag,C,LOCAL);
419 undefined_flag1(c_cflag,R,CV1EN);
420 undefined_flag1(c_cflag,X,MT1EN);
421 undefined_flag1(c_cflag,L,OBLK);
422 undefined_flag1(c_cflag,X,CLUDE);
423 st->c_cflag &= ~SVR4_CIBAUD;
424 st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
426 undefined_flag1(c_oflag,P,AREXT);
428 /* line discipline modes */
429 bsd_to_svr4_flag1(c_lflag,I,SIG);
430 bsd_to_svr4_flag1(c_lflag,I,CANON);
431 undefined_flag1(c_lflag,X,CASE);
432 bsd_to_svr4_flag1(c_lflag,E,CHO);
433 bsd_to_svr4_flag1(c_lflag,E,CHOE);
434 bsd_to_svr4_flag1(c_lflag,E,CHOK);
435 bsd_to_svr4_flag1(c_lflag,E,CHONL);
436 bsd_to_svr4_flag1(c_lflag,N,OFLSH);
437 bsd_to_svr4_flag1(c_lflag,T,OSTOP);
438 bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
439 bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
440 bsd_to_svr4_flag1(c_lflag,E,CHOKE);
441 undefined_flag1(c_lflag,D,EFECHO);
442 bsd_to_svr4_flag1(c_lflag,F,LUSHO);
443 bsd_to_svr4_flag1(c_lflag,P,ENDIN);
444 bsd_to_svr4_flag1(c_lflag,I,EXTEN);
449 svr4_termio_to_termios(t, ts)
450 const struct svr4_termio *t;
451 struct svr4_termios *ts;
455 ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
456 ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
457 ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
458 ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
460 for (i = 0; i < SVR4_NCC; i++)
461 ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
466 svr4_termios_to_termio(ts, t)
467 const struct svr4_termios *ts;
468 struct svr4_termio *t;
472 t->c_iflag = (u_short) ts->c_iflag;
473 t->c_oflag = (u_short) ts->c_oflag;
474 t->c_cflag = (u_short) ts->c_cflag;
475 t->c_lflag = (u_short) ts->c_lflag;
476 t->c_line = 0; /* XXX */
478 for (i = 0; i < SVR4_NCC; i++)
479 t->c_cc[i] = (u_char) ts->c_cc[i];
483 svr4_term_ioctl(fp, td, retval, fd, cmd, data)
492 struct svr4_termios st;
493 struct svr4_termio t;
498 DPRINTF(("TERM ioctl %lx\n", cmd));
503 DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
504 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
507 memset(&st, 0, sizeof(st));
508 bsd_to_svr4_termios(&bt, &st);
511 print_bsd_termios(&bt);
512 print_svr4_termios(&st);
513 #endif /* DEBUG_SVR4 */
515 if (cmd == SVR4_TCGETA) {
516 svr4_termios_to_termio(&st, &t);
517 return copyout(&t, data, sizeof(t));
520 return copyout(&st, data, sizeof(st));
529 DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
530 /* get full BSD termios so we don't lose information */
531 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
538 if ((error = copyin(data, &st, sizeof(st))) != 0)
546 if ((error = copyin(data, &t, sizeof(t))) != 0)
549 svr4_termio_to_termios(&t, &st);
557 svr4_to_bsd_termios(&st, &bt, new);
562 DPRINTF(("ioctl(TCSET[A|S]);\n"));
567 DPRINTF(("ioctl(TCSET[A|S]W);\n"));
572 DPRINTF(("ioctl(TCSET[A|S]F);\n"));
578 print_bsd_termios(&bt);
579 print_svr4_termios(&st);
580 #endif /* DEBUG_SVR4 */
582 return fo_ioctl(fp, cmd, (caddr_t) &bt, td);
584 case SVR4_TIOCGWINSZ:
585 DPRINTF(("TIOCGWINSZ\n"));
587 struct svr4_winsize ws;
589 error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, td);
592 return copyout(&ws, data, sizeof(ws));
595 case SVR4_TIOCSWINSZ:
596 DPRINTF(("TIOCSWINSZ\n"));
598 struct svr4_winsize ws;
600 if ((error = copyin(data, &ws, sizeof(ws))) != 0)
602 return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, td);
606 DPRINTF(("teleport to STREAMS ioctls...\n"));
607 return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data);