pty.c 18.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10
/*
 *  linux/drivers/char/pty.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  Added support for a Unix98-style ptmx device.
 *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
 *  Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
 *      waiting writers -- Sapan Bhatia <sapan@corewars.org>
 *
A
Alan Cox 已提交
11 12 13
 *  When reading this code see also fs/devpts. In particular note that the
 *  driver_data field is used by the devpts side as a binding to the devpts
 *  inode.
L
Linus Torvalds 已提交
14 15
 */

A
Alan Cox 已提交
16
#include <linux/module.h>
L
Linus Torvalds 已提交
17 18 19 20 21 22 23 24 25 26 27

#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/sysctl.h>
28
#include <linux/device.h>
A
Alan Cox 已提交
29
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
30 31 32
#include <linux/bitops.h>
#include <linux/devpts_fs.h>

A
Alan Cox 已提交
33 34
#include <asm/system.h>

L
Linus Torvalds 已提交
35 36 37 38 39 40
/* These are global because they are accessed in tty_io.c */
#ifdef CONFIG_UNIX98_PTYS
struct tty_driver *ptm_driver;
static struct tty_driver *pts_driver;
#endif

A
Alan Cox 已提交
41
static void pty_close(struct tty_struct *tty, struct file *filp)
L
Linus Torvalds 已提交
42
{
A
Alan Cox 已提交
43 44 45 46
	BUG_ON(!tty);
	if (tty->driver->subtype == PTY_TYPE_MASTER)
		WARN_ON(tty->count > 1);
	else {
L
Linus Torvalds 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
		if (tty->count > 2)
			return;
	}
	wake_up_interruptible(&tty->read_wait);
	wake_up_interruptible(&tty->write_wait);
	tty->packet = 0;
	if (!tty->link)
		return;
	tty->link->packet = 0;
	set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
	wake_up_interruptible(&tty->link->read_wait);
	wake_up_interruptible(&tty->link->write_wait);
	if (tty->driver->subtype == PTY_TYPE_MASTER) {
		set_bit(TTY_OTHER_CLOSED, &tty->flags);
#ifdef CONFIG_UNIX98_PTYS
		if (tty->driver == ptm_driver)
63
			devpts_pty_kill(tty->link);
L
Linus Torvalds 已提交
64 65 66 67 68 69 70 71 72
#endif
		tty_vhangup(tty->link);
	}
}

/*
 * The unthrottle routine is called by the line discipline to signal
 * that it can receive more characters.  For PTY's, the TTY_THROTTLED
 * flag is always set, to force the line discipline to always call the
A
Alan Cox 已提交
73
 * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
L
Linus Torvalds 已提交
74 75 76 77 78
 * characters in the queue.  This is necessary since each time this
 * happens, we need to wake up any sleeping processes that could be
 * (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
 * for the pty buffer to be drained.
 */
A
Alan Cox 已提交
79
static void pty_unthrottle(struct tty_struct *tty)
L
Linus Torvalds 已提交
80 81 82 83 84 85 86 87 88 89 90
{
	struct tty_struct *o_tty = tty->link;

	if (!o_tty)
		return;

	tty_wakeup(o_tty);
	set_bit(TTY_THROTTLED, &tty->flags);
}

/*
A
Alan Cox 已提交
91
 * WSH 05/24/97: modified to
L
Linus Torvalds 已提交
92 93 94 95 96 97 98 99 100 101
 *   (1) use space in tty->flip instead of a shared temp buffer
 *	 The flip buffers aren't being used for a pty, so there's lots
 *	 of space available.  The buffer is protected by a per-pty
 *	 semaphore that should almost never come under contention.
 *   (2) avoid redundant copying for cases where count >> receive_room
 * N.B. Calls from user space may now return an error code instead of
 * a count.
 *
 * FIXME: Our pty_write method is called with our ldisc lock held but
 * not our partners. We can't just take the other one blindly without
P
Paul Fulghum 已提交
102
 * risking deadlocks.
L
Linus Torvalds 已提交
103
 */
A
Alan Cox 已提交
104 105
static int pty_write(struct tty_struct *tty, const unsigned char *buf,
								int count)
L
Linus Torvalds 已提交
106 107 108 109 110 111 112
{
	struct tty_struct *to = tty->link;
	int	c;

	if (!to || tty->stopped)
		return 0;

A
Alan Cox 已提交
113
	c = to->receive_room;
L
Linus Torvalds 已提交
114 115
	if (c > count)
		c = count;
A
Alan Cox 已提交
116
	to->ldisc.ops->receive_buf(to, buf, NULL, c);
A
Alan Cox 已提交
117

L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125 126 127
	return c;
}

