Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.25-rc1 980 lines 26 kB view raw
1/* 2 * linux/drivers/char/tty_ioctl.c 3 * 4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 5 * 6 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines 7 * which can be dynamically activated and de-activated by the line 8 * discipline handling modules (like SLIP). 9 */ 10 11#include <linux/types.h> 12#include <linux/termios.h> 13#include <linux/errno.h> 14#include <linux/sched.h> 15#include <linux/kernel.h> 16#include <linux/major.h> 17#include <linux/tty.h> 18#include <linux/fcntl.h> 19#include <linux/string.h> 20#include <linux/mm.h> 21#include <linux/module.h> 22#include <linux/bitops.h> 23#include <linux/mutex.h> 24 25#include <asm/io.h> 26#include <asm/uaccess.h> 27#include <asm/system.h> 28 29#undef TTY_DEBUG_WAIT_UNTIL_SENT 30 31#undef DEBUG 32 33/* 34 * Internal flag options for termios setting behavior 35 */ 36#define TERMIOS_FLUSH 1 37#define TERMIOS_WAIT 2 38#define TERMIOS_TERMIO 4 39#define TERMIOS_OLD 8 40 41 42/** 43 * tty_wait_until_sent - wait for I/O to finish 44 * @tty: tty we are waiting for 45 * @timeout: how long we will wait 46 * 47 * Wait for characters pending in a tty driver to hit the wire, or 48 * for a timeout to occur (eg due to flow control) 49 * 50 * Locking: none 51 */ 52 53void tty_wait_until_sent(struct tty_struct *tty, long timeout) 54{ 55#ifdef TTY_DEBUG_WAIT_UNTIL_SENT 56 char buf[64]; 57 58 printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); 59#endif 60 if (!tty->driver->chars_in_buffer) 61 return; 62 if (!timeout) 63 timeout = MAX_SCHEDULE_TIMEOUT; 64 if (wait_event_interruptible_timeout(tty->write_wait, 65 !tty->driver->chars_in_buffer(tty), timeout) < 0) 66 return; 67 if (tty->driver->wait_until_sent) 68 tty->driver->wait_until_sent(tty, timeout); 69} 70EXPORT_SYMBOL(tty_wait_until_sent); 71 72static void unset_locked_termios(struct ktermios *termios, 73 struct ktermios *old, 74 struct ktermios *locked) 75{ 76 int i; 77 78#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z))) 79 80 if (!locked) { 81 printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n"); 82 return; 83 } 84 85 NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag); 86 NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag); 87 NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag); 88 NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag); 89 termios->c_line = locked->c_line ? old->c_line : termios->c_line; 90 for (i = 0; i < NCCS; i++) 91 termios->c_cc[i] = locked->c_cc[i] ? 92 old->c_cc[i] : termios->c_cc[i]; 93 /* FIXME: What should we do for i/ospeed */ 94} 95 96/* 97 * Routine which returns the baud rate of the tty 98 * 99 * Note that the baud_table needs to be kept in sync with the 100 * include/asm/termbits.h file. 101 */ 102static const speed_t baud_table[] = { 103 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 104 9600, 19200, 38400, 57600, 115200, 230400, 460800, 105#ifdef __sparc__ 106 76800, 153600, 307200, 614400, 921600 107#else 108 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 109 2500000, 3000000, 3500000, 4000000 110#endif 111}; 112 113#ifndef __sparc__ 114static const tcflag_t baud_bits[] = { 115 B0, B50, B75, B110, B134, B150, B200, B300, B600, 116 B1200, B1800, B2400, B4800, B9600, B19200, B38400, 117 B57600, B115200, B230400, B460800, B500000, B576000, 118 B921600, B1000000, B1152000, B1500000, B2000000, B2500000, 119 B3000000, B3500000, B4000000 120}; 121#else 122static const tcflag_t baud_bits[] = { 123 B0, B50, B75, B110, B134, B150, B200, B300, B600, 124 B1200, B1800, B2400, B4800, B9600, B19200, B38400, 125 B57600, B115200, B230400, B460800, B76800, B153600, 126 B307200, B614400, B921600 127}; 128#endif 129 130static int n_baud_table = ARRAY_SIZE(baud_table); 131 132/** 133 * tty_termios_baud_rate 134 * @termios: termios structure 135 * 136 * Convert termios baud rate data into a speed. This should be called 137 * with the termios lock held if this termios is a terminal termios 138 * structure. May change the termios data. Device drivers can call this 139 * function but should use ->c_[io]speed directly as they are updated. 140 * 141 * Locking: none 142 */ 143 144speed_t tty_termios_baud_rate(struct ktermios *termios) 145{ 146 unsigned int cbaud; 147 148 cbaud = termios->c_cflag & CBAUD; 149 150#ifdef BOTHER 151 /* Magic token for arbitary speed via c_ispeed/c_ospeed */ 152 if (cbaud == BOTHER) 153 return termios->c_ospeed; 154#endif 155 if (cbaud & CBAUDEX) { 156 cbaud &= ~CBAUDEX; 157 158 if (cbaud < 1 || cbaud + 15 > n_baud_table) 159 termios->c_cflag &= ~CBAUDEX; 160 else 161 cbaud += 15; 162 } 163 return baud_table[cbaud]; 164} 165EXPORT_SYMBOL(tty_termios_baud_rate); 166 167/** 168 * tty_termios_input_baud_rate 169 * @termios: termios structure 170 * 171 * Convert termios baud rate data into a speed. This should be called 172 * with the termios lock held if this termios is a terminal termios 173 * structure. May change the termios data. Device drivers can call this 174 * function but should use ->c_[io]speed directly as they are updated. 175 * 176 * Locking: none 177 */ 178 179speed_t tty_termios_input_baud_rate(struct ktermios *termios) 180{ 181#ifdef IBSHIFT 182 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD; 183 184 if (cbaud == B0) 185 return tty_termios_baud_rate(termios); 186 187 /* Magic token for arbitary speed via c_ispeed*/ 188 if (cbaud == BOTHER) 189 return termios->c_ispeed; 190 191 if (cbaud & CBAUDEX) { 192 cbaud &= ~CBAUDEX; 193 194 if (cbaud < 1 || cbaud + 15 > n_baud_table) 195 termios->c_cflag &= ~(CBAUDEX << IBSHIFT); 196 else 197 cbaud += 15; 198 } 199 return baud_table[cbaud]; 200#else 201 return tty_termios_baud_rate(termios); 202#endif 203} 204EXPORT_SYMBOL(tty_termios_input_baud_rate); 205 206/** 207 * tty_termios_encode_baud_rate 208 * @termios: ktermios structure holding user requested state 209 * @ispeed: input speed 210 * @ospeed: output speed 211 * 212 * Encode the speeds set into the passed termios structure. This is 213 * used as a library helper for drivers os that they can report back 214 * the actual speed selected when it differs from the speed requested 215 * 216 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour 217 * we need to carefully set the bits when the user does not get the 218 * desired speed. We allow small margins and preserve as much of possible 219 * of the input intent to keep compatiblity. 220 * 221 * Locking: Caller should hold termios lock. This is already held 222 * when calling this function from the driver termios handler. 223 * 224 * The ifdefs deal with platforms whose owners have yet to update them 225 * and will all go away once this is done. 226 */ 227 228void tty_termios_encode_baud_rate(struct ktermios *termios, 229 speed_t ibaud, speed_t obaud) 230{ 231 int i = 0; 232 int ifound = -1, ofound = -1; 233 int iclose = ibaud/50, oclose = obaud/50; 234 int ibinput = 0; 235 236 if (obaud == 0) /* CD dropped */ 237 ibaud = 0; /* Clear ibaud to be sure */ 238 239 termios->c_ispeed = ibaud; 240 termios->c_ospeed = obaud; 241 242#ifdef BOTHER 243 /* If the user asked for a precise weird speed give a precise weird 244 answer. If they asked for a Bfoo speed they many have problems 245 digesting non-exact replies so fuzz a bit */ 246 247 if ((termios->c_cflag & CBAUD) == BOTHER) 248 oclose = 0; 249 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) 250 iclose = 0; 251 if ((termios->c_cflag >> IBSHIFT) & CBAUD) 252 ibinput = 1; /* An input speed was specified */ 253#endif 254 termios->c_cflag &= ~CBAUD; 255 256 /* 257 * Our goal is to find a close match to the standard baud rate 258 * returned. Walk the baud rate table and if we get a very close 259 * match then report back the speed as a POSIX Bxxxx value by 260 * preference 261 */ 262 263 do { 264 if (obaud - oclose <= baud_table[i] && 265 obaud + oclose >= baud_table[i]) { 266 termios->c_cflag |= baud_bits[i]; 267 ofound = i; 268 } 269 if (ibaud - iclose <= baud_table[i] && 270 ibaud + iclose >= baud_table[i]) { 271 /* For the case input == output don't set IBAUD bits 272 if the user didn't do so */ 273 if (ofound == i && !ibinput) 274 ifound = i; 275#ifdef IBSHIFT 276 else { 277 ifound = i; 278 termios->c_cflag |= (baud_bits[i] << IBSHIFT); 279 } 280#endif 281 } 282 } while (++i < n_baud_table); 283 284 /* 285 * If we found no match then use BOTHER if provided or warn 286 * the user their platform maintainer needs to wake up if not. 287 */ 288#ifdef BOTHER 289 if (ofound == -1) 290 termios->c_cflag |= BOTHER; 291 /* Set exact input bits only if the input and output differ or the 292 user already did */ 293 if (ifound == -1 && (ibaud != obaud || ibinput)) 294 termios->c_cflag |= (BOTHER << IBSHIFT); 295#else 296 if (ifound == -1 || ofound == -1) { 297 static int warned; 298 if (!warned++) 299 printk(KERN_WARNING "tty: Unable to return correct " 300 "speed data as your architecture needs updating.\n"); 301 } 302#endif 303} 304EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); 305 306void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud) 307{ 308 tty_termios_encode_baud_rate(tty->termios, ibaud, obaud); 309} 310EXPORT_SYMBOL_GPL(tty_encode_baud_rate); 311 312/** 313 * tty_get_baud_rate - get tty bit rates 314 * @tty: tty to query 315 * 316 * Returns the baud rate as an integer for this terminal. The 317 * termios lock must be held by the caller and the terminal bit 318 * flags may be updated. 319 * 320 * Locking: none 321 */ 322 323speed_t tty_get_baud_rate(struct tty_struct *tty) 324{ 325 speed_t baud = tty_termios_baud_rate(tty->termios); 326 327 if (baud == 38400 && tty->alt_speed) { 328 if (!tty->warned) { 329 printk(KERN_WARNING "Use of setserial/setrocket to " 330 "set SPD_* flags is deprecated\n"); 331 tty->warned = 1; 332 } 333 baud = tty->alt_speed; 334 } 335 336 return baud; 337} 338EXPORT_SYMBOL(tty_get_baud_rate); 339 340/** 341 * tty_termios_copy_hw - copy hardware settings 342 * @new: New termios 343 * @old: Old termios 344 * 345 * Propogate the hardware specific terminal setting bits from 346 * the old termios structure to the new one. This is used in cases 347 * where the hardware does not support reconfiguration or as a helper 348 * in some cases where only minimal reconfiguration is supported 349 */ 350 351void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old) 352{ 353 /* The bits a dumb device handles in software. Smart devices need 354 to always provide a set_termios method */ 355 new->c_cflag &= HUPCL | CREAD | CLOCAL; 356 new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL); 357 new->c_ispeed = old->c_ispeed; 358 new->c_ospeed = old->c_ospeed; 359} 360EXPORT_SYMBOL(tty_termios_copy_hw); 361 362/** 363 * tty_termios_hw_change - check for setting change 364 * @a: termios 365 * @b: termios to compare 366 * 367 * Check if any of the bits that affect a dumb device have changed 368 * between the two termios structures, or a speed change is needed. 369 */ 370 371int tty_termios_hw_change(struct ktermios *a, struct ktermios *b) 372{ 373 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) 374 return 1; 375 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL)) 376 return 1; 377 return 0; 378} 379EXPORT_SYMBOL(tty_termios_hw_change); 380 381/** 382 * change_termios - update termios values 383 * @tty: tty to update 384 * @new_termios: desired new value 385 * 386 * Perform updates to the termios values set on this terminal. There 387 * is a bit of layering violation here with n_tty in terms of the 388 * internal knowledge of this function. 389 * 390 * Locking: termios_sem 391 */ 392 393static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) 394{ 395 int canon_change; 396 struct ktermios old_termios = *tty->termios; 397 struct tty_ldisc *ld; 398 399 /* 400 * Perform the actual termios internal changes under lock. 401 */ 402 403 404 /* FIXME: we need to decide on some locking/ordering semantics 405 for the set_termios notification eventually */ 406 mutex_lock(&tty->termios_mutex); 407 408 *tty->termios = *new_termios; 409 unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); 410 canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; 411 if (canon_change) { 412 memset(&tty->read_flags, 0, sizeof tty->read_flags); 413 tty->canon_head = tty->read_tail; 414 tty->canon_data = 0; 415 tty->erasing = 0; 416 } 417 418 /* This bit should be in the ldisc code */ 419 if (canon_change && !L_ICANON(tty) && tty->read_cnt) 420 /* Get characters left over from canonical mode. */ 421 wake_up_interruptible(&tty->read_wait); 422 423 /* See if packet mode change of state. */ 424 if (tty->link && tty->link->packet) { 425 int old_flow = ((old_termios.c_iflag & IXON) && 426 (old_termios.c_cc[VSTOP] == '\023') && 427 (old_termios.c_cc[VSTART] == '\021')); 428 int new_flow = (I_IXON(tty) && 429 STOP_CHAR(tty) == '\023' && 430 START_CHAR(tty) == '\021'); 431 if (old_flow != new_flow) { 432 tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); 433 if (new_flow) 434 tty->ctrl_status |= TIOCPKT_DOSTOP; 435 else 436 tty->ctrl_status |= TIOCPKT_NOSTOP; 437 wake_up_interruptible(&tty->link->read_wait); 438 } 439 } 440 441 if (tty->driver->set_termios) 442 (*tty->driver->set_termios)(tty, &old_termios); 443 else 444 tty_termios_copy_hw(tty->termios, &old_termios); 445 446 ld = tty_ldisc_ref(tty); 447 if (ld != NULL) { 448 if (ld->set_termios) 449 (ld->set_termios)(tty, &old_termios); 450 tty_ldisc_deref(ld); 451 } 452 mutex_unlock(&tty->termios_mutex); 453} 454 455/** 456 * set_termios - set termios values for a tty 457 * @tty: terminal device 458 * @arg: user data 459 * @opt: option information 460 * 461 * Helper function to prepare termios data and run necessary other 462 * functions before using change_termios to do the actual changes. 463 * 464 * Locking: 465 * Called functions take ldisc and termios_sem locks 466 */ 467 468static int set_termios(struct tty_struct *tty, void __user *arg, int opt) 469{ 470 struct ktermios tmp_termios; 471 struct tty_ldisc *ld; 472 int retval = tty_check_change(tty); 473 474 if (retval) 475 return retval; 476 477 memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); 478 479 if (opt & TERMIOS_TERMIO) { 480 if (user_termio_to_kernel_termios(&tmp_termios, 481 (struct termio __user *)arg)) 482 return -EFAULT; 483#ifdef TCGETS2 484 } else if (opt & TERMIOS_OLD) { 485 if (user_termios_to_kernel_termios_1(&tmp_termios, 486 (struct termios __user *)arg)) 487 return -EFAULT; 488 } else { 489 if (user_termios_to_kernel_termios(&tmp_termios, 490 (struct termios2 __user *)arg)) 491 return -EFAULT; 492 } 493#else 494 } else if (user_termios_to_kernel_termios(&tmp_termios, 495 (struct termios __user *)arg)) 496 return -EFAULT; 497#endif 498 499 /* If old style Bfoo values are used then load c_ispeed/c_ospeed 500 * with the real speed so its unconditionally usable */ 501 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); 502 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); 503 504 ld = tty_ldisc_ref(tty); 505 506 if (ld != NULL) { 507 if ((opt & TERMIOS_FLUSH) && ld->flush_buffer) 508 ld->flush_buffer(tty); 509 tty_ldisc_deref(ld); 510 } 511 512 if (opt & TERMIOS_WAIT) { 513 tty_wait_until_sent(tty, 0); 514 if (signal_pending(current)) 515 return -EINTR; 516 } 517 518 change_termios(tty, &tmp_termios); 519 520 /* FIXME: Arguably if tmp_termios == tty->termios AND the 521 actual requested termios was not tmp_termios then we may 522 want to return an error as no user requested change has 523 succeeded */ 524 return 0; 525} 526 527static int get_termio(struct tty_struct *tty, struct termio __user *termio) 528{ 529 if (kernel_termios_to_user_termio(termio, tty->termios)) 530 return -EFAULT; 531 return 0; 532} 533 534static unsigned long inq_canon(struct tty_struct *tty) 535{ 536 int nr, head, tail; 537 538 if (!tty->canon_data || !tty->read_buf) 539 return 0; 540 head = tty->canon_head; 541 tail = tty->read_tail; 542 nr = (head - tail) & (N_TTY_BUF_SIZE-1); 543 /* Skip EOF-chars.. */ 544 while (head != tail) { 545 if (test_bit(tail, tty->read_flags) && 546 tty->read_buf[tail] == __DISABLED_CHAR) 547 nr--; 548 tail = (tail+1) & (N_TTY_BUF_SIZE-1); 549 } 550 return nr; 551} 552 553#ifdef TIOCGETP 554/* 555 * These are deprecated, but there is limited support.. 556 * 557 * The "sg_flags" translation is a joke.. 558 */ 559static int get_sgflags(struct tty_struct *tty) 560{ 561 int flags = 0; 562 563 if (!(tty->termios->c_lflag & ICANON)) { 564 if (tty->termios->c_lflag & ISIG) 565 flags |= 0x02; /* cbreak */ 566 else 567 flags |= 0x20; /* raw */ 568 } 569 if (tty->termios->c_lflag & ECHO) 570 flags |= 0x08; /* echo */ 571 if (tty->termios->c_oflag & OPOST) 572 if (tty->termios->c_oflag & ONLCR) 573 flags |= 0x10; /* crmod */ 574 return flags; 575} 576 577static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) 578{ 579 struct sgttyb tmp; 580 581 mutex_lock(&tty->termios_mutex); 582 tmp.sg_ispeed = tty->termios->c_ispeed; 583 tmp.sg_ospeed = tty->termios->c_ospeed; 584 tmp.sg_erase = tty->termios->c_cc[VERASE]; 585 tmp.sg_kill = tty->termios->c_cc[VKILL]; 586 tmp.sg_flags = get_sgflags(tty); 587 mutex_unlock(&tty->termios_mutex); 588 589 return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; 590} 591 592static void set_sgflags(struct ktermios *termios, int flags) 593{ 594 termios->c_iflag = ICRNL | IXON; 595 termios->c_oflag = 0; 596 termios->c_lflag = ISIG | ICANON; 597 if (flags & 0x02) { /* cbreak */ 598 termios->c_iflag = 0; 599 termios->c_lflag &= ~ICANON; 600 } 601 if (flags & 0x08) { /* echo */ 602 termios->c_lflag |= ECHO | ECHOE | ECHOK | 603 ECHOCTL | ECHOKE | IEXTEN; 604 } 605 if (flags & 0x10) { /* crmod */ 606 termios->c_oflag |= OPOST | ONLCR; 607 } 608 if (flags & 0x20) { /* raw */ 609 termios->c_iflag = 0; 610 termios->c_lflag &= ~(ISIG | ICANON); 611 } 612 if (!(termios->c_lflag & ICANON)) { 613 termios->c_cc[VMIN] = 1; 614 termios->c_cc[VTIME] = 0; 615 } 616} 617 618/** 619 * set_sgttyb - set legacy terminal values 620 * @tty: tty structure 621 * @sgttyb: pointer to old style terminal structure 622 * 623 * Updates a terminal from the legacy BSD style terminal information 624 * structure. 625 * 626 * Locking: termios_sem 627 */ 628 629static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) 630{ 631 int retval; 632 struct sgttyb tmp; 633 struct ktermios termios; 634 635 retval = tty_check_change(tty); 636 if (retval) 637 return retval; 638 639 if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) 640 return -EFAULT; 641 642 mutex_lock(&tty->termios_mutex); 643 termios = *tty->termios; 644 termios.c_cc[VERASE] = tmp.sg_erase; 645 termios.c_cc[VKILL] = tmp.sg_kill; 646 set_sgflags(&termios, tmp.sg_flags); 647 /* Try and encode into Bfoo format */ 648#ifdef BOTHER 649 tty_termios_encode_baud_rate(&termios, termios.c_ispeed, 650 termios.c_ospeed); 651#endif 652 mutex_unlock(&tty->termios_mutex); 653 change_termios(tty, &termios); 654 return 0; 655} 656#endif 657 658#ifdef TIOCGETC 659static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) 660{ 661 struct tchars tmp; 662 663 tmp.t_intrc = tty->termios->c_cc[VINTR]; 664 tmp.t_quitc = tty->termios->c_cc[VQUIT]; 665 tmp.t_startc = tty->termios->c_cc[VSTART]; 666 tmp.t_stopc = tty->termios->c_cc[VSTOP]; 667 tmp.t_eofc = tty->termios->c_cc[VEOF]; 668 tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ 669 return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; 670} 671 672static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) 673{ 674 struct tchars tmp; 675 676 if (copy_from_user(&tmp, tchars, sizeof(tmp))) 677 return -EFAULT; 678 tty->termios->c_cc[VINTR] = tmp.t_intrc; 679 tty->termios->c_cc[VQUIT] = tmp.t_quitc; 680 tty->termios->c_cc[VSTART] = tmp.t_startc; 681 tty->termios->c_cc[VSTOP] = tmp.t_stopc; 682 tty->termios->c_cc[VEOF] = tmp.t_eofc; 683 tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ 684 return 0; 685} 686#endif 687 688#ifdef TIOCGLTC 689static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) 690{ 691 struct ltchars tmp; 692 693 tmp.t_suspc = tty->termios->c_cc[VSUSP]; 694 /* what is dsuspc anyway? */ 695 tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; 696 tmp.t_rprntc = tty->termios->c_cc[VREPRINT]; 697 /* what is flushc anyway? */ 698 tmp.t_flushc = tty->termios->c_cc[VEOL2]; 699 tmp.t_werasc = tty->termios->c_cc[VWERASE]; 700 tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; 701 return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; 702} 703 704static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) 705{ 706 struct ltchars tmp; 707 708 if (copy_from_user(&tmp, ltchars, sizeof(tmp))) 709 return -EFAULT; 710 711 tty->termios->c_cc[VSUSP] = tmp.t_suspc; 712 /* what is dsuspc anyway? */ 713 tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; 714 tty->termios->c_cc[VREPRINT] = tmp.t_rprntc; 715 /* what is flushc anyway? */ 716 tty->termios->c_cc[VEOL2] = tmp.t_flushc; 717 tty->termios->c_cc[VWERASE] = tmp.t_werasc; 718 tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; 719 return 0; 720} 721#endif 722 723/** 724 * send_prio_char - send priority character 725 * 726 * Send a high priority character to the tty even if stopped 727 * 728 * Locking: none for xchar method, write ordering for write method. 729 */ 730 731static int send_prio_char(struct tty_struct *tty, char ch) 732{ 733 int was_stopped = tty->stopped; 734 735 if (tty->driver->send_xchar) { 736 tty->driver->send_xchar(tty, ch); 737 return 0; 738 } 739 740 if (tty_write_lock(tty, 0) < 0) 741 return -ERESTARTSYS; 742 743 if (was_stopped) 744 start_tty(tty); 745 tty->driver->write(tty, &ch, 1); 746 if (was_stopped) 747 stop_tty(tty); 748 tty_write_unlock(tty); 749 return 0; 750} 751 752/** 753 * tty_mode_ioctl - mode related ioctls 754 * @tty: tty for the ioctl 755 * @file: file pointer for the tty 756 * @cmd: command 757 * @arg: ioctl argument 758 * 759 * Perform non line discipline specific mode control ioctls. This 760 * is designed to be called by line disciplines to ensure they provide 761 * consistent mode setting. 762 */ 763 764int tty_mode_ioctl(struct tty_struct *tty, struct file *file, 765 unsigned int cmd, unsigned long arg) 766{ 767 struct tty_struct *real_tty; 768 void __user *p = (void __user *)arg; 769 770 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 771 tty->driver->subtype == PTY_TYPE_MASTER) 772 real_tty = tty->link; 773 else 774 real_tty = tty; 775 776 switch (cmd) { 777#ifdef TIOCGETP 778 case TIOCGETP: 779 return get_sgttyb(real_tty, (struct sgttyb __user *) arg); 780 case TIOCSETP: 781 case TIOCSETN: 782 return set_sgttyb(real_tty, (struct sgttyb __user *) arg); 783#endif 784#ifdef TIOCGETC 785 case TIOCGETC: 786 return get_tchars(real_tty, p); 787 case TIOCSETC: 788 return set_tchars(real_tty, p); 789#endif 790#ifdef TIOCGLTC 791 case TIOCGLTC: 792 return get_ltchars(real_tty, p); 793 case TIOCSLTC: 794 return set_ltchars(real_tty, p); 795#endif 796 case TCSETSF: 797 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); 798 case TCSETSW: 799 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); 800 case TCSETS: 801 return set_termios(real_tty, p, TERMIOS_OLD); 802#ifndef TCGETS2 803 case TCGETS: 804 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) 805 return -EFAULT; 806 return 0; 807#else 808 case TCGETS: 809 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) 810 return -EFAULT; 811 return 0; 812 case TCGETS2: 813 if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) 814 return -EFAULT; 815 return 0; 816 case TCSETSF2: 817 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); 818 case TCSETSW2: 819 return set_termios(real_tty, p, TERMIOS_WAIT); 820 case TCSETS2: 821 return set_termios(real_tty, p, 0); 822#endif 823 case TCGETA: 824 return get_termio(real_tty, p); 825 case TCSETAF: 826 return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); 827 case TCSETAW: 828 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); 829 case TCSETA: 830 return set_termios(real_tty, p, TERMIOS_TERMIO); 831#ifndef TCGETS2 832 case TIOCGLCKTRMIOS: 833 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) 834 return -EFAULT; 835 return 0; 836 case TIOCSLCKTRMIOS: 837 if (!capable(CAP_SYS_ADMIN)) 838 return -EPERM; 839 if (user_termios_to_kernel_termios(real_tty->termios_locked, 840 (struct termios __user *) arg)) 841 return -EFAULT; 842 return 0; 843#else 844 case TIOCGLCKTRMIOS: 845 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) 846 return -EFAULT; 847 return 0; 848 case TIOCSLCKTRMIOS: 849 if (!capable(CAP_SYS_ADMIN)) 850 return -EPERM; 851 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, 852 (struct termios __user *) arg)) 853 return -EFAULT; 854 return 0; 855#endif 856 case TIOCGSOFTCAR: 857 return put_user(C_CLOCAL(tty) ? 1 : 0, 858 (int __user *)arg); 859 case TIOCSSOFTCAR: 860 if (get_user(arg, (unsigned int __user *) arg)) 861 return -EFAULT; 862 mutex_lock(&tty->termios_mutex); 863 tty->termios->c_cflag = 864 ((tty->termios->c_cflag & ~CLOCAL) | 865 (arg ? CLOCAL : 0)); 866 mutex_unlock(&tty->termios_mutex); 867 return 0; 868 default: 869 return -ENOIOCTLCMD; 870 } 871} 872EXPORT_SYMBOL_GPL(tty_mode_ioctl); 873 874int tty_perform_flush(struct tty_struct *tty, unsigned long arg) 875{ 876 struct tty_ldisc *ld; 877 int retval = tty_check_change(tty); 878 if (retval) 879 return retval; 880 881 ld = tty_ldisc_ref(tty); 882 switch (arg) { 883 case TCIFLUSH: 884 if (ld && ld->flush_buffer) 885 ld->flush_buffer(tty); 886 break; 887 case TCIOFLUSH: 888 if (ld && ld->flush_buffer) 889 ld->flush_buffer(tty); 890 /* fall through */ 891 case TCOFLUSH: 892 if (tty->driver->flush_buffer) 893 tty->driver->flush_buffer(tty); 894 break; 895 default: 896 tty_ldisc_deref(ld); 897 return -EINVAL; 898 } 899 tty_ldisc_deref(ld); 900 return 0; 901} 902EXPORT_SYMBOL_GPL(tty_perform_flush); 903 904int n_tty_ioctl(struct tty_struct *tty, struct file *file, 905 unsigned int cmd, unsigned long arg) 906{ 907 struct tty_struct *real_tty; 908 int retval; 909 910 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 911 tty->driver->subtype == PTY_TYPE_MASTER) 912 real_tty = tty->link; 913 else 914 real_tty = tty; 915 916 switch (cmd) { 917 case TCXONC: 918 retval = tty_check_change(tty); 919 if (retval) 920 return retval; 921 switch (arg) { 922 case TCOOFF: 923 if (!tty->flow_stopped) { 924 tty->flow_stopped = 1; 925 stop_tty(tty); 926 } 927 break; 928 case TCOON: 929 if (tty->flow_stopped) { 930 tty->flow_stopped = 0; 931 start_tty(tty); 932 } 933 break; 934 case TCIOFF: 935 if (STOP_CHAR(tty) != __DISABLED_CHAR) 936 return send_prio_char(tty, STOP_CHAR(tty)); 937 break; 938 case TCION: 939 if (START_CHAR(tty) != __DISABLED_CHAR) 940 return send_prio_char(tty, START_CHAR(tty)); 941 break; 942 default: 943 return -EINVAL; 944 } 945 return 0; 946 case TCFLSH: 947 return tty_perform_flush(tty, arg); 948 case TIOCOUTQ: 949 return put_user(tty->driver->chars_in_buffer ? 950 tty->driver->chars_in_buffer(tty) : 0, 951 (int __user *) arg); 952 case TIOCINQ: 953 retval = tty->read_cnt; 954 if (L_ICANON(tty)) 955 retval = inq_canon(tty); 956 return put_user(retval, (unsigned int __user *) arg); 957 case TIOCPKT: 958 { 959 int pktmode; 960 961 if (tty->driver->type != TTY_DRIVER_TYPE_PTY || 962 tty->driver->subtype != PTY_TYPE_MASTER) 963 return -ENOTTY; 964 if (get_user(pktmode, (int __user *) arg)) 965 return -EFAULT; 966 if (pktmode) { 967 if (!tty->packet) { 968 tty->packet = 1; 969 tty->link->ctrl_status = 0; 970 } 971 } else 972 tty->packet = 0; 973 return 0; 974 } 975 default: 976 /* Try the mode commands */ 977 return tty_mode_ioctl(tty, file, cmd, arg); 978 } 979} 980EXPORT_SYMBOL(n_tty_ioctl);