1/* $NetBSD: svr4_32_termios.c,v 1.16 2008/03/21 21:54:59 ad Exp $ */ 2 3/*- 4 * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: svr4_32_termios.c,v 1.16 2008/03/21 21:54:59 ad Exp $"); 34 35#include <sys/param.h> 36#include <sys/proc.h> 37#include <sys/systm.h> 38#include <sys/file.h> 39#include <sys/filedesc.h> 40#include <sys/ioctl.h> 41#include <sys/termios.h> 42#include <sys/tty.h> 43#include <sys/socket.h> 44#include <sys/mount.h> 45#include <net/if.h> 46#include <sys/malloc.h> 47 48#include <sys/syscallargs.h> 49 50#include <compat/svr4_32/svr4_32_types.h> 51#include <compat/svr4_32/svr4_32_util.h> 52#include <compat/svr4_32/svr4_32_signal.h> 53#include <compat/svr4_32/svr4_32_ioctl.h> 54#include <compat/svr4_32/svr4_32_lwp.h> 55#include <compat/svr4_32/svr4_32_ucontext.h> 56#include <compat/svr4_32/svr4_32_syscallargs.h> 57#include <compat/svr4_32/svr4_32_stropts.h> 58#include <compat/svr4_32/svr4_32_termios.h> 59 60 61#ifndef __CONCAT3 62# if __STDC__ 63# define __CONCAT3(a,b,c) a ## b ## c 64# else 65# define __CONCAT3(a,b,c) a/**/b/**/c 66# endif 67#endif 68 69static u_long bsd_to_svr4_32_speed(u_long, u_long); 70static u_long svr4_32_to_bsd_speed(u_long, u_long); 71static void svr4_32_to_bsd_termios(const struct svr4_32_termios *, 72 struct termios *, int); 73static void bsd_to_svr4_32_termios(const struct termios *, 74 struct svr4_32_termios *); 75static void svr4_termio_to_termios(const struct svr4_termio *, 76 struct svr4_32_termios *); 77static void svr4_32_termios_to_termio(const struct svr4_32_termios *, 78 struct svr4_termio *); 79#ifdef DEBUG_SVR4 80static void print_svr4_32_termios(const struct svr4_32_termios *); 81static void print_bsd_termios(const struct termios *); 82#endif /* DEBUG_SVR4 */ 83 84#define undefined_char(a,b) /**/ 85#define undefined_flag1(f,a,b) /**/ 86#define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/ 87#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/ 88 89#define svr4_to_bsd_char(a,b) \ 90 if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \ 91 if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \ 92 bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \ 93 else \ 94 bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \ 95 } 96 97#define svr4_to_bsd_flag1(f,a,b) \ 98 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 99 if (st->f & __CONCAT3(SVR4_,a,b)) \ 100 bt->f |= __CONCAT(a,b); \ 101 else \ 102 bt->f &= ~__CONCAT(a,b); \ 103 } 104 105#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \ 106 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 107 bt->f &= ~__CONCAT(a,b); \ 108 switch (st->f & __CONCAT3(SVR4_,a,b)) { \ 109 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ 110 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ 111 } \ 112 } 113 114#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ 115 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 116 bt->f &= ~__CONCAT(a,b); \ 117 switch (st->f & __CONCAT3(SVR4_,a,b)) { \ 118 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ 119 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ 120 case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \ 121 case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \ 122 } \ 123 } 124 125 126#define bsd_to_svr4_char(a,b) \ 127 if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \ 128 st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \ 129 else \ 130 st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)] 131 132#define bsd_to_svr4_flag1(f,a,b) \ 133 if (bt->f & __CONCAT(a,b)) \ 134 st->f |= __CONCAT3(SVR4_,a,b); \ 135 else \ 136 st->f &= ~__CONCAT3(SVR4_,a,b) 137 138#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \ 139 st->f &= ~__CONCAT(a,b); \ 140 switch (bt->f & __CONCAT(a,b)) { \ 141 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ 142 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ 143 } 144 145#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ 146 st->f &= ~__CONCAT(a,b); \ 147 switch (bt->f & __CONCAT(a,b)) { \ 148 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ 149 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ 150 case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \ 151 case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \ 152 } 153 154#ifdef DEBUG_SVR4 155static void 156print_svr4_32_termios(const struct svr4_32_termios *st) 157{ 158 int i; 159 uprintf("SVR4_32\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n", 160 st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag); 161 uprintf("cc: "); 162 for (i = 0; i < SVR4_NCCS; i++) 163 uprintf("%o ", st->c_cc[i]); 164 uprintf("\n"); 165} 166 167 168static void 169print_bsd_termios(const struct termios *bt) 170{ 171 int i; 172 uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n", 173 bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag); 174 uprintf("cc: "); 175 for (i = 0; i < NCCS; i++) 176 uprintf("%o ", bt->c_cc[i]); 177 uprintf("\n"); 178} 179#endif /* DEBUG_SVR4 */ 180 181static u_long 182bsd_to_svr4_32_speed(u_long sp, u_long mask) 183{ 184 switch (sp) { 185#undef getval 186#define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b) 187 getval(B,0); 188 getval(B,50); 189 getval(B,75); 190 getval(B,110); 191 getval(B,134); 192 getval(B,150); 193 getval(B,200); 194 getval(B,300); 195 getval(B,600); 196 getval(B,1200); 197 getval(B,1800); 198 getval(B,2400); 199 getval(B,4800); 200 getval(B,9600); 201 getval(B,19200); 202 getval(B,38400); 203 getval(B,57600); 204 getval(B,115200); 205 default: sp = SVR4_B9600; /* XXX */ 206 } 207 208 while ((mask & 1) == 0) { 209 mask >>= 1; 210 sp <<= 1; 211 } 212 213 return sp; 214} 215 216 217static u_long 218svr4_32_to_bsd_speed(u_long sp, u_long mask) 219{ 220 while ((mask & 1) == 0) { 221 mask >>= 1; 222 sp >>= 1; 223 } 224 225 switch (sp & mask) { 226#undef getval 227#define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b) 228 getval(B,0); 229 getval(B,50); 230 getval(B,75); 231 getval(B,110); 232 getval(B,134); 233 getval(B,150); 234 getval(B,200); 235 getval(B,300); 236 getval(B,600); 237 getval(B,1200); 238 getval(B,1800); 239 getval(B,2400); 240 getval(B,4800); 241 getval(B,9600); 242 getval(B,19200); 243 getval(B,38400); 244 getval(B,57600); 245 getval(B,115200); 246 default: return B9600; /* XXX */ 247 } 248} 249 250 251static void 252svr4_32_to_bsd_termios(const struct svr4_32_termios *st, struct termios *bt, int new) 253{ 254 /* control characters */ 255 /* 256 * We process VMIN and VTIME first, 257 * because they are shared with VEOF and VEOL 258 */ 259 svr4_to_bsd_char(V,MIN); 260 svr4_to_bsd_char(V,TIME); 261 262 svr4_to_bsd_char(V,INTR); 263 svr4_to_bsd_char(V,QUIT); 264 svr4_to_bsd_char(V,ERASE); 265 svr4_to_bsd_char(V,KILL); 266 svr4_to_bsd_char(V,EOF); 267 svr4_to_bsd_char(V,EOL); 268 svr4_to_bsd_char(V,EOL2); 269 undefined_char(V,SWTCH); 270 svr4_to_bsd_char(V,START); 271 svr4_to_bsd_char(V,STOP); 272 svr4_to_bsd_char(V,SUSP); 273 svr4_to_bsd_char(V,DSUSP); 274 svr4_to_bsd_char(V,REPRINT); 275 svr4_to_bsd_char(V,DISCARD); 276 svr4_to_bsd_char(V,WERASE); 277 svr4_to_bsd_char(V,LNEXT); 278 279 /* Input modes */ 280 svr4_to_bsd_flag1(c_iflag,I,GNBRK); 281 svr4_to_bsd_flag1(c_iflag,B,RKINT); 282 svr4_to_bsd_flag1(c_iflag,I,GNPAR); 283 svr4_to_bsd_flag1(c_iflag,P,ARMRK); 284 svr4_to_bsd_flag1(c_iflag,I,NPCK); 285 svr4_to_bsd_flag1(c_iflag,I,STRIP); 286 svr4_to_bsd_flag1(c_iflag,I,NLCR); 287 svr4_to_bsd_flag1(c_iflag,I,GNCR); 288 svr4_to_bsd_flag1(c_iflag,I,CRNL); 289 undefined_flag1(c_iflag,I,UCLC); 290 svr4_to_bsd_flag1(c_iflag,I,XON); 291 svr4_to_bsd_flag1(c_iflag,I,XANY); 292 svr4_to_bsd_flag1(c_iflag,I,XOFF); 293 svr4_to_bsd_flag1(c_iflag,I,MAXBEL); 294 undefined_flag1(c_iflag,D,OSMODE); 295 296 /* Output modes */ 297 svr4_to_bsd_flag1(c_oflag,O,POST); 298 undefined_flag1(c_oflag,O,LCUC); 299 svr4_to_bsd_flag1(c_oflag,O,NLCR); 300 undefined_flag1(c_oflag,O,CRNL); 301 undefined_flag1(c_oflag,O,NOCR); 302 undefined_flag1(c_oflag,O,NLRET); 303 undefined_flag1(c_oflag,O,FILL); 304 undefined_flag1(c_oflag,O,FDEL); 305 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); 306 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); 307 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); 308 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); 309 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); 310 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); 311 undefined_flag1(c_oflag,P,AGEOUT); 312 undefined_flag1(c_oflag,W,RAP); 313 314 /* Control modes */ 315 bt->c_ospeed = svr4_32_to_bsd_speed(st->c_cflag, SVR4_CBAUD); 316 svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) 317 svr4_to_bsd_flag1(c_cflag,C,STOPB); 318 svr4_to_bsd_flag1(c_cflag,C,READ); 319 svr4_to_bsd_flag1(c_cflag,P,ARENB); 320 svr4_to_bsd_flag1(c_cflag,P,ARODD); 321 svr4_to_bsd_flag1(c_cflag,H,UPCL); 322 svr4_to_bsd_flag1(c_cflag,C,LOCAL); 323 undefined_flag1(c_cflag,R,CV1EN); 324 undefined_flag1(c_cflag,X,MT1EN); 325 undefined_flag1(c_cflag,L,OBLK); 326 undefined_flag1(c_cflag,X,CLUDE); 327 bt->c_ispeed = svr4_32_to_bsd_speed(st->c_cflag, SVR4_CIBAUD); 328 undefined_flag1(c_cflag,P,AREXT); 329 330 /* line discipline modes */ 331 svr4_to_bsd_flag1(c_lflag,I,SIG); 332 svr4_to_bsd_flag1(c_lflag,I,CANON); 333 undefined_flag1(c_lflag,X,CASE); 334 svr4_to_bsd_flag1(c_lflag,E,CHO); 335 svr4_to_bsd_flag1(c_lflag,E,CHOE); 336 svr4_to_bsd_flag1(c_lflag,E,CHOK); 337 svr4_to_bsd_flag1(c_lflag,E,CHONL); 338 svr4_to_bsd_flag1(c_lflag,N,OFLSH); 339 svr4_to_bsd_flag1(c_lflag,T,OSTOP); 340 svr4_to_bsd_flag1(c_lflag,E,CHOCTL); 341 svr4_to_bsd_flag1(c_lflag,E,CHOPRT); 342 svr4_to_bsd_flag1(c_lflag,E,CHOKE); 343 undefined_flag1(c_lflag,D,EFECHO); 344 svr4_to_bsd_flag1(c_lflag,F,LUSHO); 345 svr4_to_bsd_flag1(c_lflag,P,ENDIN); 346 svr4_to_bsd_flag1(c_lflag,I,EXTEN); 347} 348 349 350static void 351bsd_to_svr4_32_termios(const struct termios *bt, struct svr4_32_termios *st) 352{ 353 /* control characters */ 354 /* 355 * We process VMIN and VTIME first, 356 * because they are shared with VEOF and VEOL 357 */ 358 bsd_to_svr4_char(V,MIN); 359 bsd_to_svr4_char(V,TIME); 360 bsd_to_svr4_char(V,INTR); 361 bsd_to_svr4_char(V,QUIT); 362 bsd_to_svr4_char(V,ERASE); 363 bsd_to_svr4_char(V,KILL); 364 bsd_to_svr4_char(V,EOF); 365 bsd_to_svr4_char(V,EOL); 366 bsd_to_svr4_char(V,EOL2); 367 undefined_char(V,SWTCH); 368 bsd_to_svr4_char(V,START); 369 bsd_to_svr4_char(V,STOP); 370 bsd_to_svr4_char(V,SUSP); 371 bsd_to_svr4_char(V,DSUSP); 372 bsd_to_svr4_char(V,REPRINT); 373 bsd_to_svr4_char(V,DISCARD); 374 bsd_to_svr4_char(V,WERASE); 375 bsd_to_svr4_char(V,LNEXT); 376 377 /* Input modes */ 378 bsd_to_svr4_flag1(c_iflag,I,GNBRK); 379 bsd_to_svr4_flag1(c_iflag,B,RKINT); 380 bsd_to_svr4_flag1(c_iflag,I,GNPAR); 381 bsd_to_svr4_flag1(c_iflag,P,ARMRK); 382 bsd_to_svr4_flag1(c_iflag,I,NPCK); 383 bsd_to_svr4_flag1(c_iflag,I,STRIP); 384 bsd_to_svr4_flag1(c_iflag,I,NLCR); 385 bsd_to_svr4_flag1(c_iflag,I,GNCR); 386 bsd_to_svr4_flag1(c_iflag,I,CRNL); 387 undefined_flag1(c_iflag,I,UCLC); 388 bsd_to_svr4_flag1(c_iflag,I,XON); 389 bsd_to_svr4_flag1(c_iflag,I,XANY); 390 bsd_to_svr4_flag1(c_iflag,I,XOFF); 391 bsd_to_svr4_flag1(c_iflag,I,MAXBEL); 392 undefined_flag1(c_iflag,D,OSMODE); 393 394 /* Output modes */ 395 bsd_to_svr4_flag1(c_oflag,O,POST); 396 undefined_flag1(c_oflag,O,LCUC); 397 bsd_to_svr4_flag1(c_oflag,O,NLCR); 398 undefined_flag1(c_oflag,O,CRNL); 399 undefined_flag1(c_oflag,O,NOCR); 400 undefined_flag1(c_oflag,O,NLRET); 401 undefined_flag1(c_oflag,O,FILL); 402 undefined_flag1(c_oflag,O,FDEL); 403 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); 404 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); 405 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); 406 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); 407 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); 408 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); 409 undefined_flag1(c_oflag,P,AGEOUT); 410 undefined_flag1(c_oflag,W,RAP); 411 412 /* Control modes */ 413 st->c_cflag &= ~SVR4_CBAUD; 414 st->c_cflag |= bsd_to_svr4_32_speed(bt->c_ospeed, SVR4_CBAUD); 415 bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) 416 bsd_to_svr4_flag1(c_cflag,C,STOPB); 417 bsd_to_svr4_flag1(c_cflag,C,READ); 418 bsd_to_svr4_flag1(c_cflag,P,ARENB); 419 bsd_to_svr4_flag1(c_cflag,P,ARODD); 420 bsd_to_svr4_flag1(c_cflag,H,UPCL); 421 bsd_to_svr4_flag1(c_cflag,C,LOCAL); 422 undefined_flag1(c_cflag,R,CV1EN); 423 undefined_flag1(c_cflag,X,MT1EN); 424 undefined_flag1(c_cflag,L,OBLK); 425 undefined_flag1(c_cflag,X,CLUDE); 426 st->c_cflag &= ~SVR4_CIBAUD; 427 st->c_cflag |= bsd_to_svr4_32_speed(bt->c_ispeed, SVR4_CIBAUD); 428 429 undefined_flag1(c_oflag,P,AREXT); 430 431 /* line discipline modes */ 432 bsd_to_svr4_flag1(c_lflag,I,SIG); 433 bsd_to_svr4_flag1(c_lflag,I,CANON); 434 undefined_flag1(c_lflag,X,CASE); 435 bsd_to_svr4_flag1(c_lflag,E,CHO); 436 bsd_to_svr4_flag1(c_lflag,E,CHOE); 437 bsd_to_svr4_flag1(c_lflag,E,CHOK); 438 bsd_to_svr4_flag1(c_lflag,E,CHONL); 439 bsd_to_svr4_flag1(c_lflag,N,OFLSH); 440 bsd_to_svr4_flag1(c_lflag,T,OSTOP); 441 bsd_to_svr4_flag1(c_lflag,E,CHOCTL); 442 bsd_to_svr4_flag1(c_lflag,E,CHOPRT); 443 bsd_to_svr4_flag1(c_lflag,E,CHOKE); 444 undefined_flag1(c_lflag,D,EFECHO); 445 bsd_to_svr4_flag1(c_lflag,F,LUSHO); 446 bsd_to_svr4_flag1(c_lflag,P,ENDIN); 447 bsd_to_svr4_flag1(c_lflag,I,EXTEN); 448} 449 450 451static void 452svr4_termio_to_termios(const struct svr4_termio *t, struct svr4_32_termios *ts) 453{ 454 int i; 455 456 ts->c_iflag = (svr4_32_tcflag_t) t->c_iflag; 457 ts->c_oflag = (svr4_32_tcflag_t) t->c_oflag; 458 ts->c_cflag = (svr4_32_tcflag_t) t->c_cflag; 459 ts->c_lflag = (svr4_32_tcflag_t) t->c_lflag; 460 461 for (i = 0; i < SVR4_NCC; i++) 462 ts->c_cc[i] = (svr4_cc_t) t->c_cc[i]; 463} 464 465 466static void 467svr4_32_termios_to_termio(const struct svr4_32_termios *ts, struct svr4_termio *t) 468{ 469 int i; 470 471 t->c_iflag = (u_short) ts->c_iflag; 472 t->c_oflag = (u_short) ts->c_oflag; 473 t->c_cflag = (u_short) ts->c_cflag; 474 t->c_lflag = (u_short) ts->c_lflag; 475 t->c_line = 0; /* XXX */ 476 477 for (i = 0; i < SVR4_NCC; i++) 478 t->c_cc[i] = (u_char) ts->c_cc[i]; 479} 480 481int 482svr4_32_term_ioctl(struct file *fp, struct lwp *l, register_t *retval, int fd, u_long cmd, void *data) 483{ 484 struct termios bt; 485 struct svr4_32_termios st; 486 struct svr4_termio t; 487 int error, new; 488 int (*ctl)(file_t *, u_long, void *) = fp->f_ops->fo_ioctl; 489 490 *retval = 0; 491 492 switch (cmd) { 493 case SVR4_TCGETA: 494 case SVR4_TCGETS: 495 if ((error = (*ctl)(fp, TIOCGETA, &bt)) != 0) 496 return error; 497 498 memset(&st, 0, sizeof(st)); 499 bsd_to_svr4_32_termios(&bt, &st); 500 501 DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S')); 502#ifdef DEBUG_SVR4 503 print_bsd_termios(&bt); 504 print_svr4_32_termios(&st); 505#endif /* DEBUG_SVR4 */ 506 507 if (cmd == SVR4_TCGETA) { 508 svr4_32_termios_to_termio(&st, &t); 509 return copyout(&t, data, sizeof(t)); 510 } 511 else { 512 return copyout(&st, data, sizeof(st)); 513 } 514 515 case SVR4_TCSETA: 516 case SVR4_TCSETS: 517 case SVR4_TCSETAW: 518 case SVR4_TCSETSW: 519 case SVR4_TCSETAF: 520 case SVR4_TCSETSF: 521 /* get full BSD termios so we don't lose information */ 522 if ((error = (*ctl)(fp, TIOCGETA, &bt)) != 0) 523 return error; 524 525 switch (cmd) { 526 case SVR4_TCSETS: 527 case SVR4_TCSETSW: 528 case SVR4_TCSETSF: 529 if ((error = copyin(data, &st, sizeof(st))) != 0) 530 return error; 531 new = 1; 532 break; 533 534 case SVR4_TCSETA: 535 case SVR4_TCSETAW: 536 case SVR4_TCSETAF: 537 if ((error = copyin(data, &t, sizeof(t))) != 0) 538 return error; 539 540 svr4_termio_to_termios(&t, &st); 541 new = 0; 542 break; 543 544 default: 545 return EINVAL; 546 } 547 548 svr4_32_to_bsd_termios(&st, &bt, new); 549 550 switch (cmd) { 551 case SVR4_TCSETA: 552 case SVR4_TCSETS: 553 DPRINTF(("ioctl(TCSET[A|S]);\n")); 554 cmd = TIOCSETA; 555 break; 556 case SVR4_TCSETAW: 557 case SVR4_TCSETSW: 558 DPRINTF(("ioctl(TCSET[A|S]W);\n")); 559 cmd = TIOCSETAW; 560 break; 561 case SVR4_TCSETAF: 562 case SVR4_TCSETSF: 563 DPRINTF(("ioctl(TCSET[A|S]F);\n")); 564 cmd = TIOCSETAF; 565 break; 566 } 567 568#ifdef DEBUG_SVR4 569 print_bsd_termios(&bt); 570 print_svr4_32_termios(&st); 571#endif /* DEBUG_SVR4 */ 572 573 return (*ctl)(fp, cmd, &bt); 574 575 case SVR4_TIOCGWINSZ: 576 { 577 struct svr4_winsize ws; 578 579 error = (*ctl)(fp, TIOCGWINSZ, &ws); 580 if (error) 581 return error; 582 return copyout(&ws, data, sizeof(ws)); 583 } 584 585 case SVR4_TIOCSWINSZ: 586 { 587 struct svr4_winsize ws; 588 589 if ((error = copyin(data, &ws, sizeof(ws))) != 0) 590 return error; 591 return (*ctl)(fp, TIOCSWINSZ, &ws); 592 } 593 594 default: 595 return svr4_32_stream_ti_ioctl(fp, l, retval, fd, cmd, data); 596 } 597} 598