1/*- 2 * Copyright (c) 1998 Mark Newton 3 * Copyright (c) 1994 Christos Zoulas 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 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 16 * 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. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/proc.h> 34#include <sys/systm.h> 35#include <sys/file.h> 36#include <sys/filedesc.h> 37#include <sys/tty.h> 38 39#include <sys/sysproto.h> 40 41#include <compat/svr4/svr4.h> 42#include <compat/svr4/svr4_util.h> 43#include <compat/svr4/svr4_ioctl.h> 44#include <compat/svr4/svr4_termios.h> 45 46#ifndef __CONCAT3 47# if __STDC__ 48# define __CONCAT3(a,b,c) a ## b ## c 49# else 50# define __CONCAT3(a,b,c) a/**/b/**/c 51# endif 52#endif 53 54static u_long bsd_to_svr4_speed(u_long, u_long); 55static u_long svr4_to_bsd_speed(u_long, u_long); 56static void svr4_to_bsd_termios(const struct svr4_termios *, 57 struct termios *, int); 58static void bsd_to_svr4_termios(const struct termios *, 59 struct svr4_termios *); 60static void svr4_termio_to_termios(const struct svr4_termio *, 61 struct svr4_termios *); 62static void svr4_termios_to_termio(const struct svr4_termios *, 63 struct svr4_termio *); 64#ifdef DEBUG_SVR4 65static void print_svr4_termios(const struct svr4_termios *); 66static void print_bsd_termios(const struct termios *); 67#endif /* DEBUG_SVR4 */ 68 69#define undefined_char(a,b) /**/ 70#define undefined_flag1(f,a,b) /**/ 71#define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/ 72#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/ 73 74#define svr4_to_bsd_char(a,b) \ 75 if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \ 76 if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \ 77 bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \ 78 else \ 79 bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \ 80 } 81 82#define svr4_to_bsd_flag1(f,a,b) \ 83 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 84 if (st->f & __CONCAT3(SVR4_,a,b)) \ 85 bt->f |= __CONCAT(a,b); \ 86 else \ 87 bt->f &= ~__CONCAT(a,b); \ 88 } 89 90#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \ 91 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 92 bt->f &= ~__CONCAT(a,b); \ 93 switch (st->f & __CONCAT3(SVR4_,a,b)) { \ 94 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ 95 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ 96 } \ 97 } 98 99#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ 100 if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ 101 bt->f &= ~__CONCAT(a,b); \ 102 switch (st->f & __CONCAT3(SVR4_,a,b)) { \ 103 case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ 104 case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ 105 case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \ 106 case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \ 107 } \ 108 } 109 110 111#define bsd_to_svr4_char(a,b) \ 112 if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \ 113 st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \ 114 else \ 115 st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)] 116 117#define bsd_to_svr4_flag1(f,a,b) \ 118 if (bt->f & __CONCAT(a,b)) \ 119 st->f |= __CONCAT3(SVR4_,a,b); \ 120 else \ 121 st->f &= ~__CONCAT3(SVR4_,a,b) 122 123#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \ 124 st->f &= ~__CONCAT(a,b); \ 125 switch (bt->f & __CONCAT(a,b)) { \ 126 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ 127 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ 128 } 129 130#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ 131 st->f &= ~__CONCAT(a,b); \ 132 switch (bt->f & __CONCAT(a,b)) { \ 133 case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ 134 case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ 135 case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \ 136 case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \ 137 } 138 139#ifdef DEBUG_SVR4 140static void 141print_svr4_termios(st) 142 const struct svr4_termios *st; 143{ 144 int i; 145 DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n", 146 st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag)); 147 DPRINTF(("cc: ")); 148 for (i = 0; i < SVR4_NCCS; i++) 149 DPRINTF(("%o ", st->c_cc[i])); 150 DPRINTF(("\n")); 151} 152 153 154static void 155print_bsd_termios(bt) 156 const struct termios *bt; 157{ 158 int i; 159 uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n", 160 bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag); 161 uprintf("cc: "); 162 for (i = 0; i < NCCS; i++) 163 uprintf("%o ", bt->c_cc[i]); 164 uprintf("\n"); 165} 166#endif /* DEBUG_SVR4 */ 167 168static u_long 169bsd_to_svr4_speed(sp, mask) 170 u_long sp; 171 u_long mask; 172{ 173 switch (sp) { 174#undef getval 175#define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b) 176 getval(B,0); 177 getval(B,50); 178 getval(B,75); 179 getval(B,110); 180 getval(B,134); 181 getval(B,150); 182 getval(B,200); 183 getval(B,300); 184 getval(B,600); 185 getval(B,1200); 186 getval(B,1800); 187 getval(B,2400); 188 getval(B,4800); 189 getval(B,9600); 190 getval(B,19200); 191 getval(B,38400); 192 getval(B,57600); 193 getval(B,115200); 194 default: sp = SVR4_B9600; /* XXX */ 195 } 196 197 while ((mask & 1) == 0) { 198 mask >>= 1; 199 sp <<= 1; 200 } 201 202 return sp; 203} 204 205 206static u_long 207svr4_to_bsd_speed(sp, mask) 208 u_long sp; 209 u_long mask; 210{ 211 while ((mask & 1) == 0) { 212 mask >>= 1; 213 sp >>= 1; 214 } 215 216 switch (sp & mask) { 217#undef getval 218#define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b) 219 getval(B,0); 220 getval(B,50); 221 getval(B,75); 222 getval(B,110); 223 getval(B,134); 224 getval(B,150); 225 getval(B,200); 226 getval(B,300); 227 getval(B,600); 228 getval(B,1200); 229 getval(B,1800); 230 getval(B,2400); 231 getval(B,4800); 232 getval(B,9600); 233 getval(B,19200); 234 getval(B,38400); 235 getval(B,57600); 236 getval(B,115200); 237 default: return B9600; /* XXX */ 238 } 239} 240 241 242static void 243svr4_to_bsd_termios(st, bt, new) 244 const struct svr4_termios *st; 245 struct termios *bt; 246 int new; 247{ 248 /* control characters */ 249 /* 250 * We process VMIN and VTIME first, 251 * because they are shared with VEOF and VEOL 252 */ 253 svr4_to_bsd_char(V,MIN); 254 svr4_to_bsd_char(V,TIME); 255 256 svr4_to_bsd_char(V,INTR); 257 svr4_to_bsd_char(V,QUIT); 258 svr4_to_bsd_char(V,ERASE); 259 svr4_to_bsd_char(V,KILL); 260 svr4_to_bsd_char(V,EOF); 261 svr4_to_bsd_char(V,EOL); 262 svr4_to_bsd_char(V,EOL2); 263 undefined_char(V,SWTCH); 264 svr4_to_bsd_char(V,START); 265 svr4_to_bsd_char(V,STOP); 266 svr4_to_bsd_char(V,SUSP); 267 svr4_to_bsd_char(V,DSUSP); 268 svr4_to_bsd_char(V,REPRINT); 269 svr4_to_bsd_char(V,DISCARD); 270 svr4_to_bsd_char(V,WERASE); 271 svr4_to_bsd_char(V,LNEXT); 272 273 /* Input modes */ 274 svr4_to_bsd_flag1(c_iflag,I,GNBRK); 275 svr4_to_bsd_flag1(c_iflag,B,RKINT); 276 svr4_to_bsd_flag1(c_iflag,I,GNPAR); 277 svr4_to_bsd_flag1(c_iflag,P,ARMRK); 278 svr4_to_bsd_flag1(c_iflag,I,NPCK); 279 svr4_to_bsd_flag1(c_iflag,I,STRIP); 280 svr4_to_bsd_flag1(c_iflag,I,NLCR); 281 svr4_to_bsd_flag1(c_iflag,I,GNCR); 282 svr4_to_bsd_flag1(c_iflag,I,CRNL); 283 undefined_flag1(c_iflag,I,UCLC); 284 svr4_to_bsd_flag1(c_iflag,I,XON); 285 svr4_to_bsd_flag1(c_iflag,I,XANY); 286 svr4_to_bsd_flag1(c_iflag,I,XOFF); 287 svr4_to_bsd_flag1(c_iflag,I,MAXBEL); 288 undefined_flag1(c_iflag,D,OSMODE); 289 290 /* Output modes */ 291 svr4_to_bsd_flag1(c_oflag,O,POST); 292 undefined_flag1(c_oflag,O,LCUC); 293 svr4_to_bsd_flag1(c_oflag,O,NLCR); 294 undefined_flag1(c_oflag,O,CRNL); 295 undefined_flag1(c_oflag,O,NOCR); 296 undefined_flag1(c_oflag,O,NLRET); 297 undefined_flag1(c_oflag,O,FILL); 298 undefined_flag1(c_oflag,O,FDEL); 299 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); 300 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); 301 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); 302 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); 303 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); 304 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); 305 undefined_flag1(c_oflag,P,AGEOUT); 306 undefined_flag1(c_oflag,W,RAP); 307 308 /* Control modes */ 309 bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD); 310 svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) 311 svr4_to_bsd_flag1(c_cflag,C,STOPB); 312 svr4_to_bsd_flag1(c_cflag,C,READ); 313 svr4_to_bsd_flag1(c_cflag,P,ARENB); 314 svr4_to_bsd_flag1(c_cflag,P,ARODD); 315 svr4_to_bsd_flag1(c_cflag,H,UPCL); 316 svr4_to_bsd_flag1(c_cflag,C,LOCAL); 317 undefined_flag1(c_cflag,R,CV1EN); 318 undefined_flag1(c_cflag,X,MT1EN); 319 undefined_flag1(c_cflag,L,OBLK); 320 undefined_flag1(c_cflag,X,CLUDE); 321 bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD); 322 undefined_flag1(c_cflag,P,AREXT); 323 324 /* line discipline modes */ 325 svr4_to_bsd_flag1(c_lflag,I,SIG); 326 svr4_to_bsd_flag1(c_lflag,I,CANON); 327 undefined_flag1(c_lflag,X,CASE); 328 svr4_to_bsd_flag1(c_lflag,E,CHO); 329 svr4_to_bsd_flag1(c_lflag,E,CHOE); 330 svr4_to_bsd_flag1(c_lflag,E,CHOK); 331 svr4_to_bsd_flag1(c_lflag,E,CHONL); 332 svr4_to_bsd_flag1(c_lflag,N,OFLSH); 333 svr4_to_bsd_flag1(c_lflag,T,OSTOP); 334 svr4_to_bsd_flag1(c_lflag,E,CHOCTL); 335 svr4_to_bsd_flag1(c_lflag,E,CHOPRT); 336 svr4_to_bsd_flag1(c_lflag,E,CHOKE); 337 undefined_flag1(c_lflag,D,EFECHO); 338 svr4_to_bsd_flag1(c_lflag,F,LUSHO); 339 svr4_to_bsd_flag1(c_lflag,P,ENDIN); 340 svr4_to_bsd_flag1(c_lflag,I,EXTEN); 341} 342 343 344static void 345bsd_to_svr4_termios(bt, st) 346 const struct termios *bt; 347 struct svr4_termios *st; 348{ 349 /* control characters */ 350 /* 351 * We process VMIN and VTIME first, 352 * because they are shared with VEOF and VEOL 353 */ 354 bsd_to_svr4_char(V,MIN); 355 bsd_to_svr4_char(V,TIME); 356 bsd_to_svr4_char(V,INTR); 357 bsd_to_svr4_char(V,QUIT); 358 bsd_to_svr4_char(V,ERASE); 359 bsd_to_svr4_char(V,KILL); 360 bsd_to_svr4_char(V,EOF); 361 bsd_to_svr4_char(V,EOL); 362 bsd_to_svr4_char(V,EOL2); 363 undefined_char(V,SWTCH); 364 bsd_to_svr4_char(V,START); 365 bsd_to_svr4_char(V,STOP); 366 bsd_to_svr4_char(V,SUSP); 367 bsd_to_svr4_char(V,DSUSP); 368 bsd_to_svr4_char(V,REPRINT); 369 bsd_to_svr4_char(V,DISCARD); 370 bsd_to_svr4_char(V,WERASE); 371 bsd_to_svr4_char(V,LNEXT); 372 373 /* Input modes */ 374 bsd_to_svr4_flag1(c_iflag,I,GNBRK); 375 bsd_to_svr4_flag1(c_iflag,B,RKINT); 376 bsd_to_svr4_flag1(c_iflag,I,GNPAR); 377 bsd_to_svr4_flag1(c_iflag,P,ARMRK); 378 bsd_to_svr4_flag1(c_iflag,I,NPCK); 379 bsd_to_svr4_flag1(c_iflag,I,STRIP); 380 bsd_to_svr4_flag1(c_iflag,I,NLCR); 381 bsd_to_svr4_flag1(c_iflag,I,GNCR); 382 bsd_to_svr4_flag1(c_iflag,I,CRNL); 383 undefined_flag1(c_iflag,I,UCLC); 384 bsd_to_svr4_flag1(c_iflag,I,XON); 385 bsd_to_svr4_flag1(c_iflag,I,XANY); 386 bsd_to_svr4_flag1(c_iflag,I,XOFF); 387 bsd_to_svr4_flag1(c_iflag,I,MAXBEL); 388 undefined_flag1(c_iflag,D,OSMODE); 389 390 /* Output modes */ 391 bsd_to_svr4_flag1(c_oflag,O,POST); 392 undefined_flag1(c_oflag,O,LCUC); 393 bsd_to_svr4_flag1(c_oflag,O,NLCR); 394 undefined_flag1(c_oflag,O,CRNL); 395 undefined_flag1(c_oflag,O,NOCR); 396 undefined_flag1(c_oflag,O,NLRET); 397 undefined_flag1(c_oflag,O,FILL); 398 undefined_flag1(c_oflag,O,FDEL); 399 undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); 400 undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); 401 undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); 402 undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); 403 undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); 404 undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); 405 undefined_flag1(c_oflag,P,AGEOUT); 406 undefined_flag1(c_oflag,W,RAP); 407 408 /* Control modes */ 409 st->c_cflag &= ~SVR4_CBAUD; 410 st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD); 411 bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) 412 bsd_to_svr4_flag1(c_cflag,C,STOPB); 413 bsd_to_svr4_flag1(c_cflag,C,READ); 414 bsd_to_svr4_flag1(c_cflag,P,ARENB); 415 bsd_to_svr4_flag1(c_cflag,P,ARODD); 416 bsd_to_svr4_flag1(c_cflag,H,UPCL); 417 bsd_to_svr4_flag1(c_cflag,C,LOCAL); 418 undefined_flag1(c_cflag,R,CV1EN); 419 undefined_flag1(c_cflag,X,MT1EN); 420 undefined_flag1(c_cflag,L,OBLK); 421 undefined_flag1(c_cflag,X,CLUDE); 422 st->c_cflag &= ~SVR4_CIBAUD; 423 st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD); 424 425 undefined_flag1(c_oflag,P,AREXT); 426 427 /* line discipline modes */ 428 bsd_to_svr4_flag1(c_lflag,I,SIG); 429 bsd_to_svr4_flag1(c_lflag,I,CANON); 430 undefined_flag1(c_lflag,X,CASE); 431 bsd_to_svr4_flag1(c_lflag,E,CHO); 432 bsd_to_svr4_flag1(c_lflag,E,CHOE); 433 bsd_to_svr4_flag1(c_lflag,E,CHOK); 434 bsd_to_svr4_flag1(c_lflag,E,CHONL); 435 bsd_to_svr4_flag1(c_lflag,N,OFLSH); 436 bsd_to_svr4_flag1(c_lflag,T,OSTOP); 437 bsd_to_svr4_flag1(c_lflag,E,CHOCTL); 438 bsd_to_svr4_flag1(c_lflag,E,CHOPRT); 439 bsd_to_svr4_flag1(c_lflag,E,CHOKE); 440 undefined_flag1(c_lflag,D,EFECHO); 441 bsd_to_svr4_flag1(c_lflag,F,LUSHO); 442 bsd_to_svr4_flag1(c_lflag,P,ENDIN); 443 bsd_to_svr4_flag1(c_lflag,I,EXTEN); 444} 445 446 447static void 448svr4_termio_to_termios(t, ts) 449 const struct svr4_termio *t; 450 struct svr4_termios *ts; 451{ 452 int i; 453 454 ts->c_iflag = (svr4_tcflag_t) t->c_iflag; 455 ts->c_oflag = (svr4_tcflag_t) t->c_oflag; 456 ts->c_cflag = (svr4_tcflag_t) t->c_cflag; 457 ts->c_lflag = (svr4_tcflag_t) t->c_lflag; 458 459 for (i = 0; i < SVR4_NCC; i++) 460 ts->c_cc[i] = (svr4_cc_t) t->c_cc[i]; 461} 462 463 464static void 465svr4_termios_to_termio(ts, t) 466 const struct svr4_termios *ts; 467 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_term_ioctl(fp, td, retval, fd, cmd, data) 483 struct file *fp; 484 struct thread *td; 485 register_t *retval; 486 int fd; 487 u_long cmd; 488 caddr_t data; 489{ 490 struct termios bt; 491 struct svr4_termios st; 492 struct svr4_termio t; 493 int error, new; 494 495 *retval = 0; 496 497 DPRINTF(("TERM ioctl %lx\n", cmd)); 498 499 switch (cmd) { 500 case SVR4_TCGETA: 501 case SVR4_TCGETS: 502 DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S')); 503 if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, 504 td->td_ucred, td)) != 0) 505 return error; 506 507 memset(&st, 0, sizeof(st)); 508 bsd_to_svr4_termios(&bt, &st); 509 510#ifdef DEBUG_SVR4 511 print_bsd_termios(&bt); 512 print_svr4_termios(&st); 513#endif /* DEBUG_SVR4 */ 514 515 if (cmd == SVR4_TCGETA) { 516 svr4_termios_to_termio(&st, &t); 517 return copyout(&t, data, sizeof(t)); 518 } 519 else { 520 return copyout(&st, data, sizeof(st)); 521 } 522 523 case SVR4_TCSETA: 524 case SVR4_TCSETS: 525 case SVR4_TCSETAW: 526 case SVR4_TCSETSW: 527 case SVR4_TCSETAF: 528 case SVR4_TCSETSF: 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, 532 td->td_ucred, td)) != 0) 533 return error; 534 535 switch (cmd) { 536 case SVR4_TCSETS: 537 case SVR4_TCSETSW: 538 case SVR4_TCSETSF: 539 if ((error = copyin(data, &st, sizeof(st))) != 0) 540 return error; 541 new = 1; 542 break; 543 544 case SVR4_TCSETA: 545 case SVR4_TCSETAW: 546 case SVR4_TCSETAF: 547 if ((error = copyin(data, &t, sizeof(t))) != 0) 548 return error; 549 550 svr4_termio_to_termios(&t, &st); 551 new = 0; 552 break; 553 554 default: 555 return EINVAL; 556 } 557 558 svr4_to_bsd_termios(&st, &bt, new); 559 560 switch (cmd) { 561 case SVR4_TCSETA: 562 case SVR4_TCSETS: 563 DPRINTF(("ioctl(TCSET[A|S]);\n")); 564 cmd = TIOCSETA; 565 break; 566 case SVR4_TCSETAW: 567 case SVR4_TCSETSW: 568 DPRINTF(("ioctl(TCSET[A|S]W);\n")); 569 cmd = TIOCSETAW; 570 break; 571 case SVR4_TCSETAF: 572 case SVR4_TCSETSF: 573 DPRINTF(("ioctl(TCSET[A|S]F);\n")); 574 cmd = TIOCSETAF; 575 break; 576 } 577 578#ifdef DEBUG_SVR4 579 print_bsd_termios(&bt); 580 print_svr4_termios(&st); 581#endif /* DEBUG_SVR4 */ 582 583 return fo_ioctl(fp, cmd, (caddr_t) &bt, td->td_ucred, td); 584 585 case SVR4_TIOCGWINSZ: 586 DPRINTF(("TIOCGWINSZ\n")); 587 { 588 struct svr4_winsize ws; 589 590 error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, 591 td->td_ucred, td); 592 if (error) 593 return error; 594 return copyout(&ws, data, sizeof(ws)); 595 } 596 597 case SVR4_TIOCSWINSZ: 598 DPRINTF(("TIOCSWINSZ\n")); 599 { 600 struct svr4_winsize ws; 601 602 if ((error = copyin(data, &ws, sizeof(ws))) != 0) 603 return error; 604 return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, 605 td->td_ucred, td); 606 } 607 608 default: 609 DPRINTF(("teleport to STREAMS ioctls...\n")); 610 return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data); 611 } 612} 613