static int pty_write_room(struct tty_struct *tty)
{
	struct tty_struct *to = tty->link;

	if (!to || tty->stopped)
		return 0;

A
Alan Cox 已提交
128
	return to->receive_room;
L
Linus Torvalds 已提交
129 130 131 132
}

/*
 *	WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
A
Alan Cox 已提交
133
 *	The chars_in_buffer() value is used by the ldisc select() function
L
Linus Torvalds 已提交
134 135 136 137 138 139
 *	to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
 *	The pty driver chars_in_buffer() Master/Slave must behave differently:
 *
 *      The Master side needs to allow typed-ahead commands to accumulate
 *      while being canonicalized, so we report "our buffer" as empty until
 *	some threshold is reached, and then report the count. (Any count >
A
Alan Cox 已提交
140 141
 *	WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock
 *	the count returned must be 0 if no canonical data is available to be
L
Linus Torvalds 已提交
142
 *	read. (The N_TTY ldisc.chars_in_buffer now knows this.)
A
Alan Cox 已提交
143
 *
L
Linus Torvalds 已提交
144 145 146 147 148 149 150 151 152 153
 *	The Slave side passes all characters in raw mode to the Master side's
 *	buffer where they can be read immediately, so in this case we can
 *	return the true count in the buffer.
 */
static int pty_chars_in_buffer(struct tty_struct *tty)
{
	struct tty_struct *to = tty->link;
	int count;

	/* We should get the line discipline lock for "tty->link" */
A
Alan Cox 已提交
154
	if (!to || !to->ldisc.ops->chars_in_buffer)
L
Linus Torvalds 已提交
155 156 157
		return 0;

	/* The ldisc must report 0 if no characters available to be read */
A
Alan Cox 已提交
158
	count = to->ldisc.ops->chars_in_buffer(to);
L
Linus Torvalds 已提交
159

A
Alan Cox 已提交
160 161
	if (tty->driver->subtype == PTY_TYPE_SLAVE)
		return count;
L
Linus Torvalds 已提交
162

A
Alan Cox 已提交
163
	/* Master side driver ... if the other side's read buffer is less than
L
Linus Torvalds 已提交
164
	 * half full, return 0 to allow writers to proceed; otherwise return
A
Alan Cox 已提交
165
	 * the count.  This leaves a comfortable margin to avoid overflow,
L
Linus Torvalds 已提交
166 167
	 * and still allows half a buffer's worth of typed-ahead commands.
	 */
A
Alan Cox 已提交
168
	return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
L
Linus Torvalds 已提交
169 170 171
}

/* Set the lock flag on a pty */
A
Alan Cox 已提交
172
static int pty_set_lock(struct tty_struct *tty, int __user *arg)
L
Linus Torvalds 已提交
173 174
{
	int val;
A
Alan Cox 已提交
175
	if (get_user(val, arg))
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184 185 186
		return -EFAULT;
	if (val)
		set_bit(TTY_PTY_LOCK, &tty->flags);
	else
		clear_bit(TTY_PTY_LOCK, &tty->flags);
	return 0;
}

static void pty_flush_buffer(struct tty_struct *tty)
{
	struct tty_struct *to = tty->link;
A
Alan Cox 已提交
187
	unsigned long flags;
A
Alan Cox 已提交
188

L
Linus Torvalds 已提交
189 190
	if (!to)
		return;
A
Alan Cox 已提交
191

A
Alan Cox 已提交
192 193
	if (to->ldisc.ops->flush_buffer)
		to->ldisc.ops->flush_buffer(to);
A
Alan Cox 已提交
194

L
Linus Torvalds 已提交
195
	if (to->packet) {
A
Alan Cox 已提交
196
		spin_lock_irqsave(&tty->ctrl_lock, flags);
L
Linus Torvalds 已提交
197 198
		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
		wake_up_interruptible(&to->read_wait);
A
Alan Cox 已提交
199
		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
L
Linus Torvalds 已提交
200 201 202
	}
}

A
Alan Cox 已提交
203
static int pty_open(struct tty_struct *tty, struct file *filp)
L
Linus Torvalds 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
{
	int	retval = -ENODEV;

	if (!tty || !tty->link)
		goto out;

	retval = -EIO;
	if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
		goto out;
	if (test_bit(TTY_PTY_LOCK, &tty->link->flags))
		goto out;
	if (tty->link->count != 1)
		goto out;

	clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
	set_bit(TTY_THROTTLED, &tty->flags);
	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
	retval = 0;
out:
	return retval;
}

