linux/drivers/tty/pty.c
<<
>>
Prefs
   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
   9 *  inode.
  10 */
  11
  12#include <linux/module.h>
  13
  14#include <linux/errno.h>
  15#include <linux/interrupt.h>
  16#include <linux/tty.h>
  17#include <linux/tty_flip.h>
  18#include <linux/fcntl.h>
  19#include <linux/sched.h>
  20#include <linux/string.h>
  21#include <linux/major.h>
  22#include <linux/mm.h>
  23#include <linux/init.h>
  24#include <linux/device.h>
  25#include <linux/uaccess.h>
  26#include <linux/bitops.h>
  27#include <linux/devpts_fs.h>
  28#include <linux/slab.h>
  29#include <linux/mutex.h>
  30
  31
  32#ifdef CONFIG_UNIX98_PTYS
  33static struct tty_driver *ptm_driver;
  34static struct tty_driver *pts_driver;
  35static DEFINE_MUTEX(devpts_mutex);
  36#endif
  37
  38static void pty_close(struct tty_struct *tty, struct file *filp)
  39{
  40        BUG_ON(!tty);
  41        if (tty->driver->subtype == PTY_TYPE_MASTER)
  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        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
  65                tty_unlock();
  66                tty_vhangup(tty->link);
  67                tty_lock();
  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
  76 * characters in the queue.  This is necessary since each time this
  77 * happens, we need to wake up any sleeping processes that could be
  78 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
  79 * for the pty buffer to be drained.
  80 */
  81static void pty_unthrottle(struct tty_struct *tty)
  82{
  83        tty_wakeup(tty->link);
  84        set_bit(TTY_THROTTLED, &tty->flags);
  85}
  86
  87/**
  88 *      pty_space       -       report space left for writing
  89 *      @to: tty we are writing into
  90 *
  91 *      The tty buffers allow 64K but we sneak a peak and clip at 8K this
  92 *      allows a lot of overspill room for echo and other fun messes to
  93 *      be handled properly
  94 */
  95
  96static int pty_space(struct tty_struct *to)
  97{
  98        int n = 8192 - to->buf.memory_used;
  99        if (n < 0)
 100                return 0;
 101        return n;
 102}
 103
 104/**
 105 *      pty_write               -       write to a pty
 106 *      @tty: the tty we write from
 107 *      @buf: kernel buffer of data
 108 *      @count: bytes to write
 109 *
 110 *      Our "hardware" write method. Data is coming from the ldisc which
 111 *      may be in a non sleeping state. We simply throw this at the other
 112 *      end of the link as if we were an IRQ handler receiving stuff for
 113 *      the other side of the pty/tty pair.
 114 */
 115
 116static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
 117{
 118        struct tty_struct *to = tty->link;
 119
 120        if (tty->stopped)
 121                return 0;
 122
 123        if (c > 0) {
 124                /* Stuff the data into the input queue of the other end */
 125                c = tty_insert_flip_string(to, buf, c);
 126                /* And shovel */
 127                if (c) {
 128                        tty_flip_buffer_push(to);
 129                        tty_wakeup(tty);
 130                }
 131        }
 132        return c;
 133}
 134
 135/**
 136 *      pty_write_room  -       write space
 137 *      @tty: tty we are writing from
 138 *
 139 *      Report how many bytes the ldisc can send into the queue for
 140 *      the other device.
 141 */
 142
 143static int pty_write_room(struct tty_struct *tty)
 144{
 145        if (tty->stopped)
 146                return 0;
 147        return pty_space(tty->link);
 148}
 149
 150/**
 151 *      pty_chars_in_buffer     -       characters currently in our tx queue
 152 *      @tty: our tty
 153 *
 154 *      Report how much we have in the transmit queue. As everything is
 155 *      instantly at the other end this is easy to implement.
 156 */
 157
 158static int pty_chars_in_buffer(struct tty_struct *tty)
 159{
 160        return 0;
 161}
 162
 163/* Set the lock flag on a pty */
 164static int pty_set_lock(struct tty_struct *tty, int __user *arg)
 165{
 166        int val;
 167        if (get_user(val, arg))
 168                return -EFAULT;
 169        if (val)
 170                set_bit(TTY_PTY_LOCK, &tty->flags);
 171        else
 172                clear_bit(TTY_PTY_LOCK, &tty->flags);
 173        return 0;
 174}
 175
 176/* Send a signal to the slave */
 177static int pty_signal(struct tty_struct *tty, int sig)
 178{
 179        unsigned long flags;
 180        struct pid *pgrp;
 181
 182        if (tty->link) {
 183                spin_lock_irqsave(&tty->link->ctrl_lock, flags);
 184                pgrp = get_pid(tty->link->pgrp);
 185                spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
 186
 187                kill_pgrp(pgrp, sig, 1);
 188                put_pid(pgrp);
 189        }
 190        return 0;
 191}
 192
 193static void pty_flush_buffer(struct tty_struct *tty)
 194{
 195        struct tty_struct *to = tty->link;
 196        unsigned long flags;
 197
 198        if (!to)
 199                return;
 200        /* tty_buffer_flush(to); FIXME */
 201        if (to->packet) {
 202                spin_lock_irqsave(&tty->ctrl_lock, flags);
 203                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
 204                wake_up_interruptible(&to->read_wait);
 205                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 206        }
 207}
 208
 209static int pty_open(struct tty_struct *tty, struct file *filp)
 210{
 211        int     retval = -ENODEV;
 212
 213        if (!tty || !tty->link)
 214                goto out;
 215
 216        retval = -EIO;
 217        if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 218                goto out;
 219        if (test_bit(TTY_PTY_LOCK, &tty->link->flags))
 220                goto out;
 221        if (tty->link->count != 1)
 222                goto out;
 223
 224        clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
 225        set_bit(TTY_THROTTLED, &tty->flags);
 226        retval = 0;
 227out:
 228        return retval;
 229}
 230
 231static void pty_set_termios(struct tty_struct *tty,
 232                                        struct ktermios *old_termios)
 233{
 234        tty->termios->c_cflag &= ~(CSIZE | PARENB);
 235        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
 244 *      peform a terminal resize correctly
 245 */
 246
 247int pty_resize(struct tty_struct *tty,  struct winsize *ws)
 248{
 249        struct pid *pgrp, *rpgrp;
 250        unsigned long flags;
 251        struct tty_struct *pty = tty->link;
 252
 253        /* For a PTY we need to lock the tty side */
 254        mutex_lock(&tty->termios_mutex);
 255        if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
 256                goto done;
 257
 258        /* Get the PID values and reference them so we can
 259           avoid holding the tty ctrl lock while sending signals.
 260           We need to lock these individually however. */
 261
 262        spin_lock_irqsave(&tty->ctrl_lock, flags);
 263        pgrp = get_pid(tty->pgrp);
 264        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 265
 266        spin_lock_irqsave(&pty->ctrl_lock, flags);
 267        rpgrp = get_pid(pty->pgrp);
 268        spin_unlock_irqrestore(&pty->ctrl_lock, flags);
 269
 270        if (pgrp)
 271                kill_pgrp(pgrp, SIGWINCH, 1);
 272        if (rpgrp != pgrp && rpgrp)
 273                kill_pgrp(rpgrp, SIGWINCH, 1);
 274
 275        put_pid(pgrp);
 276        put_pid(rpgrp);
 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
 285/* Traditional BSD devices */
 286#ifdef CONFIG_LEGACY_PTYS
 287
 288static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
 289{
 290        struct tty_struct *o_tty;
 291        int idx = tty->index;
 292        int retval;
 293
 294        o_tty = alloc_tty_struct();
 295        if (!o_tty)
 296                return -ENOMEM;
 297        if (!try_module_get(driver->other->owner)) {
 298                /* 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
 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;
 309
 310        retval = tty_init_termios(o_tty);
 311        if (retval)
 312                goto err_free_termios;
 313
 314        /*
 315         * Everything allocated ... set up the o_tty structure.
 316         */
 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;
 324
 325        tty_driver_kref_get(driver);
 326        tty->count++;
 327        driver->ttys[idx] = tty;
 328        return 0;
 329err_free_termios:
 330        tty_free_termios(tty);
 331err_deinit_tty:
 332        deinitialize_tty_struct(o_tty);
 333        module_put(o_tty->driver->owner);
 334err_free_tty:
 335        free_tty_struct(o_tty);
 336        return retval;
 337}
 338
 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);
 347        }
 348        return -ENOIOCTLCMD;
 349}
 350
 351static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
 352module_param(legacy_count, int, 0);
 353
 354/*
 355 * The master side of a pty can do TIOCSPTLCK and thus
 356 * has pty_bsd_ioctl.
 357 */
 358static const struct tty_operations master_pty_ops_bsd = {
 359        .install = pty_install,
 360        .open = pty_open,
 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,
 369        .resize = pty_resize
 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,
 382        .resize = pty_resize
 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;
 391
 392        pty_driver = alloc_tty_driver(legacy_count);
 393        if (!pty_driver)
 394                panic("Couldn't allocate pty driver");
 395
 396        pty_slave_driver = alloc_tty_driver(legacy_count);
 397        if (!pty_slave_driver)
 398                panic("Couldn't allocate pty slave driver");
 399
 400        pty_driver->driver_name = "pty_master";
 401        pty_driver->name = "pty";
 402        pty_driver->major = PTY_MASTER_MAJOR;
 403        pty_driver->minor_start = 0;
 404        pty_driver->type = TTY_DRIVER_TYPE_PTY;
 405        pty_driver->subtype = PTY_TYPE_MASTER;
 406        pty_driver->init_termios = tty_std_termios;
 407        pty_driver->init_termios.c_iflag = 0;
 408        pty_driver->init_termios.c_oflag = 0;
 409        pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 410        pty_driver->init_termios.c_lflag = 0;
 411        pty_driver->init_termios.c_ispeed = 38400;
 412        pty_driver->init_termios.c_ospeed = 38400;
 413        pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
 414        pty_driver->other = pty_slave_driver;
 415        tty_set_operations(pty_driver, &master_pty_ops_bsd);
 416
 417        pty_slave_driver->driver_name = "pty_slave";
 418        pty_slave_driver->name = "ttyp";
 419        pty_slave_driver->major = PTY_SLAVE_MAJOR;
 420        pty_slave_driver->minor_start = 0;
 421        pty_slave_driver->type = TTY_DRIVER_TYPE_PTY;
 422        pty_slave_driver->subtype = PTY_TYPE_SLAVE;
 423        pty_slave_driver->init_termios = tty_std_termios;
 424        pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 425        pty_slave_driver->init_termios.c_ispeed = 38400;
 426        pty_slave_driver->init_termios.c_ospeed = 38400;
 427        pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
 428                                        TTY_DRIVER_REAL_RAW;
 429        pty_slave_driver->other = pty_driver;
 430        tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
 431
 432        if (tty_register_driver(pty_driver))
 433                panic("Couldn't register pty driver");
 434        if (tty_register_driver(pty_slave_driver))
 435                panic("Couldn't register pty slave driver");
 436}
 437#else
 438static inline void legacy_pty_init(void) { }
 439#endif
 440
 441/* Unix98 devices */
 442#ifdef CONFIG_UNIX98_PTYS
 443
 444static struct cdev ptmx_cdev;
 445
 446static int pty_unix98_ioctl(struct tty_struct *tty,
 447                            unsigned int cmd, unsigned long arg)
 448{
 449        switch (cmd) {
 450        case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
 451                return pty_set_lock(tty, (int __user *)arg);
 452        case TIOCGPTN: /* Get PT Number */
 453                return put_user(tty->index, (unsigned int __user *)arg);
 454        case TIOCSIG:    /* Send signal to other side of pty */
 455                return pty_signal(tty, (int) arg);
 456        }
 457
 458        return -ENOIOCTLCMD;
 459}
 460
 461/**
 462 *      ptm_unix98_lookup       -       find a pty master
 463 *      @driver: ptm driver
 464 *      @idx: tty index
 465 *
 466 *      Look up a pty master device. Called under the tty_mutex for now.
 467 *      This provides our locking.
 468 */
 469
 470static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
 471                struct inode *ptm_inode, int idx)
 472{
 473        /* Master must be open via /dev/ptmx */
 474        return ERR_PTR(-EIO);
 475}
 476
 477/**
 478 *      pts_unix98_lookup       -       find a pty slave
 479 *      @driver: pts driver
 480 *      @idx: tty index
 481 *
 482 *      Look up a pty master device. Called under the tty_mutex for now.
 483 *      This provides our locking for the tty pointer.
 484 */
 485
 486static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 487                struct inode *pts_inode, int idx)
 488{
 489        struct tty_struct *tty;
 490
 491        mutex_lock(&devpts_mutex);
 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
 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{
 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;
 558}
 559
 560static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 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,
 571        .remove = ptm_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,
 581        .shutdown = pty_unix98_shutdown,
 582        .resize = pty_resize
 583};
 584
 585static const struct tty_operations pty_unix98_ops = {
 586        .lookup = pts_unix98_lookup,
 587        .install = pty_unix98_install,
 588        .remove = pts_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,
 597        .shutdown = pty_unix98_shutdown
 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.
 606 *
 607 *      Locking: tty_mutex protects the init_dev work. tty->count should
 608 *              protect the rest.
 609 *              allocated_ptys_lock handles the list of free pty numbers
 610 */
 611
 612static int ptmx_open(struct inode *inode, struct file *filp)
 613{
 614        struct tty_struct *tty;
 615        int retval;
 616        int index;
 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. */
 625        tty_lock();
 626        index = devpts_new_index(inode);
 627        tty_unlock();
 628        if (index < 0) {
 629                retval = index;
 630                goto err_file;
 631        }
 632
 633        mutex_lock(&tty_mutex);
 634        mutex_lock(&devpts_mutex);
 635        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
 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
 657        tty_unlock();
 658        return 0;
 659err_release:
 660        tty_unlock();
 661        tty_release(inode, filp);
 662        return retval;
 663out:
 664        devpts_kill_index(inode, index);
 665        tty_unlock();
 666err_file:
 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{
 675        ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 676        if (!ptm_driver)
 677                panic("Couldn't allocate Unix98 ptm driver");
 678        pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 679        if (!pts_driver)
 680                panic("Couldn't allocate Unix98 pts driver");
 681
 682        ptm_driver->driver_name = "pty_master";
 683        ptm_driver->name = "ptm";
 684        ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
 685        ptm_driver->minor_start = 0;
 686        ptm_driver->type = TTY_DRIVER_TYPE_PTY;
 687        ptm_driver->subtype = PTY_TYPE_MASTER;
 688        ptm_driver->init_termios = tty_std_termios;
 689        ptm_driver->init_termios.c_iflag = 0;
 690        ptm_driver->init_termios.c_oflag = 0;
 691        ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 692        ptm_driver->init_termios.c_lflag = 0;
 693        ptm_driver->init_termios.c_ispeed = 38400;
 694        ptm_driver->init_termios.c_ospeed = 38400;
 695        ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
 696                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
 697        ptm_driver->other = pts_driver;
 698        tty_set_operations(ptm_driver, &ptm_unix98_ops);
 699
 700        pts_driver->driver_name = "pty_slave";
 701        pts_driver->name = "pts";
 702        pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
 703        pts_driver->minor_start = 0;
 704        pts_driver->type = TTY_DRIVER_TYPE_PTY;
 705        pts_driver->subtype = PTY_TYPE_SLAVE;
 706        pts_driver->init_termios = tty_std_termios;
 707        pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 708        pts_driver->init_termios.c_ispeed = 38400;
 709        pts_driver->init_termios.c_ospeed = 38400;
 710        pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
 711                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
 712        pts_driver->other = ptm_driver;
 713        tty_set_operations(pts_driver, &pty_unix98_ops);
 714
 715        if (tty_register_driver(ptm_driver))
 716                panic("Couldn't register Unix98 ptm driver");
 717        if (tty_register_driver(pts_driver))
 718                panic("Couldn't register Unix98 pts driver");
 719
 720        /* Now create the /dev/ptmx special device */
 721        tty_default_fops(&ptmx_fops);
 722        ptmx_fops.open = ptmx_open;
 723
 724        cdev_init(&ptmx_cdev, &ptmx_fops);
 725        if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 726            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 727                panic("Couldn't register /dev/ptmx driver\n");
 728        device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 729}
 730
 731#else
 732static inline void unix98_pty_init(void) { }
 733#endif
 734
 735static int __init pty_init(void)
 736{
 737        legacy_pty_init();
 738        unix98_pty_init();
 739        return 0;
 740}
 741module_init(pty_init);
 742
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.