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 */
   8
   9#include <linux/module.h>
  10
  11#include <linux/errno.h>
  12#include <linux/interrupt.h>
  13#include <linux/tty.h>
  14#include <linux/tty_flip.h>
  15#include <linux/fcntl.h>
  16#include <linux/sched.h>
  17#include <linux/string.h>
  18#include <linux/major.h>
  19#include <linux/mm.h>
  20#include <linux/init.h>
  21#include <linux/device.h>
  22#include <linux/uaccess.h>
  23#include <linux/bitops.h>
  24#include <linux/devpts_fs.h>
  25#include <linux/slab.h>
  26#include <linux/mutex.h>
  27
  28
  29#ifdef CONFIG_UNIX98_PTYS
  30static struct tty_driver *ptm_driver;
  31static struct tty_driver *pts_driver;
  32static DEFINE_MUTEX(devpts_mutex);
  33#endif
  34
  35static void pty_close(struct tty_struct *tty, struct file *filp)
  36{
  37        BUG_ON(!tty);
  38        if (tty->driver->subtype == PTY_TYPE_MASTER)
  39                WARN_ON(tty->count > 1);
  40        else {
  41                if (tty->count > 2)
  42                        return;
  43        }
  44        wake_up_interruptible(&tty->read_wait);
  45        wake_up_interruptible(&tty->write_wait);
  46        tty->packet = 0;
  47        /* Review - krefs on tty_link ?? */
  48        if (!tty->link)
  49                return;
  50        tty->link->packet = 0;
  51        set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
  52        wake_up_interruptible(&tty->link->read_wait);
  53        wake_up_interruptible(&tty->link->write_wait);
  54        if (tty->driver->subtype == PTY_TYPE_MASTER) {
  55                set_bit(TTY_OTHER_CLOSED, &tty->flags);
  56#ifdef CONFIG_UNIX98_PTYS
  57                if (tty->driver == ptm_driver) {
  58                        mutex_lock(&devpts_mutex);
  59                        devpts_pty_kill(tty->link->driver_data);
  60                        mutex_unlock(&devpts_mutex);
  61                }
  62#endif
  63                tty_unlock(tty);
  64                tty_vhangup(tty->link);
  65                tty_lock(tty);
  66        }
  67}
  68
  69/*
  70 * The unthrottle routine is called by the line discipline to signal
  71 * that it can receive more characters.  For PTY's, the TTY_THROTTLED
  72 * flag is always set, to force the line discipline to always call the
  73 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
  74 * characters in the queue.  This is necessary since each time this
  75 * happens, we need to wake up any sleeping processes that could be
  76 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
  77 * for the pty buffer to be drained.
  78 */
  79static void pty_unthrottle(struct tty_struct *tty)
  80{
  81        tty_wakeup(tty->link);
  82        set_bit(TTY_THROTTLED, &tty->flags);
  83}
  84
  85/**
  86 *      pty_space       -       report space left for writing
  87 *      @to: tty we are writing into
  88 *
  89 *      The tty buffers allow 64K but we sneak a peak and clip at 8K this
  90 *      allows a lot of overspill room for echo and other fun messes to
  91 *      be handled properly
  92 */
  93
  94static int pty_space(struct tty_struct *to)
  95{
  96        int n = 8192 - to->port->buf.memory_used;
  97        if (n < 0)
  98                return 0;
  99        return n;
 100}
 101
 102/**
 103 *      pty_write               -       write to a pty
 104 *      @tty: the tty we write from
 105 *      @buf: kernel buffer of data
 106 *      @count: bytes to write
 107 *
 108 *      Our "hardware" write method. Data is coming from the ldisc which
 109 *      may be in a non sleeping state. We simply throw this at the other
 110 *      end of the link as if we were an IRQ handler receiving stuff for
 111 *      the other side of the pty/tty pair.
 112 */
 113
 114static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
 115{
 116        struct tty_struct *to = tty->link;
 117
 118        if (tty->stopped)
 119                return 0;
 120
 121        if (c > 0) {
 122                /* Stuff the data into the input queue of the other end */
 123                c = tty_insert_flip_string(to, buf, c);
 124                /* And shovel */
 125                if (c) {
 126                        tty_flip_buffer_push(to);
 127                        tty_wakeup(tty);
 128                }
 129        }
 130        return c;
 131}
 132
 133/**
 134 *      pty_write_room  -       write space
 135 *      @tty: tty we are writing from
 136 *
 137 *      Report how many bytes the ldisc can send into the queue for
 138 *      the other device.
 139 */
 140
 141static int pty_write_room(struct tty_struct *tty)
 142{
 143        if (tty->stopped)
 144                return 0;
 145        return pty_space(tty->link);
 146}
 147
 148/**
 149 *      pty_chars_in_buffer     -       characters currently in our tx queue
 150 *      @tty: our tty
 151 *
 152 *      Report how much we have in the transmit queue. As everything is
 153 *      instantly at the other end this is easy to implement.
 154 */
 155
 156static int pty_chars_in_buffer(struct tty_struct *tty)
 157{
 158        return 0;
 159}
 160
 161/* Set the lock flag on a pty */
 162static int pty_set_lock(struct tty_struct *tty, int __user *arg)
 163{
 164        int val;
 165        if (get_user(val, arg))
 166                return -EFAULT;
 167        if (val)
 168                set_bit(TTY_PTY_LOCK, &tty->flags);
 169        else
 170                clear_bit(TTY_PTY_LOCK, &tty->flags);
 171        return 0;
 172}
 173
 174static int pty_get_lock(struct tty_struct *tty, int __user *arg)
 175{
 176        int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
 177        return put_user(locked, arg);
 178}
 179
 180/* Set the packet mode on a pty */
 181static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
 182{
 183        unsigned long flags;
 184        int pktmode;
 185
 186        if (get_user(pktmode, arg))
 187                return -EFAULT;
 188
 189        spin_lock_irqsave(&tty->ctrl_lock, flags);
 190        if (pktmode) {
 191                if (!tty->packet) {
 192                        tty->packet = 1;
 193                        tty->link->ctrl_status = 0;
 194                }
 195        } else
 196                tty->packet = 0;
 197        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 198
 199        return 0;
 200}
 201
 202/* Get the packet mode of a pty */
 203static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
 204{
 205        int pktmode = tty->packet;
 206        return put_user(pktmode, arg);
 207}
 208
 209/* Send a signal to the slave */
 210static int pty_signal(struct tty_struct *tty, int sig)
 211{
 212        unsigned long flags;
 213        struct pid *pgrp;
 214
 215        if (tty->link) {
 216                spin_lock_irqsave(&tty->link->ctrl_lock, flags);
 217                pgrp = get_pid(tty->link->pgrp);
 218                spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
 219
 220                kill_pgrp(pgrp, sig, 1);
 221                put_pid(pgrp);
 222        }
 223        return 0;
 224}
 225
 226static void pty_flush_buffer(struct tty_struct *tty)
 227{
 228        struct tty_struct *to = tty->link;
 229        unsigned long flags;
 230
 231        if (!to)
 232                return;
 233        /* tty_buffer_flush(to); FIXME */
 234        if (to->packet) {
 235                spin_lock_irqsave(&tty->ctrl_lock, flags);
 236                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
 237                wake_up_interruptible(&to->read_wait);
 238                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 239        }
 240}
 241
 242static int pty_open(struct tty_struct *tty, struct file *filp)
 243{
 244        int     retval = -ENODEV;
 245
 246        if (!tty || !tty->link)
 247                goto out;
 248
 249        retval = -EIO;
 250        if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
 251                goto out;
 252        if (test_bit(TTY_PTY_LOCK, &tty->link->flags))
 253                goto out;
 254        if (tty->link->count != 1)
 255                goto out;
 256
 257        clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
 258        set_bit(TTY_THROTTLED, &tty->flags);
 259        retval = 0;
 260out:
 261        return retval;
 262}
 263
 264static void pty_set_termios(struct tty_struct *tty,
 265                                        struct ktermios *old_termios)
 266{
 267        tty->termios.c_cflag &= ~(CSIZE | PARENB);
 268        tty->termios.c_cflag |= (CS8 | CREAD);
 269}
 270
 271/**
 272 *      pty_do_resize           -       resize event
 273 *      @tty: tty being resized
 274 *      @ws: window size being set.
 275 *
 276 *      Update the termios variables and send the necessary signals to
 277 *      peform a terminal resize correctly
 278 */
 279
 280static int pty_resize(struct tty_struct *tty,  struct winsize *ws)
 281{
 282        struct pid *pgrp, *rpgrp;
 283        unsigned long flags;
 284        struct tty_struct *pty = tty->link;
 285
 286        /* For a PTY we need to lock the tty side */
 287        mutex_lock(&tty->termios_mutex);
 288        if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
 289                goto done;
 290
 291        /* Get the PID values and reference them so we can
 292           avoid holding the tty ctrl lock while sending signals.
 293           We need to lock these individually however. */
 294
 295        spin_lock_irqsave(&tty->ctrl_lock, flags);
 296        pgrp = get_pid(tty->pgrp);
 297        spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 298
 299        spin_lock_irqsave(&pty->ctrl_lock, flags);
 300        rpgrp = get_pid(pty->pgrp);
 301        spin_unlock_irqrestore(&pty->ctrl_lock, flags);
 302
 303        if (pgrp)
 304                kill_pgrp(pgrp, SIGWINCH, 1);
 305        if (rpgrp != pgrp && rpgrp)
 306                kill_pgrp(rpgrp, SIGWINCH, 1);
 307
 308        put_pid(pgrp);
 309        put_pid(rpgrp);
 310
 311        tty->winsize = *ws;
 312        pty->winsize = *ws;     /* Never used so will go away soon */
 313done:
 314        mutex_unlock(&tty->termios_mutex);
 315        return 0;
 316}
 317
 318/**
 319 *      pty_common_install              -       set up the pty pair
 320 *      @driver: the pty driver
 321 *      @tty: the tty being instantiated
 322 *      @bool: legacy, true if this is BSD style
 323 *
 324 *      Perform the initial set up for the tty/pty pair. Called from the
 325 *      tty layer when the port is first opened.
 326 *
 327 *      Locking: the caller must hold the tty_mutex
 328 */
 329static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
 330                bool legacy)
 331{
 332        struct tty_struct *o_tty;
 333        struct tty_port *ports[2];
 334        int idx = tty->index;
 335        int retval = -ENOMEM;
 336
 337        o_tty = alloc_tty_struct();
 338        if (!o_tty)
 339                goto err;
 340        ports[0] = kmalloc(sizeof **ports, GFP_KERNEL);
 341        ports[1] = kmalloc(sizeof **ports, GFP_KERNEL);
 342        if (!ports[0] || !ports[1])
 343                goto err_free_tty;
 344        if (!try_module_get(driver->other->owner)) {
 345                /* This cannot in fact currently happen */
 346                goto err_free_tty;
 347        }
 348        initialize_tty_struct(o_tty, driver->other, idx);
 349
 350        if (legacy) {
 351                /* We always use new tty termios data so we can do this
 352                   the easy way .. */
 353                retval = tty_init_termios(tty);
 354                if (retval)
 355                        goto err_deinit_tty;
 356
 357                retval = tty_init_termios(o_tty);
 358                if (retval)
 359                        goto err_free_termios;
 360
 361                driver->other->ttys[idx] = o_tty;
 362                driver->ttys[idx] = tty;
 363        } else {
 364                memset(&tty->termios_locked, 0, sizeof(tty->termios_locked));
 365                tty->termios = driver->init_termios;
 366                memset(&o_tty->termios_locked, 0, sizeof(tty->termios_locked));
 367                o_tty->termios = driver->other->init_termios;
 368        }
 369
 370        /*
 371         * Everything allocated ... set up the o_tty structure.
 372         */
 373        tty_driver_kref_get(driver->other);
 374        if (driver->subtype == PTY_TYPE_MASTER)
 375                o_tty->count++;
 376        /* Establish the links in both directions */
 377        tty->link   = o_tty;
 378        o_tty->link = tty;
 379        tty_port_init(ports[0]);
 380        tty_port_init(ports[1]);
 381        o_tty->port = ports[0];
 382        tty->port = ports[1];
 383        o_tty->port->itty = o_tty;
 384
 385        tty_driver_kref_get(driver);
 386        tty->count++;
 387        return 0;
 388err_free_termios:
 389        if (legacy)
 390                tty_free_termios(tty);
 391err_deinit_tty:
 392        deinitialize_tty_struct(o_tty);
 393        module_put(o_tty->driver->owner);
 394err_free_tty:
 395        kfree(ports[0]);
 396        kfree(ports[1]);
 397        free_tty_struct(o_tty);
 398err:
 399        return retval;
 400}
 401
 402/* this is called once with whichever end is closed last */
 403static void pty_unix98_shutdown(struct tty_struct *tty)
 404{
 405        devpts_kill_index(tty->driver_data, tty->index);
 406}
 407
 408static void pty_cleanup(struct tty_struct *tty)
 409{
 410        tty->port->itty = NULL;
 411        tty_port_put(tty->port);
 412}
 413
 414/* Traditional BSD devices */
 415#ifdef CONFIG_LEGACY_PTYS
 416
 417static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
 418{
 419        return pty_common_install(driver, tty, true);
 420}
 421
 422static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
 423{
 424        struct tty_struct *pair = tty->link;
 425        driver->ttys[tty->index] = NULL;
 426        if (pair)
 427                pair->driver->ttys[pair->index] = NULL;
 428}
 429
 430static int pty_bsd_ioctl(struct tty_struct *tty,
 431                         unsigned int cmd, unsigned long arg)
 432{
 433        switch (cmd) {
 434        case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
 435                return pty_set_lock(tty, (int __user *) arg);
 436        case TIOCGPTLCK: /* Get PT Lock status */
 437                return pty_get_lock(tty, (int __user *)arg);
 438        case TIOCPKT: /* Set PT packet mode */
 439                return pty_set_pktmode(tty, (int __user *)arg);
 440        case TIOCGPKT: /* Get PT packet mode */
 441                return pty_get_pktmode(tty, (int __user *)arg);
 442        case TIOCSIG:    /* Send signal to other side of pty */
 443                return pty_signal(tty, (int) arg);
 444        case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */
 445                return -EINVAL;
 446        }
 447        return -ENOIOCTLCMD;
 448}
 449
 450static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
 451module_param(legacy_count, int, 0);
 452
 453/*
 454 * The master side of a pty can do TIOCSPTLCK and thus
 455 * has pty_bsd_ioctl.
 456 */
 457static const struct tty_operations master_pty_ops_bsd = {
 458        .install = pty_install,
 459        .open = pty_open,
 460        .close = pty_close,
 461        .write = pty_write,
 462        .write_room = pty_write_room,
 463        .flush_buffer = pty_flush_buffer,
 464        .chars_in_buffer = pty_chars_in_buffer,
 465        .unthrottle = pty_unthrottle,
 466        .set_termios = pty_set_termios,
 467        .ioctl = pty_bsd_ioctl,
 468        .cleanup = pty_cleanup,
 469        .resize = pty_resize,
 470        .remove = pty_remove
 471};
 472
 473static const struct tty_operations slave_pty_ops_bsd = {
 474        .install = pty_install,
 475        .open = pty_open,
 476        .close = pty_close,
 477        .write = pty_write,
 478        .write_room = pty_write_room,
 479        .flush_buffer = pty_flush_buffer,
 480        .chars_in_buffer = pty_chars_in_buffer,
 481        .unthrottle = pty_unthrottle,
 482        .set_termios = pty_set_termios,
 483        .cleanup = pty_cleanup,
 484        .resize = pty_resize,
 485        .remove = pty_remove
 486};
 487
 488static void __init legacy_pty_init(void)
 489{
 490        struct tty_driver *pty_driver, *pty_slave_driver;
 491
 492        if (legacy_count <= 0)
 493                return;
 494
 495        pty_driver = tty_alloc_driver(legacy_count,
 496                        TTY_DRIVER_RESET_TERMIOS |
 497                        TTY_DRIVER_REAL_RAW |
 498                        TTY_DRIVER_DYNAMIC_ALLOC);
 499        if (IS_ERR(pty_driver))
 500                panic("Couldn't allocate pty driver");
 501
 502        pty_slave_driver = tty_alloc_driver(legacy_count,
 503                        TTY_DRIVER_RESET_TERMIOS |
 504                        TTY_DRIVER_REAL_RAW |
 505                        TTY_DRIVER_DYNAMIC_ALLOC);
 506        if (IS_ERR(pty_slave_driver))
 507                panic("Couldn't allocate pty slave driver");
 508
 509        pty_driver->driver_name = "pty_master";
 510        pty_driver->name = "pty";
 511        pty_driver->major = PTY_MASTER_MAJOR;
 512        pty_driver->minor_start = 0;
 513        pty_driver->type = TTY_DRIVER_TYPE_PTY;
 514        pty_driver->subtype = PTY_TYPE_MASTER;
 515        pty_driver->init_termios = tty_std_termios;
 516        pty_driver->init_termios.c_iflag = 0;
 517        pty_driver->init_termios.c_oflag = 0;
 518        pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 519        pty_driver->init_termios.c_lflag = 0;
 520        pty_driver->init_termios.c_ispeed = 38400;
 521        pty_driver->init_termios.c_ospeed = 38400;
 522        pty_driver->other = pty_slave_driver;
 523        tty_set_operations(pty_driver, &master_pty_ops_bsd);
 524
 525        pty_slave_driver->driver_name = "pty_slave";
 526        pty_slave_driver->name = "ttyp";
 527        pty_slave_driver->major = PTY_SLAVE_MAJOR;
 528        pty_slave_driver->minor_start = 0;
 529        pty_slave_driver->type = TTY_DRIVER_TYPE_PTY;
 530        pty_slave_driver->subtype = PTY_TYPE_SLAVE;
 531        pty_slave_driver->init_termios = tty_std_termios;
 532        pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 533        pty_slave_driver->init_termios.c_ispeed = 38400;
 534        pty_slave_driver->init_termios.c_ospeed = 38400;
 535        pty_slave_driver->other = pty_driver;
 536        tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
 537
 538        if (tty_register_driver(pty_driver))
 539                panic("Couldn't register pty driver");
 540        if (tty_register_driver(pty_slave_driver))
 541                panic("Couldn't register pty slave driver");
 542}
 543#else
 544static inline void legacy_pty_init(void) { }
 545#endif
 546
 547/* Unix98 devices */
 548#ifdef CONFIG_UNIX98_PTYS
 549
 550static struct cdev ptmx_cdev;
 551
 552static int pty_unix98_ioctl(struct tty_struct *tty,
 553                            unsigned int cmd, unsigned long arg)
 554{
 555        switch (cmd) {
 556        case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
 557                return pty_set_lock(tty, (int __user *)arg);
 558        case TIOCGPTLCK: /* Get PT Lock status */
 559                return pty_get_lock(tty, (int __user *)arg);
 560        case TIOCPKT: /* Set PT packet mode */
 561                return pty_set_pktmode(tty, (int __user *)arg);
 562        case TIOCGPKT: /* Get PT packet mode */
 563                return pty_get_pktmode(tty, (int __user *)arg);
 564        case TIOCGPTN: /* Get PT Number */
 565                return put_user(tty->index, (unsigned int __user *)arg);
 566        case TIOCSIG:    /* Send signal to other side of pty */
 567                return pty_signal(tty, (int) arg);
 568        }
 569
 570        return -ENOIOCTLCMD;
 571}
 572
 573/**
 574 *      ptm_unix98_lookup       -       find a pty master
 575 *      @driver: ptm driver
 576 *      @idx: tty index
 577 *
 578 *      Look up a pty master device. Called under the tty_mutex for now.
 579 *      This provides our locking.
 580 */
 581
 582static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
 583                struct inode *ptm_inode, int idx)
 584{
 585        /* Master must be open via /dev/ptmx */
 586        return ERR_PTR(-EIO);
 587}
 588
 589/**
 590 *      pts_unix98_lookup       -       find a pty slave
 591 *      @driver: pts driver
 592 *      @idx: tty index
 593 *
 594 *      Look up a pty master device. Called under the tty_mutex for now.
 595 *      This provides our locking for the tty pointer.
 596 */
 597
 598static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 599                struct inode *pts_inode, int idx)
 600{
 601        struct tty_struct *tty;
 602
 603        mutex_lock(&devpts_mutex);
 604        tty = devpts_get_priv(pts_inode);
 605        mutex_unlock(&devpts_mutex);
 606        /* Master must be open before slave */
 607        if (!tty)
 608                return ERR_PTR(-EIO);
 609        return tty;
 610}
 611
 612/* We have no need to install and remove our tty objects as devpts does all
 613   the work for us */
 614
 615static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
 616{
 617        return pty_common_install(driver, tty, false);
 618}
 619
 620static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
 621{
 622}
 623
 624static const struct tty_operations ptm_unix98_ops = {
 625        .lookup = ptm_unix98_lookup,
 626        .install = pty_unix98_install,
 627        .remove = pty_unix98_remove,
 628        .open = pty_open,
 629        .close = pty_close,
 630        .write = pty_write,
 631        .write_room = pty_write_room,
 632        .flush_buffer = pty_flush_buffer,
 633        .chars_in_buffer = pty_chars_in_buffer,
 634        .unthrottle = pty_unthrottle,
 635        .set_termios = pty_set_termios,
 636        .ioctl = pty_unix98_ioctl,
 637        .resize = pty_resize,
 638        .shutdown = pty_unix98_shutdown,
 639        .cleanup = pty_cleanup
 640};
 641
 642static const struct tty_operations pty_unix98_ops = {
 643        .lookup = pts_unix98_lookup,
 644        .install = pty_unix98_install,
 645        .remove = pty_unix98_remove,
 646        .open = pty_open,
 647        .close = pty_close,
 648        .write = pty_write,
 649        .write_room = pty_write_room,
 650        .flush_buffer = pty_flush_buffer,
 651        .chars_in_buffer = pty_chars_in_buffer,
 652        .unthrottle = pty_unthrottle,
 653        .set_termios = pty_set_termios,
 654        .shutdown = pty_unix98_shutdown,
 655        .cleanup = pty_cleanup,
 656};
 657
 658/**
 659 *      ptmx_open               -       open a unix 98 pty master
 660 *      @inode: inode of device file
 661 *      @filp: file pointer to tty
 662 *
 663 *      Allocate a unix98 pty master device from the ptmx driver.
 664 *
 665 *      Locking: tty_mutex protects the init_dev work. tty->count should
 666 *              protect the rest.
 667 *              allocated_ptys_lock handles the list of free pty numbers
 668 */
 669
 670static int ptmx_open(struct inode *inode, struct file *filp)
 671{
 672        struct tty_struct *tty;
 673        struct inode *slave_inode;
 674        int retval;
 675        int index;
 676
 677        nonseekable_open(inode, filp);
 678
 679        retval = tty_alloc_file(filp);
 680        if (retval)
 681                return retval;
 682
 683        /* find a device that is not in use. */
 684        mutex_lock(&devpts_mutex);
 685        index = devpts_new_index(inode);
 686        if (index < 0) {
 687                retval = index;
 688                mutex_unlock(&devpts_mutex);
 689                goto err_file;
 690        }
 691
 692        mutex_unlock(&devpts_mutex);
 693
 694        mutex_lock(&tty_mutex);
 695        tty = tty_init_dev(ptm_driver, index);
 696
 697        if (IS_ERR(tty)) {
 698                retval = PTR_ERR(tty);
 699                goto out;
 700        }
 701
 702        /* The tty returned here is locked so we can safely
 703           drop the mutex */
 704        mutex_unlock(&tty_mutex);
 705
 706        set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 707
 708        tty_add_file(tty, filp);
 709
 710        slave_inode = devpts_pty_new(inode,
 711                        MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
 712                        tty->link);
 713        if (IS_ERR(slave_inode)) {
 714                retval = PTR_ERR(slave_inode);
 715                goto err_release;
 716        }
 717
 718        retval = ptm_driver->ops->open(tty, filp);
 719        if (retval)
 720                goto err_release;
 721
 722        tty_unlock(tty);
 723        tty->driver_data = inode;
 724        tty->link->driver_data = slave_inode;
 725        return 0;
 726err_release:
 727        tty_unlock(tty);
 728        tty_release(inode, filp);
 729        return retval;
 730out:
 731        mutex_unlock(&tty_mutex);
 732        devpts_kill_index(inode, index);
 733err_file:
 734        tty_free_file(filp);
 735        return retval;
 736}
 737
 738static struct file_operations ptmx_fops;
 739
 740static void __init unix98_pty_init(void)
 741{
 742        ptm_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
 743                        TTY_DRIVER_RESET_TERMIOS |
 744                        TTY_DRIVER_REAL_RAW |
 745                        TTY_DRIVER_DYNAMIC_DEV |
 746                        TTY_DRIVER_DEVPTS_MEM |
 747                        TTY_DRIVER_DYNAMIC_ALLOC);
 748        if (IS_ERR(ptm_driver))
 749                panic("Couldn't allocate Unix98 ptm driver");
 750        pts_driver = tty_alloc_driver(NR_UNIX98_PTY_MAX,
 751                        TTY_DRIVER_RESET_TERMIOS |
 752                        TTY_DRIVER_REAL_RAW |
 753                        TTY_DRIVER_DYNAMIC_DEV |
 754                        TTY_DRIVER_DEVPTS_MEM |
 755                        TTY_DRIVER_DYNAMIC_ALLOC);
 756        if (IS_ERR(pts_driver))
 757                panic("Couldn't allocate Unix98 pts driver");
 758
 759        ptm_driver->driver_name = "pty_master";
 760        ptm_driver->name = "ptm";
 761        ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
 762        ptm_driver->minor_start = 0;
 763        ptm_driver->type = TTY_DRIVER_TYPE_PTY;
 764        ptm_driver->subtype = PTY_TYPE_MASTER;
 765        ptm_driver->init_termios = tty_std_termios;
 766        ptm_driver->init_termios.c_iflag = 0;
 767        ptm_driver->init_termios.c_oflag = 0;
 768        ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 769        ptm_driver->init_termios.c_lflag = 0;
 770        ptm_driver->init_termios.c_ispeed = 38400;
 771        ptm_driver->init_termios.c_ospeed = 38400;
 772        ptm_driver->other = pts_driver;
 773        tty_set_operations(ptm_driver, &ptm_unix98_ops);
 774
 775        pts_driver->driver_name = "pty_slave";
 776        pts_driver->name = "pts";
 777        pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
 778        pts_driver->minor_start = 0;
 779        pts_driver->type = TTY_DRIVER_TYPE_PTY;
 780        pts_driver->subtype = PTY_TYPE_SLAVE;
 781        pts_driver->init_termios = tty_std_termios;
 782        pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
 783        pts_driver->init_termios.c_ispeed = 38400;
 784        pts_driver->init_termios.c_ospeed = 38400;
 785        pts_driver->other = ptm_driver;
 786        tty_set_operations(pts_driver, &pty_unix98_ops);
 787
 788        if (tty_register_driver(ptm_driver))
 789                panic("Couldn't register Unix98 ptm driver");
 790        if (tty_register_driver(pts_driver))
 791                panic("Couldn't register Unix98 pts driver");
 792
 793        /* Now create the /dev/ptmx special device */
 794        tty_default_fops(&ptmx_fops);
 795        ptmx_fops.open = ptmx_open;
 796
 797        cdev_init(&ptmx_cdev, &ptmx_fops);
 798        if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 799            register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 800                panic("Couldn't register /dev/ptmx driver\n");
 801        device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 802}
 803
 804#else
 805static inline void unix98_pty_init(void) { }
 806#endif
 807
 808static int __init pty_init(void)
 809{
 810        legacy_pty_init();
 811        unix98_pty_init();
 812        return 0;
 813}
 814module_init(pty_init);
 815
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.