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 ---