pty.c (f9cd49033b349b8be3bb1f01b39eed837853d880) | pty.c (89c8d91e31f267703e365593f6bfebb9f6d2ad01) |
---|---|
1/* 2 * Copyright (C) 1991, 1992 Linus Torvalds 3 * 4 * Added support for a Unix98-style ptmx device. 5 * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 6 * 7 * When reading this code see also fs/devpts. In particular note that the 8 * driver_data field is used by the devpts side as a binding to the devpts --- 33 unchanged lines hidden (view full) --- 42 WARN_ON(tty->count > 1); 43 else { 44 if (tty->count > 2) 45 return; 46 } 47 wake_up_interruptible(&tty->read_wait); 48 wake_up_interruptible(&tty->write_wait); 49 tty->packet = 0; | 1/* 2 * Copyright (C) 1991, 1992 Linus Torvalds 3 * 4 * Added support for a Unix98-style ptmx device. 5 * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 6 * 7 * When reading this code see also fs/devpts. In particular note that the 8 * driver_data field is used by the devpts side as a binding to the devpts --- 33 unchanged lines hidden (view full) --- 42 WARN_ON(tty->count > 1); 43 else { 44 if (tty->count > 2) 45 return; 46 } 47 wake_up_interruptible(&tty->read_wait); 48 wake_up_interruptible(&tty->write_wait); 49 tty->packet = 0; |
50 /* Review - krefs on tty_link ?? */ |
|
50 if (!tty->link) 51 return; 52 tty->link->packet = 0; 53 set_bit(TTY_OTHER_CLOSED, &tty->link->flags); 54 wake_up_interruptible(&tty->link->read_wait); 55 wake_up_interruptible(&tty->link->write_wait); 56 if (tty->driver->subtype == PTY_TYPE_MASTER) { 57 set_bit(TTY_OTHER_CLOSED, &tty->flags); 58#ifdef CONFIG_UNIX98_PTYS 59 if (tty->driver == ptm_driver) { 60 mutex_lock(&devpts_mutex); 61 devpts_pty_kill(tty->link); 62 mutex_unlock(&devpts_mutex); 63 } 64#endif | 51 if (!tty->link) 52 return; 53 tty->link->packet = 0; 54 set_bit(TTY_OTHER_CLOSED, &tty->link->flags); 55 wake_up_interruptible(&tty->link->read_wait); 56 wake_up_interruptible(&tty->link->write_wait); 57 if (tty->driver->subtype == PTY_TYPE_MASTER) { 58 set_bit(TTY_OTHER_CLOSED, &tty->flags); 59#ifdef CONFIG_UNIX98_PTYS 60 if (tty->driver == ptm_driver) { 61 mutex_lock(&devpts_mutex); 62 devpts_pty_kill(tty->link); 63 mutex_unlock(&devpts_mutex); 64 } 65#endif |
65 tty_unlock(); | 66 tty_unlock(tty); |
66 tty_vhangup(tty->link); | 67 tty_vhangup(tty->link); |
67 tty_lock(); | 68 tty_lock(tty); |
68 } 69} 70 71/* 72 * The unthrottle routine is called by the line discipline to signal 73 * that it can receive more characters. For PTY's, the TTY_THROTTLED 74 * flag is always set, to force the line discipline to always call the 75 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE --- 150 unchanged lines hidden (view full) --- 226 retval = 0; 227out: 228 return retval; 229} 230 231static void pty_set_termios(struct tty_struct *tty, 232 struct ktermios *old_termios) 233{ | 69 } 70} 71 72/* 73 * The unthrottle routine is called by the line discipline to signal 74 * that it can receive more characters. For PTY's, the TTY_THROTTLED 75 * flag is always set, to force the line discipline to always call the 76 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE --- 150 unchanged lines hidden (view full) --- 227 retval = 0; 228out: 229 return retval; 230} 231 232static void pty_set_termios(struct tty_struct *tty, 233 struct ktermios *old_termios) 234{ |
234 tty->termios->c_cflag &= ~(CSIZE | PARENB); 235 tty->termios->c_cflag |= (CS8 | CREAD); | 235 tty->termios.c_cflag &= ~(CSIZE | PARENB); 236 tty->termios.c_cflag |= (CS8 | CREAD); |
236} 237 238/** 239 * pty_do_resize - resize event 240 * @tty: tty being resized 241 * @ws: window size being set. 242 * 243 * Update the termios variables and send the necessary signals to --- 33 unchanged lines hidden (view full) --- 277 278 tty->winsize = *ws; 279 pty->winsize = *ws; /* Never used so will go away soon */ 280done: 281 mutex_unlock(&tty->termios_mutex); 282 return 0; 283} 284 | 237} 238 239/** 240 * pty_do_resize - resize event 241 * @tty: tty being resized 242 * @ws: window size being set. 243 * 244 * Update the termios variables and send the necessary signals to --- 33 unchanged lines hidden (view full) --- 278 279 tty->winsize = *ws; 280 pty->winsize = *ws; /* Never used so will go away soon */ 281done: 282 mutex_unlock(&tty->termios_mutex); 283 return 0; 284} 285 |
285/* Traditional BSD devices */ 286#ifdef CONFIG_LEGACY_PTYS 287 288static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | 286/** 287 * pty_common_install - set up the pty pair 288 * @driver: the pty driver 289 * @tty: the tty being instantiated 290 * @bool: legacy, true if this is BSD style 291 * 292 * Perform the initial set up for the tty/pty pair. Called from the 293 * tty layer when the port is first opened. 294 * 295 * Locking: the caller must hold the tty_mutex 296 */ 297static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, 298 bool legacy) |
289{ 290 struct tty_struct *o_tty; | 299{ 300 struct tty_struct *o_tty; |
301 struct tty_port *ports[2]; |
|
291 int idx = tty->index; | 302 int idx = tty->index; |
292 int retval; | 303 int retval = -ENOMEM; |
293 294 o_tty = alloc_tty_struct(); | 304 305 o_tty = alloc_tty_struct(); |
295 if (!o_tty) 296 return -ENOMEM; | 306 ports[0] = kmalloc(sizeof **ports, GFP_KERNEL); 307 ports[1] = kmalloc(sizeof **ports, GFP_KERNEL); 308 if (!o_tty || !ports[0] || !ports[1]) 309 goto err_free_tty; |
297 if (!try_module_get(driver->other->owner)) { 298 /* This cannot in fact currently happen */ | 310 if (!try_module_get(driver->other->owner)) { 311 /* This cannot in fact currently happen */ |
299 retval = -ENOMEM; | |
300 goto err_free_tty; 301 } 302 initialize_tty_struct(o_tty, driver->other, idx); 303 | 312 goto err_free_tty; 313 } 314 initialize_tty_struct(o_tty, driver->other, idx); 315 |
304 /* We always use new tty termios data so we can do this 305 the easy way .. */ 306 retval = tty_init_termios(tty); 307 if (retval) 308 goto err_deinit_tty; | 316 if (legacy) { 317 /* We always use new tty termios data so we can do this 318 the easy way .. */ 319 retval = tty_init_termios(tty); 320 if (retval) 321 goto err_deinit_tty; |
309 | 322 |
310 retval = tty_init_termios(o_tty); 311 if (retval) 312 goto err_free_termios; | 323 retval = tty_init_termios(o_tty); 324 if (retval) 325 goto err_free_termios; |
313 | 326 |
327 driver->other->ttys[idx] = o_tty; 328 driver->ttys[idx] = tty; 329 } else { 330 memset(&tty->termios_locked, 0, sizeof(tty->termios_locked)); 331 tty->termios = driver->init_termios; 332 memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked)); 333 o_tty->termios = driver->other->init_termios; 334 } 335 |
|
314 /* 315 * Everything allocated ... set up the o_tty structure. 316 */ | 336 /* 337 * Everything allocated ... set up the o_tty structure. 338 */ |
317 driver->other->ttys[idx] = o_tty; | |
318 tty_driver_kref_get(driver->other); 319 if (driver->subtype == PTY_TYPE_MASTER) 320 o_tty->count++; 321 /* Establish the links in both directions */ 322 tty->link = o_tty; 323 o_tty->link = tty; | 339 tty_driver_kref_get(driver->other); 340 if (driver->subtype == PTY_TYPE_MASTER) 341 o_tty->count++; 342 /* Establish the links in both directions */ 343 tty->link = o_tty; 344 o_tty->link = tty; |
345 tty_port_init(ports[0]); 346 tty_port_init(ports[1]); 347 o_tty->port = ports[0]; 348 tty->port = ports[1]; |
|
324 325 tty_driver_kref_get(driver); 326 tty->count++; | 349 350 tty_driver_kref_get(driver); 351 tty->count++; |
327 driver->ttys[idx] = tty; | |
328 return 0; 329err_free_termios: | 352 return 0; 353err_free_termios: |
330 tty_free_termios(tty); | 354 if (legacy) 355 tty_free_termios(tty); |
331err_deinit_tty: 332 deinitialize_tty_struct(o_tty); 333 module_put(o_tty->driver->owner); 334err_free_tty: | 356err_deinit_tty: 357 deinitialize_tty_struct(o_tty); 358 module_put(o_tty->driver->owner); 359err_free_tty: |
360 kfree(ports[0]); 361 kfree(ports[1]); |
|
335 free_tty_struct(o_tty); 336 return retval; 337} 338 | 362 free_tty_struct(o_tty); 363 return retval; 364} 365 |
366static void pty_cleanup(struct tty_struct *tty) 367{ 368 kfree(tty->port); 369} 370 371/* Traditional BSD devices */ 372#ifdef CONFIG_LEGACY_PTYS 373 374static int pty_install(struct tty_driver *driver, struct tty_struct *tty) 375{ 376 return pty_common_install(driver, tty, true); 377} 378 379static void pty_remove(struct tty_driver *driver, struct tty_struct *tty) 380{ 381 struct tty_struct *pair = tty->link; 382 driver->ttys[tty->index] = NULL; 383 if (pair) 384 pair->driver->ttys[pair->index] = NULL; 385} 386 |
|
339static int pty_bsd_ioctl(struct tty_struct *tty, 340 unsigned int cmd, unsigned long arg) 341{ 342 switch (cmd) { 343 case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ 344 return pty_set_lock(tty, (int __user *) arg); 345 case TIOCSIG: /* Send signal to other side of pty */ 346 return pty_signal(tty, (int) arg); --- 14 unchanged lines hidden (view full) --- 361 .close = pty_close, 362 .write = pty_write, 363 .write_room = pty_write_room, 364 .flush_buffer = pty_flush_buffer, 365 .chars_in_buffer = pty_chars_in_buffer, 366 .unthrottle = pty_unthrottle, 367 .set_termios = pty_set_termios, 368 .ioctl = pty_bsd_ioctl, | 387static int pty_bsd_ioctl(struct tty_struct *tty, 388 unsigned int cmd, unsigned long arg) 389{ 390 switch (cmd) { 391 case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ 392 return pty_set_lock(tty, (int __user *) arg); 393 case TIOCSIG: /* Send signal to other side of pty */ 394 return pty_signal(tty, (int) arg); --- 14 unchanged lines hidden (view full) --- 409 .close = pty_close, 410 .write = pty_write, 411 .write_room = pty_write_room, 412 .flush_buffer = pty_flush_buffer, 413 .chars_in_buffer = pty_chars_in_buffer, 414 .unthrottle = pty_unthrottle, 415 .set_termios = pty_set_termios, 416 .ioctl = pty_bsd_ioctl, |
369 .resize = pty_resize | 417 .cleanup = pty_cleanup, 418 .resize = pty_resize, 419 .remove = pty_remove |
370}; 371 372static const struct tty_operations slave_pty_ops_bsd = { 373 .install = pty_install, 374 .open = pty_open, 375 .close = pty_close, 376 .write = pty_write, 377 .write_room = pty_write_room, 378 .flush_buffer = pty_flush_buffer, 379 .chars_in_buffer = pty_chars_in_buffer, 380 .unthrottle = pty_unthrottle, 381 .set_termios = pty_set_termios, | 420}; 421 422static const struct tty_operations slave_pty_ops_bsd = { 423 .install = pty_install, 424 .open = pty_open, 425 .close = pty_close, 426 .write = pty_write, 427 .write_room = pty_write_room, 428 .flush_buffer = pty_flush_buffer, 429 .chars_in_buffer = pty_chars_in_buffer, 430 .unthrottle = pty_unthrottle, 431 .set_termios = pty_set_termios, |
382 .resize = pty_resize | 432 .cleanup = pty_cleanup, 433 .resize = pty_resize, 434 .remove = pty_remove |
383}; 384 385static void __init legacy_pty_init(void) 386{ 387 struct tty_driver *pty_driver, *pty_slave_driver; 388 389 if (legacy_count <= 0) 390 return; --- 101 unchanged lines hidden (view full) --- 492 tty = devpts_get_tty(pts_inode, idx); 493 mutex_unlock(&devpts_mutex); 494 /* Master must be open before slave */ 495 if (!tty) 496 return ERR_PTR(-EIO); 497 return tty; 498} 499 | 435}; 436 437static void __init legacy_pty_init(void) 438{ 439 struct tty_driver *pty_driver, *pty_slave_driver; 440 441 if (legacy_count <= 0) 442 return; --- 101 unchanged lines hidden (view full) --- 544 tty = devpts_get_tty(pts_inode, idx); 545 mutex_unlock(&devpts_mutex); 546 /* Master must be open before slave */ 547 if (!tty) 548 return ERR_PTR(-EIO); 549 return tty; 550} 551 |
500static void pty_unix98_shutdown(struct tty_struct *tty) 501{ 502 tty_driver_remove_tty(tty->driver, tty); 503 /* We have our own method as we don't use the tty index */ 504 kfree(tty->termios); 505} 506 | |
507/* We have no need to install and remove our tty objects as devpts does all 508 the work for us */ 509 510static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) 511{ | 552/* We have no need to install and remove our tty objects as devpts does all 553 the work for us */ 554 555static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) 556{ |
512 struct tty_struct *o_tty; 513 int idx = tty->index; 514 515 o_tty = alloc_tty_struct(); 516 if (!o_tty) 517 return -ENOMEM; 518 if (!try_module_get(driver->other->owner)) { 519 /* This cannot in fact currently happen */ 520 goto err_free_tty; 521 } 522 initialize_tty_struct(o_tty, driver->other, idx); 523 524 tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); 525 if (tty->termios == NULL) 526 goto err_free_mem; 527 *tty->termios = driver->init_termios; 528 tty->termios_locked = tty->termios + 1; 529 530 o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); 531 if (o_tty->termios == NULL) 532 goto err_free_mem; 533 *o_tty->termios = driver->other->init_termios; 534 o_tty->termios_locked = o_tty->termios + 1; 535 536 tty_driver_kref_get(driver->other); 537 if (driver->subtype == PTY_TYPE_MASTER) 538 o_tty->count++; 539 /* Establish the links in both directions */ 540 tty->link = o_tty; 541 o_tty->link = tty; 542 /* 543 * All structures have been allocated, so now we install them. 544 * Failures after this point use release_tty to clean up, so 545 * there's no need to null out the local pointers. 546 */ 547 tty_driver_kref_get(driver); 548 tty->count++; 549 return 0; 550err_free_mem: 551 deinitialize_tty_struct(o_tty); 552 kfree(o_tty->termios); 553 kfree(tty->termios); 554 module_put(o_tty->driver->owner); 555err_free_tty: 556 free_tty_struct(o_tty); 557 return -ENOMEM; | 557 return pty_common_install(driver, tty, false); |
558} 559 | 558} 559 |
560static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | 560static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) |
561{ 562} 563 | 561{ 562} 563 |
564static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) 565{ 566} 567 | |
568static const struct tty_operations ptm_unix98_ops = { 569 .lookup = ptm_unix98_lookup, 570 .install = pty_unix98_install, | 564static const struct tty_operations ptm_unix98_ops = { 565 .lookup = ptm_unix98_lookup, 566 .install = pty_unix98_install, |
571 .remove = ptm_unix98_remove, | 567 .remove = pty_unix98_remove, |
572 .open = pty_open, 573 .close = pty_close, 574 .write = pty_write, 575 .write_room = pty_write_room, 576 .flush_buffer = pty_flush_buffer, 577 .chars_in_buffer = pty_chars_in_buffer, 578 .unthrottle = pty_unthrottle, 579 .set_termios = pty_set_termios, 580 .ioctl = pty_unix98_ioctl, | 568 .open = pty_open, 569 .close = pty_close, 570 .write = pty_write, 571 .write_room = pty_write_room, 572 .flush_buffer = pty_flush_buffer, 573 .chars_in_buffer = pty_chars_in_buffer, 574 .unthrottle = pty_unthrottle, 575 .set_termios = pty_set_termios, 576 .ioctl = pty_unix98_ioctl, |
581 .shutdown = pty_unix98_shutdown, 582 .resize = pty_resize | 577 .resize = pty_resize, 578 .cleanup = pty_cleanup |
583}; 584 585static const struct tty_operations pty_unix98_ops = { 586 .lookup = pts_unix98_lookup, 587 .install = pty_unix98_install, | 579}; 580 581static const struct tty_operations pty_unix98_ops = { 582 .lookup = pts_unix98_lookup, 583 .install = pty_unix98_install, |
588 .remove = pts_unix98_remove, | 584 .remove = pty_unix98_remove, |
589 .open = pty_open, 590 .close = pty_close, 591 .write = pty_write, 592 .write_room = pty_write_room, 593 .flush_buffer = pty_flush_buffer, 594 .chars_in_buffer = pty_chars_in_buffer, 595 .unthrottle = pty_unthrottle, 596 .set_termios = pty_set_termios, | 585 .open = pty_open, 586 .close = pty_close, 587 .write = pty_write, 588 .write_room = pty_write_room, 589 .flush_buffer = pty_flush_buffer, 590 .chars_in_buffer = pty_chars_in_buffer, 591 .unthrottle = pty_unthrottle, 592 .set_termios = pty_set_termios, |
597 .shutdown = pty_unix98_shutdown | 593 .cleanup = pty_cleanup, |
598}; 599 600/** 601 * ptmx_open - open a unix 98 pty master 602 * @inode: inode of device file 603 * @filp: file pointer to tty 604 * 605 * Allocate a unix98 pty master device from the ptmx driver. --- 11 unchanged lines hidden (view full) --- 617 618 nonseekable_open(inode, filp); 619 620 retval = tty_alloc_file(filp); 621 if (retval) 622 return retval; 623 624 /* find a device that is not in use. */ | 594}; 595 596/** 597 * ptmx_open - open a unix 98 pty master 598 * @inode: inode of device file 599 * @filp: file pointer to tty 600 * 601 * Allocate a unix98 pty master device from the ptmx driver. --- 11 unchanged lines hidden (view full) --- 613 614 nonseekable_open(inode, filp); 615 616 retval = tty_alloc_file(filp); 617 if (retval) 618 return retval; 619 620 /* find a device that is not in use. */ |
625 tty_lock(); | 621 mutex_lock(&devpts_mutex); |
626 index = devpts_new_index(inode); | 622 index = devpts_new_index(inode); |
627 tty_unlock(); | |
628 if (index < 0) { 629 retval = index; 630 goto err_file; 631 } 632 | 623 if (index < 0) { 624 retval = index; 625 goto err_file; 626 } 627 |
628 mutex_unlock(&devpts_mutex); 629 |
|
633 mutex_lock(&tty_mutex); | 630 mutex_lock(&tty_mutex); |
634 mutex_lock(&devpts_mutex); | |
635 tty = tty_init_dev(ptm_driver, index); | 631 tty = tty_init_dev(ptm_driver, index); |
636 mutex_unlock(&devpts_mutex); 637 tty_lock(); 638 mutex_unlock(&tty_mutex); | |
639 640 if (IS_ERR(tty)) { 641 retval = PTR_ERR(tty); 642 goto out; 643 } 644 | 632 633 if (IS_ERR(tty)) { 634 retval = PTR_ERR(tty); 635 goto out; 636 } 637 |
638 /* The tty returned here is locked so we can safely 639 drop the mutex */ 640 mutex_unlock(&tty_mutex); 641 |
|
645 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 646 647 tty_add_file(tty, filp); 648 649 retval = devpts_pty_new(inode, tty->link); 650 if (retval) 651 goto err_release; 652 653 retval = ptm_driver->ops->open(tty, filp); 654 if (retval) 655 goto err_release; 656 | 642 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 643 644 tty_add_file(tty, filp); 645 646 retval = devpts_pty_new(inode, tty->link); 647 if (retval) 648 goto err_release; 649 650 retval = ptm_driver->ops->open(tty, filp); 651 if (retval) 652 goto err_release; 653 |
657 tty_unlock(); | 654 tty_unlock(tty); |
658 return 0; 659err_release: | 655 return 0; 656err_release: |
660 tty_unlock(); | 657 tty_unlock(tty); |
661 tty_release(inode, filp); 662 return retval; 663out: | 658 tty_release(inode, filp); 659 return retval; 660out: |
661 mutex_unlock(&tty_mutex); |
|
664 devpts_kill_index(inode, index); | 662 devpts_kill_index(inode, index); |
665 tty_unlock(); | |
666err_file: | 663err_file: |
664 mutex_unlock(&devpts_mutex); |
|
667 tty_free_file(filp); 668 return retval; 669} 670 671static struct file_operations ptmx_fops; 672 673static void __init unix98_pty_init(void) 674{ --- 67 unchanged lines hidden --- | 665 tty_free_file(filp); 666 return retval; 667} 668 669static struct file_operations ptmx_fops; 670 671static void __init unix98_pty_init(void) 672{ --- 67 unchanged lines hidden --- |