A
Alan Cox 已提交
226 227
static void pty_set_termios(struct tty_struct *tty,
					struct ktermios *old_termios)
L
Linus Torvalds 已提交
228
{
A
Alan Cox 已提交
229 230
	tty->termios->c_cflag &= ~(CSIZE | PARENB);
	tty->termios->c_cflag |= (CS8 | CREAD);
L
Linus Torvalds 已提交
231 232
}

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{
	struct tty_struct *o_tty;
	int idx = tty->index;
	int retval;

	o_tty = alloc_tty_struct();
	if (!o_tty)
		return -ENOMEM;
	if (!try_module_get(driver->other->owner)) {
		/* This cannot in fact currently happen */
		free_tty_struct(o_tty);
		return -ENOMEM;
	}
	initialize_tty_struct(o_tty, driver->other, idx);

	/* We always use new tty termios data so we can do this
	   the easy way .. */
	retval = tty_init_termios(tty);
	if (retval)
		goto free_mem_out;

	retval = tty_init_termios(o_tty);
	if (retval) {
		tty_free_termios(tty);
		goto free_mem_out;
	}
A
Alan Cox 已提交
260

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
	/*
	 * Everything allocated ... set up the o_tty structure.
	 */
	driver->other->ttys[idx] = o_tty;
	tty_driver_kref_get(driver->other);
	if (driver->subtype == PTY_TYPE_MASTER)
		o_tty->count++;
	/* Establish the links in both directions */
	tty->link   = o_tty;
	o_tty->link = tty;

	tty_driver_kref_get(driver);
	tty->count++;
	driver->ttys[idx] = tty;
	return 0;
free_mem_out:
	module_put(o_tty->driver->owner);
	free_tty_struct(o_tty);
	return -ENOMEM;
}


J
Jeff Dike 已提交
283
static const struct tty_operations pty_ops = {
284
	.install = pty_install,
L
Linus Torvalds 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
	.open = pty_open,
	.close = pty_close,
	.write = pty_write,
	.write_room = pty_write_room,
	.flush_buffer = pty_flush_buffer,
	.chars_in_buffer = pty_chars_in_buffer,
	.unthrottle = pty_unthrottle,
	.set_termios = pty_set_termios,
};

/* Traditional BSD devices */
#ifdef CONFIG_LEGACY_PTYS
static struct tty_driver *pty_driver, *pty_slave_driver;

static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
			 unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
		return pty_set_lock(tty, (int __user *) arg);
	}
	return -ENOIOCTLCMD;
}

309 310 311
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
module_param(legacy_count, int, 0);

A
Alan Cox 已提交
312 313 314 315 316 317 318 319 320 321 322 323
static const struct tty_operations pty_ops_bsd = {
	.open = pty_open,
	.close = pty_close,
	.write = pty_write,
	.write_room = pty_write_room,
	.flush_buffer = pty_flush_buffer,
	.chars_in_buffer = pty_chars_in_buffer,
	.unthrottle = pty_unthrottle,
	.set_termios = pty_set_termios,
	.ioctl = pty_bsd_ioctl,
};

