diff options
Diffstat (limited to 'drivers/char/pty.c')
-rw-r--r-- | drivers/char/pty.c | 78 |
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; | |||
332 | static int pty_limit_min = 0; | 333 | static int pty_limit_min = 0; |
333 | static int pty_limit_max = NR_UNIX98_PTY_MAX; | 334 | static int pty_limit_max = NR_UNIX98_PTY_MAX; |
334 | 335 | ||
336 | static struct cdev ptmx_cdev; | ||
337 | |||
335 | static struct ctl_table pty_table[] = { | 338 | static 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 | |||
427 | static 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; | ||
458 | out1: | ||
459 | tty_release_dev(filp); | ||
460 | return retval; | ||
461 | out: | ||
462 | devpts_kill_index(index); | ||
463 | return retval; | ||
464 | } | ||
465 | |||
466 | static 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 | |||
476 | static struct file_operations ptmx_fops; | ||
477 | |||
411 | static void __init unix98_pty_init(void) | 478 | static 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 |
464 | static inline void unix98_pty_init(void) { } | 542 | static inline void unix98_pty_init(void) { } |
465 | #endif | 543 | #endif |