aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/pty.c')
-rw-r--r--drivers/char/pty.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index ec09c1cd4fe9..328e8ac12306 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -23,6 +23,7 @@
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/sysctl.h> 25#include <linux/sysctl.h>
26#include <linux/device.h>
26 27
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28#include <asm/system.h> 29#include <asm/system.h>
@@ -332,6 +333,8 @@ int pty_limit = NR_UNIX98_PTY_DEFAULT;
332static int pty_limit_min = 0; 333static int pty_limit_min = 0;
333static int pty_limit_max = NR_UNIX98_PTY_MAX; 334static int pty_limit_max = NR_UNIX98_PTY_MAX;
334 335
336static struct cdev ptmx_cdev;
337
335static struct ctl_table pty_table[] = { 338static struct ctl_table pty_table[] = {
336 { 339 {
337 .ctl_name = PTY_MAX, 340 .ctl_name = PTY_MAX,
@@ -408,6 +411,70 @@ static const struct tty_operations ptm_unix98_ops = {
408 .shutdown = pty_shutdown 411 .shutdown = pty_shutdown
409}; 412};
410 413
414
415/**
416 * ptmx_open - open a unix 98 pty master
417 * @inode: inode of device file
418 * @filp: file pointer to tty
419 *
420 * Allocate a unix98 pty master device from the ptmx driver.
421 *
422 * Locking: tty_mutex protects the init_dev work. tty->count should
423 * protect the rest.
424 * allocated_ptys_lock handles the list of free pty numbers
425 */
426
427static int __ptmx_open(struct inode *inode, struct file *filp)
428{
429 struct tty_struct *tty;
430 int retval;
431 int index;
432
433 nonseekable_open(inode, filp);
434
435 /* find a device that is not in use. */
436 index = devpts_new_index();
437 if (index < 0)
438 return index;
439
440 mutex_lock(&tty_mutex);
441 retval = tty_init_dev(ptm_driver, index, &tty, 1);
442 mutex_unlock(&tty_mutex);
443
444 if (retval)
445 goto out;
446
447 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
448 filp->private_data = tty;
449 file_move(filp, &tty->tty_files);
450
451 retval = devpts_pty_new(tty->link);
452 if (retval)
453 goto out1;
454
455 retval = ptm_driver->ops->open(tty, filp);
456 if (!retval)
457 return 0;
458out1:
459 tty_release_dev(filp);
460 return retval;
461out:
462 devpts_kill_index(index);
463 return retval;
464}
465
466static int ptmx_open(struct inode *inode, struct file *filp)
467{
468 int ret;
469
470 lock_kernel();
471 ret = __ptmx_open(inode, filp);
472 unlock_kernel();
473 return ret;
474}
475
476static struct file_operations ptmx_fops;
477
411static void __init unix98_pty_init(void) 478static void __init unix98_pty_init(void)
412{ 479{
413 ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); 480 ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
@@ -459,7 +526,18 @@ static void __init unix98_pty_init(void)
459 526
460 pty_table[1].data = &ptm_driver->refcount; 527 pty_table[1].data = &ptm_driver->refcount;
461 register_sysctl_table(pty_root_table); 528 register_sysctl_table(pty_root_table);
529
530 /* Now create the /dev/ptmx special device */
531 tty_default_fops(&ptmx_fops);
532 ptmx_fops.open = ptmx_open;
533
534 cdev_init(&ptmx_cdev, &ptmx_fops);
535 if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
536 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
537 panic("Couldn't register /dev/ptmx driver\n");
538 device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
462} 539}
540
463#else 541#else
464static inline void unix98_pty_init(void) { } 542static inline void unix98_pty_init(void) { }
465#endif 543#endif