L
Linus Torvalds 已提交
324 325
static void __init legacy_pty_init(void)
{
326 327
	if (legacy_count <= 0)
		return;
L
Linus Torvalds 已提交
328

329
	pty_driver = alloc_tty_driver(legacy_count);
L
Linus Torvalds 已提交
330 331 332
	if (!pty_driver)
		panic("Couldn't allocate pty driver");

333
	pty_slave_driver = alloc_tty_driver(legacy_count);
L
Linus Torvalds 已提交
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
	if (!pty_slave_driver)
		panic("Couldn't allocate pty slave driver");

	pty_driver->owner = THIS_MODULE;
	pty_driver->driver_name = "pty_master";
	pty_driver->name = "pty";
	pty_driver->major = PTY_MASTER_MAJOR;
	pty_driver->minor_start = 0;
	pty_driver->type = TTY_DRIVER_TYPE_PTY;
	pty_driver->subtype = PTY_TYPE_MASTER;
	pty_driver->init_termios = tty_std_termios;
	pty_driver->init_termios.c_iflag = 0;
	pty_driver->init_termios.c_oflag = 0;
	pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
	pty_driver->init_termios.c_lflag = 0;
A
Alan Cox 已提交
349 350
	pty_driver->init_termios.c_ispeed = 38400;
	pty_driver->init_termios.c_ospeed = 38400;
L
Linus Torvalds 已提交
351 352 353 354 355 356 357 358 359 360 361 362 363
	pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
	pty_driver->other = pty_slave_driver;
	tty_set_operations(pty_driver, &pty_ops);

	pty_slave_driver->owner = THIS_MODULE;
	pty_slave_driver->driver_name = "pty_slave";
	pty_slave_driver->name = "ttyp";
	pty_slave_driver->major = PTY_SLAVE_MAJOR;
	pty_slave_driver->minor_start = 0;
	pty_slave_driver->type = TTY_DRIVER_TYPE_PTY;
	pty_slave_driver->subtype = PTY_TYPE_SLAVE;
	pty_slave_driver->init_termios = tty_std_termios;
	pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
A
Alan Cox 已提交
364 365
	pty_slave_driver->init_termios.c_ispeed = 38400;
	pty_slave_driver->init_termios.c_ospeed = 38400;
L
Linus Torvalds 已提交
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
	pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
					TTY_DRIVER_REAL_RAW;
	pty_slave_driver->other = pty_driver;
	tty_set_operations(pty_slave_driver, &pty_ops);

	if (tty_register_driver(pty_driver))
		panic("Couldn't register pty driver");
	if (tty_register_driver(pty_slave_driver))
		panic("Couldn't register pty slave driver");
}
#else
static inline void legacy_pty_init(void) { }
#endif

/* Unix98 devices */
#ifdef CONFIG_UNIX98_PTYS
/*
 * sysctl support for setting limits on the number of Unix98 ptys allocated.
 * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
 */
int pty_limit = NR_UNIX98_PTY_DEFAULT;
A
Alan Cox 已提交
387
static int pty_limit_min;
L
Linus Torvalds 已提交
388
static int pty_limit_max = NR_UNIX98_PTY_MAX;
A
Alan Cox 已提交
389
static int pty_count;
L
Linus Torvalds 已提交
390

391 392
static struct cdev ptmx_cdev;

393
static struct ctl_table pty_table[] = {
L
Linus Torvalds 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
	{
		.ctl_name	= PTY_MAX,
		.procname	= "max",
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.data		= &pty_limit,
		.proc_handler	= &proc_dointvec_minmax,
		.strategy	= &sysctl_intvec,
		.extra1		= &pty_limit_min,
		.extra2		= &pty_limit_max,
	}, {
		.ctl_name	= PTY_NR,
		.procname	= "nr",
		.maxlen		= sizeof(int),
		.mode		= 0444,
409
		.data		= &pty_count,
L
Linus Torvalds 已提交
410 411 412 413 414 415
		.proc_handler	= &proc_dointvec,
	}, {
		.ctl_name	= 0
	}
};

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
static struct ctl_table pty_kern_table[] = {
	{
		.ctl_name	= KERN_PTY,
		.procname	= "pty",
		.mode		= 0555,
		.child		= pty_table,
	},
	{}
};

static struct ctl_table pty_root_table[] = {
	{
		.ctl_name	= CTL_KERN,
		.procname	= "kernel",
		.mode		= 0555,
		.child		= pty_kern_table,
	},
	{}
};


L
Linus Torvalds 已提交
437 438 439 440 441 442 443 444 445 446 447 448 449
static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
			    unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
		return pty_set_lock(tty, (int __user *)arg);
	case TIOCGPTN: /* Get PT Number */
		return put_user(tty->index, (unsigned int __user *)arg);
	}

	return -ENOIOCTLCMD;
}

450 451 452 453 454 455 456 457 458
/**
 *	ptm_unix98_lookup	-	find a pty master
 *	@driver: ptm driver
 *	@idx: tty index
 *
 *	Look up a pty master device. Called under the tty_mutex for now.
 *	This provides our locking.
 */

459 460
static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
		struct inode *ptm_inode, int idx)
461
{
462
	struct tty_struct *tty = devpts_get_tty(ptm_inode, idx);
463 464 465 466 467 468 469 470 471 472 473 474 475 476
	if (tty)
		tty = tty->link;
	return tty;
}

/**
 *	pts_unix98_lookup	-	find a pty slave
 *	@driver: pts driver
 *	@idx: tty index
 *
 *	Look up a pty master device. Called under the tty_mutex for now.
 *	This provides our locking.
 */

477 478
static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
		struct inode *pts_inode, int idx)
479
{
480
	struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
481 482 483 484 485 486
	/* Master must be open before slave */
	if (!tty)
		return ERR_PTR(-EIO);
	return tty;
}

487
static void pty_unix98_shutdown(struct tty_struct *tty)
A
Alan Cox 已提交
488 489 490 491 492
{
	/* We have our own method as we don't use the tty index */
	kfree(tty->termios);
}

A
Alan Cox 已提交
493 494 495
/* We have no need to install and remove our tty objects as devpts does all
   the work for us */

496
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
A
Alan Cox 已提交
497
{
498 499 500 501 502 503 504 505 506 507 508 509 510
	struct tty_struct *o_tty;
	int idx = tty->index;

	o_tty = alloc_tty_struct();
	if (!o_tty)
		return -ENOMEM;
	if (!try_module_get(driver->other->owner)) {
		/* This cannot in fact currently happen */
		free_tty_struct(o_tty);
		return -ENOMEM;
	}
	initialize_tty_struct(o_tty, driver->other, idx);

A
Alan Cox 已提交
511
	tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
512 513 514
	if (tty->termios == NULL)
		goto free_mem_out;
	*tty->termios = driver->init_termios;
A
Alan Cox 已提交
515 516 517
	tty->termios_locked = tty->termios + 1;

	o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
518 519 520
	if (o_tty->termios == NULL)
		goto free_mem_out;
	*o_tty->termios = driver->other->init_termios;
A
Alan Cox 已提交
521
	o_tty->termios_locked = o_tty->termios + 1;
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536

	tty_driver_kref_get(driver->other);
	if (driver->subtype == PTY_TYPE_MASTER)
		o_tty->count++;
	/* Establish the links in both directions */
	tty->link   = o_tty;
	o_tty->link = tty;
	/*
	 * All structures have been allocated, so now we install them.
	 * Failures after this point use release_tty to clean up, so
	 * there's no need to null out the local pointers.
	 */
	tty_driver_kref_get(driver);
	tty->count++;
	pty_count++;
A
Alan Cox 已提交
537
	return 0;
538
free_mem_out:
A
Alan Cox 已提交
539
	kfree(o_tty->termios);
540 541
	module_put(o_tty->driver->owner);
	free_tty_struct(o_tty);
A
Alan Cox 已提交
542
	kfree(tty->termios);
543
	return -ENOMEM;
A
Alan Cox 已提交
544 545
}

546
static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
A
Alan Cox 已提交
547
{
548
	pty_count--;
A
Alan Cox 已提交
549 550
}

A
Alan Cox 已提交
551
static const struct tty_operations ptm_unix98_ops = {
552
	.lookup = ptm_unix98_lookup,
553 554
	.install = pty_unix98_install,
	.remove = pty_unix98_remove,
A
Alan Cox 已提交
555 556 557 558 559 560 561 562
	.open = pty_open,
	.close = pty_close,
	.write = pty_write,
	.write_room = pty_write_room,
	.flush_buffer = pty_flush_buffer,
	.chars_in_buffer = pty_chars_in_buffer,
	.unthrottle = pty_unthrottle,
	.set_termios = pty_set_termios,
A
Alan Cox 已提交
563
	.ioctl = pty_unix98_ioctl,
564
	.shutdown = pty_unix98_shutdown
A
Alan Cox 已提交
565 566
};

567 568
static const struct tty_operations pty_unix98_ops = {
	.lookup = pts_unix98_lookup,
569 570
	.install = pty_unix98_install,
	.remove = pty_unix98_remove,
571 572 573 574 575 576 577 578
	.open = pty_open,
	.close = pty_close,
	.write = pty_write,
	.write_room = pty_write_room,
	.flush_buffer = pty_flush_buffer,
	.chars_in_buffer = pty_chars_in_buffer,
	.unthrottle = pty_unthrottle,
	.set_termios = pty_set_termios,
579
	.shutdown = pty_unix98_shutdown
580
};
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602

/**
 *	ptmx_open		-	open a unix 98 pty master
 *	@inode: inode of device file
 *	@filp: file pointer to tty
 *
 *	Allocate a unix98 pty master device from the ptmx driver.
 *
 *	Locking: tty_mutex protects the init_dev work. tty->count should
 * 		protect the rest.
 *		allocated_ptys_lock handles the list of free pty numbers
 */

static int __ptmx_open(struct inode *inode, struct file *filp)
{
	struct tty_struct *tty;
	int retval;
	int index;

	nonseekable_open(inode, filp);

	/* find a device that is not in use. */
603
	index = devpts_new_index(inode);
604 605 606 607
	if (index < 0)
		return index;

	mutex_lock(&tty_mutex);
608
	tty = tty_init_dev(ptm_driver, index, 1);
609 610
	mutex_unlock(&tty_mutex);

611 612
	if (IS_ERR(tty)) {
		retval = PTR_ERR(tty);
613
		goto out;
614
	}
615 616 617 618 619

	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
	filp->private_data = tty;
	file_move(filp, &tty->tty_files);

620
	retval = devpts_pty_new(inode, tty->link);
621 622 623 624 625 626 627 628 629 630
	if (retval)
		goto out1;

	retval = ptm_driver->ops->open(tty, filp);
	if (!retval)
		return 0;
out1:
	tty_release_dev(filp);
	return retval;
out:
631
	devpts_kill_index(inode, index);
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
	return retval;
}

static int ptmx_open(struct inode *inode, struct file *filp)
{
	int ret;

	lock_kernel();
	ret = __ptmx_open(inode, filp);
	unlock_kernel();
	return ret;
}

static struct file_operations ptmx_fops;

L
Linus Torvalds 已提交
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
static void __init unix98_pty_init(void)
{
	ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
	if (!ptm_driver)
		panic("Couldn't allocate Unix98 ptm driver");
	pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
	if (!pts_driver)
		panic("Couldn't allocate Unix98 pts driver");

	ptm_driver->owner = THIS_MODULE;
	ptm_driver->driver_name = "pty_master";
	ptm_driver->name = "ptm";
	ptm_driver->major = UNIX98_PTY_MASTER_MAJOR;
	ptm_driver->minor_start = 0;
	ptm_driver->type = TTY_DRIVER_TYPE_PTY;
	ptm_driver->subtype = PTY_TYPE_MASTER;
	ptm_driver->init_termios = tty_std_termios;
	ptm_driver->init_termios.c_iflag = 0;
	ptm_driver->init_termios.c_oflag = 0;
	ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
	ptm_driver->init_termios.c_lflag = 0;
A
Alan Cox 已提交
668 669
	ptm_driver->init_termios.c_ispeed = 38400;
	ptm_driver->init_termios.c_ospeed = 38400;
L
Linus Torvalds 已提交
670
	ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
671
		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
L
Linus Torvalds 已提交
672
	ptm_driver->other = pts_driver;
A
Alan Cox 已提交
673
	tty_set_operations(ptm_driver, &ptm_unix98_ops);
L
Linus Torvalds 已提交
674 675 676 677 678 679 680 681 682 683

	pts_driver->owner = THIS_MODULE;
	pts_driver->driver_name = "pty_slave";
	pts_driver->name = "pts";
	pts_driver->major = UNIX98_PTY_SLAVE_MAJOR;
	pts_driver->minor_start = 0;
	pts_driver->type = TTY_DRIVER_TYPE_PTY;
	pts_driver->subtype = PTY_TYPE_SLAVE;
	pts_driver->init_termios = tty_std_termios;
	pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
A
Alan Cox 已提交
684 685
	pts_driver->init_termios.c_ispeed = 38400;
	pts_driver->init_termios.c_ospeed = 38400;
L
Linus Torvalds 已提交
686
	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
687
		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
L
Linus Torvalds 已提交
688
	pts_driver->other = ptm_driver;
689
	tty_set_operations(pts_driver, &pty_unix98_ops);
A
Alan Cox 已提交
690

L
Linus Torvalds 已提交
691 692 693 694 695
	if (tty_register_driver(ptm_driver))
		panic("Couldn't register Unix98 ptm driver");
	if (tty_register_driver(pts_driver))
		panic("Couldn't register Unix98 pts driver");

A
Alan Cox 已提交
696
	register_sysctl_table(pty_root_table);
697 698 699 700 701 702 703 704 705 706

	/* Now create the /dev/ptmx special device */
	tty_default_fops(&ptmx_fops);
	ptmx_fops.open = ptmx_open;

	cdev_init(&ptmx_cdev, &ptmx_fops);
	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
		panic("Couldn't register /dev/ptmx driver\n");
	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
L
Linus Torvalds 已提交
707
}
708

L
Linus Torvalds 已提交
709 710 711 712 713 714 715 716 717 718 719
#else
static inline void unix98_pty_init(void) { }
#endif

static int __init pty_init(void)
{
	legacy_pty_init();
	unix98_pty_init();
	return 0;
}
module_init(pty_init);