Blame view

drivers/tty/pty.c 19.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
   *  Added support for a Unix98-style ptmx device.
   *    -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   *
fe9cd962a   Alan Cox   pty: Coding style...
7
8
9
   *  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.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
   */
fe9cd962a   Alan Cox   pty: Coding style...
11
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
  
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
  #include <linux/interrupt.h>
  #include <linux/tty.h>
  #include <linux/tty_flip.h>
  #include <linux/fcntl.h>
d43c36dc6   Alexey Dobriyan   headers: remove s...
18
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include <linux/string.h>
  #include <linux/major.h>
  #include <linux/mm.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include <linux/sysctl.h>
d81ed1030   Alan Cox   tty: Remove more ...
24
  #include <linux/device.h>
fe9cd962a   Alan Cox   pty: Coding style...
25
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
  #include <linux/bitops.h>
  #include <linux/devpts_fs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

fe9cd962a   Alan Cox   pty: Coding style...
30
  #include <asm/system.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #ifdef CONFIG_UNIX98_PTYS
da2bdf9a6   Roel Kluin   Make various thin...
32
  static struct tty_driver *ptm_driver;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
  static struct tty_driver *pts_driver;
  #endif
fe9cd962a   Alan Cox   pty: Coding style...
35
  static void pty_close(struct tty_struct *tty, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  {
fe9cd962a   Alan Cox   pty: Coding style...
37
38
39
40
  	BUG_ON(!tty);
  	if (tty->driver->subtype == PTY_TYPE_MASTER)
  		WARN_ON(tty->count > 1);
  	else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  		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)
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
57
  			devpts_pty_kill(tty->link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  #endif
11dbf2039   Arnd Bergmann   tty: avoid recurs...
59
60
61
  		tty_unlock();
  		tty_vhangup(tty->link);
  		tty_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
65
66
67
68
  	}
  }
  
  /*
   * 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
fe9cd962a   Alan Cox   pty: Coding style...
69
   * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
   * 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.
   */
fe9cd962a   Alan Cox   pty: Coding style...
75
  static void pty_unthrottle(struct tty_struct *tty)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  {
d945cb9cc   Alan Cox   pty: Rework the p...
77
  	tty_wakeup(tty->link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  	set_bit(TTY_THROTTLED, &tty->flags);
  }
d945cb9cc   Alan Cox   pty: Rework the p...
80
81
82
  /**
   *	pty_space	-	report space left for writing
   *	@to: tty we are writing into
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
   *
d945cb9cc   Alan Cox   pty: Rework the p...
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
   *	The tty buffers allow 64K but we sneak a peak and clip at 8K this
   *	allows a lot of overspill room for echo and other fun messes to
   *	be handled properly
   */
  
  static int pty_space(struct tty_struct *to)
  {
  	int n = 8192 - to->buf.memory_used;
  	if (n < 0)
  		return 0;
  	return n;
  }
  
  /**
   *	pty_write		-	write to a pty
   *	@tty: the tty we write from
   *	@buf: kernel buffer of data
   *	@count: bytes to write
762faaed9   Alan Cox   pty: Narrow the r...
102
   *
d945cb9cc   Alan Cox   pty: Rework the p...
103
104
105
106
   *	Our "hardware" write method. Data is coming from the ldisc which
   *	may be in a non sleeping state. We simply throw this at the other
   *	end of the link as if we were an IRQ handler receiving stuff for
   *	the other side of the pty/tty pair.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
   */
d945cb9cc   Alan Cox   pty: Rework the p...
108

ac89a9174   Linus Torvalds   pty: don't limit ...
109
  static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
  {
  	struct tty_struct *to = tty->link;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

d945cb9cc   Alan Cox   pty: Rework the p...
113
  	if (tty->stopped)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  		return 0;
d945cb9cc   Alan Cox   pty: Rework the p...
115

d945cb9cc   Alan Cox   pty: Rework the p...
116
117
118
119
  	if (c > 0) {
  		/* Stuff the data into the input queue of the other end */
  		c = tty_insert_flip_string(to, buf, c);
  		/* And shovel */
202c4675c   Linus Torvalds   pty_write: don't ...
120
121
122
123
  		if (c) {
  			tty_flip_buffer_push(to);
  			tty_wakeup(tty);
  		}
762faaed9   Alan Cox   pty: Narrow the r...
124
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  	return c;
  }
d945cb9cc   Alan Cox   pty: Rework the p...
127
128
129
130
131
132
133
  /**
   *	pty_write_room	-	write space
   *	@tty: tty we are writing from
   *
   *	Report how many bytes the ldisc can send into the queue for
   *	the other device.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  static int pty_write_room(struct tty_struct *tty)
  {
85dfd81dc   Linus Torvalds   pty: fix data los...
136
137
  	if (tty->stopped)
  		return 0;
d945cb9cc   Alan Cox   pty: Rework the p...
138
  	return pty_space(tty->link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  }
d945cb9cc   Alan Cox   pty: Rework the p...
140
141
142
  /**
   *	pty_chars_in_buffer	-	characters currently in our tx queue
   *	@tty: our tty
fe9cd962a   Alan Cox   pty: Coding style...
143
   *
d945cb9cc   Alan Cox   pty: Rework the p...
144
145
   *	Report how much we have in the transmit queue. As everything is
   *	instantly at the other end this is easy to implement.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
   */
d945cb9cc   Alan Cox   pty: Rework the p...
147

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
  static int pty_chars_in_buffer(struct tty_struct *tty)
  {
d945cb9cc   Alan Cox   pty: Rework the p...
150
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
  }
  
  /* Set the lock flag on a pty */
fe9cd962a   Alan Cox   pty: Coding style...
154
  static int pty_set_lock(struct tty_struct *tty, int __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
  {
  	int val;
fe9cd962a   Alan Cox   pty: Coding style...
157
  	if (get_user(val, arg))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
163
164
  		return -EFAULT;
  	if (val)
  		set_bit(TTY_PTY_LOCK, &tty->flags);
  	else
  		clear_bit(TTY_PTY_LOCK, &tty->flags);
  	return 0;
  }
26df6d134   hyc@symas.com   tty: Add EXTPROC ...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  /* Send a signal to the slave */
  static int pty_signal(struct tty_struct *tty, int sig)
  {
  	unsigned long flags;
  	struct pid *pgrp;
  
  	if (tty->link) {
  		spin_lock_irqsave(&tty->link->ctrl_lock, flags);
  		pgrp = get_pid(tty->link->pgrp);
  		spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
  
  		kill_pgrp(pgrp, sig, 1);
  		put_pid(pgrp);
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
  static void pty_flush_buffer(struct tty_struct *tty)
  {
  	struct tty_struct *to = tty->link;
04f378b19   Alan Cox   tty: BKL pushdown
184
  	unsigned long flags;
fe9cd962a   Alan Cox   pty: Coding style...
185

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
  	if (!to)
  		return;
d945cb9cc   Alan Cox   pty: Rework the p...
188
  	/* tty_buffer_flush(to); FIXME */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  	if (to->packet) {
04f378b19   Alan Cox   tty: BKL pushdown
190
  		spin_lock_irqsave(&tty->ctrl_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
  		tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
  		wake_up_interruptible(&to->read_wait);
04f378b19   Alan Cox   tty: BKL pushdown
193
  		spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  	}
  }
fe9cd962a   Alan Cox   pty: Coding style...
196
  static int pty_open(struct tty_struct *tty, struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  {
  	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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
  	retval = 0;
  out:
  	return retval;
  }
fe9cd962a   Alan Cox   pty: Coding style...
217
218
  static void pty_set_termios(struct tty_struct *tty,
  					struct ktermios *old_termios)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  {
fe9cd962a   Alan Cox   pty: Coding style...
220
221
  	tty->termios->c_cflag &= ~(CSIZE | PARENB);
  	tty->termios->c_cflag |= (CS8 | CREAD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  }
fc6f62382   Alan Cox   pty: simplify resize
223
224
225
  /**
   *	pty_do_resize		-	resize event
   *	@tty: tty being resized
c774bda2f   Alan Cox   pty: Fix document...
226
   *	@ws: window size being set.
fc6f62382   Alan Cox   pty: simplify resize
227
   *
3ad2f3fbb   Daniel Mack   tree-wide: Assort...
228
   *	Update the termios variables and send the necessary signals to
fc6f62382   Alan Cox   pty: simplify resize
229
230
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
260
261
262
263
264
265
266
267
268
   *	peform a terminal resize correctly
   */
  
  int pty_resize(struct tty_struct *tty,  struct winsize *ws)
  {
  	struct pid *pgrp, *rpgrp;
  	unsigned long flags;
  	struct tty_struct *pty = tty->link;
  
  	/* For a PTY we need to lock the tty side */
  	mutex_lock(&tty->termios_mutex);
  	if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
  		goto done;
  
  	/* Get the PID values and reference them so we can
  	   avoid holding the tty ctrl lock while sending signals.
  	   We need to lock these individually however. */
  
  	spin_lock_irqsave(&tty->ctrl_lock, flags);
  	pgrp = get_pid(tty->pgrp);
  	spin_unlock_irqrestore(&tty->ctrl_lock, flags);
  
  	spin_lock_irqsave(&pty->ctrl_lock, flags);
  	rpgrp = get_pid(pty->pgrp);
  	spin_unlock_irqrestore(&pty->ctrl_lock, flags);
  
  	if (pgrp)
  		kill_pgrp(pgrp, SIGWINCH, 1);
  	if (rpgrp != pgrp && rpgrp)
  		kill_pgrp(rpgrp, SIGWINCH, 1);
  
  	put_pid(pgrp);
  	put_pid(rpgrp);
  
  	tty->winsize = *ws;
  	pty->winsize = *ws;	/* Never used so will go away soon */
  done:
  	mutex_unlock(&tty->termios_mutex);
  	return 0;
  }
342a59714   Linus Torvalds   pty: reconnect th...
269
270
  /* Traditional BSD devices */
  #ifdef CONFIG_LEGACY_PTYS
bf970ee46   Alan Cox   tty: extract the ...
271
272
273
274
275
276
277
278
279
280
281
  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 */
8a1b8d70a   Jiri Slaby   TTY: unify pty_in...
282
283
  		retval = -ENOMEM;
  		goto err_free_tty;
bf970ee46   Alan Cox   tty: extract the ...
284
285
286
287
288
289
290
  	}
  	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)
a9dccddb6   Jiri Slaby   TTY: plug in dein...
291
  		goto err_deinit_tty;
bf970ee46   Alan Cox   tty: extract the ...
292
293
  
  	retval = tty_init_termios(o_tty);
8a1b8d70a   Jiri Slaby   TTY: unify pty_in...
294
295
  	if (retval)
  		goto err_free_termios;
fe9cd962a   Alan Cox   pty: Coding style...
296

bf970ee46   Alan Cox   tty: extract the ...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  	/*
  	 * 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;
8a1b8d70a   Jiri Slaby   TTY: unify pty_in...
312
313
  err_free_termios:
  	tty_free_termios(tty);
a9dccddb6   Jiri Slaby   TTY: plug in dein...
314
315
  err_deinit_tty:
  	deinitialize_tty_struct(o_tty);
bf970ee46   Alan Cox   tty: extract the ...
316
  	module_put(o_tty->driver->owner);
8a1b8d70a   Jiri Slaby   TTY: unify pty_in...
317
  err_free_tty:
bf970ee46   Alan Cox   tty: extract the ...
318
  	free_tty_struct(o_tty);
8a1b8d70a   Jiri Slaby   TTY: unify pty_in...
319
  	return retval;
bf970ee46   Alan Cox   tty: extract the ...
320
  }
6caa76b77   Alan Cox   tty: now phase ou...
321
  static int pty_bsd_ioctl(struct tty_struct *tty,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
  			 unsigned int cmd, unsigned long arg)
  {
  	switch (cmd) {
  	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
  		return pty_set_lock(tty, (int __user *) arg);
26df6d134   hyc@symas.com   tty: Add EXTPROC ...
327
328
  	case TIOCSIG:    /* Send signal to other side of pty */
  		return pty_signal(tty, (int) arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  	}
  	return -ENOIOCTLCMD;
  }
dc8c85871   Kay Sievers   PTY: add kernel p...
332
333
  static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
  module_param(legacy_count, int, 0);
342a59714   Linus Torvalds   pty: reconnect th...
334
335
336
337
338
339
  /*
   * The master side of a pty can do TIOCSPTLCK and thus
   * has pty_bsd_ioctl.
   */
  static const struct tty_operations master_pty_ops_bsd = {
  	.install = pty_install,
3e8e88ca0   Alan Cox   pty: prepare for ...
340
341
342
343
344
345
346
347
348
  	.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,
fc6f62382   Alan Cox   pty: simplify resize
349
  	.resize = pty_resize
3e8e88ca0   Alan Cox   pty: prepare for ...
350
  };
342a59714   Linus Torvalds   pty: reconnect th...
351
352
353
354
355
356
357
358
359
360
361
362
  static const struct tty_operations slave_pty_ops_bsd = {
  	.install = pty_install,
  	.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,
  	.resize = pty_resize
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
  static void __init legacy_pty_init(void)
  {
342a59714   Linus Torvalds   pty: reconnect th...
365
  	struct tty_driver *pty_driver, *pty_slave_driver;
dc8c85871   Kay Sievers   PTY: add kernel p...
366
367
  	if (legacy_count <= 0)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

dc8c85871   Kay Sievers   PTY: add kernel p...
369
  	pty_driver = alloc_tty_driver(legacy_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
  	if (!pty_driver)
  		panic("Couldn't allocate pty driver");
dc8c85871   Kay Sievers   PTY: add kernel p...
372
  	pty_slave_driver = alloc_tty_driver(legacy_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
377
378
  	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";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
385
386
387
  	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;
606d099cd   Alan Cox   [PATCH] tty: swit...
388
389
  	pty_driver->init_termios.c_ispeed = 38400;
  	pty_driver->init_termios.c_ospeed = 38400;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
  	pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
  	pty_driver->other = pty_slave_driver;
342a59714   Linus Torvalds   pty: reconnect th...
392
  	tty_set_operations(pty_driver, &master_pty_ops_bsd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
  
  	pty_slave_driver->owner = THIS_MODULE;
  	pty_slave_driver->driver_name = "pty_slave";
  	pty_slave_driver->name = "ttyp";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
398
399
400
401
402
  	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;
606d099cd   Alan Cox   [PATCH] tty: swit...
403
404
  	pty_slave_driver->init_termios.c_ispeed = 38400;
  	pty_slave_driver->init_termios.c_ospeed = 38400;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
  	pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS |
  					TTY_DRIVER_REAL_RAW;
  	pty_slave_driver->other = pty_driver;
342a59714   Linus Torvalds   pty: reconnect th...
408
  	tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  
  	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;
fe9cd962a   Alan Cox   pty: Coding style...
426
  static int pty_limit_min;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  static int pty_limit_max = NR_UNIX98_PTY_MAX;
fe9cd962a   Alan Cox   pty: Coding style...
428
  static int pty_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429

d81ed1030   Alan Cox   tty: Remove more ...
430
  static struct cdev ptmx_cdev;
35834ca1e   Eric W. Biederman   sysctl: simplify ...
431
  static struct ctl_table pty_table[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  	{
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  		.procname	= "max",
  		.maxlen		= sizeof(int),
  		.mode		= 0644,
  		.data		= &pty_limit,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
437
  		.proc_handler	= proc_dointvec_minmax,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
  		.extra1		= &pty_limit_min,
  		.extra2		= &pty_limit_max,
  	}, {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
  		.procname	= "nr",
  		.maxlen		= sizeof(int),
  		.mode		= 0444,
bf970ee46   Alan Cox   tty: extract the ...
444
  		.data		= &pty_count,
6d4561110   Eric W. Biederman   sysctl: Drop & in...
445
  		.proc_handler	= proc_dointvec,
894d24911   Eric W. Biederman   sysctl drivers: R...
446
447
  	}, 
  	{}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  };
35834ca1e   Eric W. Biederman   sysctl: simplify ...
449
450
  static struct ctl_table pty_kern_table[] = {
  	{
35834ca1e   Eric W. Biederman   sysctl: simplify ...
451
452
453
454
455
456
457
458
459
  		.procname	= "pty",
  		.mode		= 0555,
  		.child		= pty_table,
  	},
  	{}
  };
  
  static struct ctl_table pty_root_table[] = {
  	{
35834ca1e   Eric W. Biederman   sysctl: simplify ...
460
461
462
463
464
465
  		.procname	= "kernel",
  		.mode		= 0555,
  		.child		= pty_kern_table,
  	},
  	{}
  };
6caa76b77   Alan Cox   tty: now phase ou...
466
  static int pty_unix98_ioctl(struct tty_struct *tty,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
471
472
473
  			    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);
26df6d134   hyc@symas.com   tty: Add EXTPROC ...
474
475
  	case TIOCSIG:    /* Send signal to other side of pty */
  		return pty_signal(tty, (int) arg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
479
  	}
  
  	return -ENOIOCTLCMD;
  }
99f1fe189   Alan Cox   tty: Clean up the...
480
481
482
483
484
485
486
487
  /**
   *	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.
   */
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
488
489
  static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
  		struct inode *ptm_inode, int idx)
99f1fe189   Alan Cox   tty: Clean up the...
490
  {
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
491
  	struct tty_struct *tty = devpts_get_tty(ptm_inode, idx);
99f1fe189   Alan Cox   tty: Clean up the...
492
493
494
495
496
497
498
499
500
501
502
503
504
  	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.
   */
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
505
506
  static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
  		struct inode *pts_inode, int idx)
99f1fe189   Alan Cox   tty: Clean up the...
507
  {
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
508
  	struct tty_struct *tty = devpts_get_tty(pts_inode, idx);
99f1fe189   Alan Cox   tty: Clean up the...
509
510
511
512
513
  	/* Master must be open before slave */
  	if (!tty)
  		return ERR_PTR(-EIO);
  	return tty;
  }
bf970ee46   Alan Cox   tty: extract the ...
514
  static void pty_unix98_shutdown(struct tty_struct *tty)
feebed651   Alan Cox   tty: shutdown method
515
  {
24d406a6b   Jiri Slaby   TTY: pty, fix pty...
516
  	tty_driver_remove_tty(tty->driver, tty);
feebed651   Alan Cox   tty: shutdown method
517
518
  	/* We have our own method as we don't use the tty index */
  	kfree(tty->termios);
feebed651   Alan Cox   tty: shutdown method
519
  }
8b0a88d59   Alan Cox   tty: More driver ...
520
521
  /* We have no need to install and remove our tty objects as devpts does all
     the work for us */
bf970ee46   Alan Cox   tty: extract the ...
522
  static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty)
8b0a88d59   Alan Cox   tty: More driver ...
523
  {
bf970ee46   Alan Cox   tty: extract the ...
524
525
526
527
528
529
530
531
  	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 */
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
532
  		goto err_free_tty;
bf970ee46   Alan Cox   tty: extract the ...
533
534
  	}
  	initialize_tty_struct(o_tty, driver->other, idx);
8dff04ea3   Alan Cox   pty: simplify uni...
535
  	tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
bf970ee46   Alan Cox   tty: extract the ...
536
  	if (tty->termios == NULL)
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
537
  		goto err_free_mem;
bf970ee46   Alan Cox   tty: extract the ...
538
  	*tty->termios = driver->init_termios;
8dff04ea3   Alan Cox   pty: simplify uni...
539
540
541
  	tty->termios_locked = tty->termios + 1;
  
  	o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL);
bf970ee46   Alan Cox   tty: extract the ...
542
  	if (o_tty->termios == NULL)
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
543
  		goto err_free_mem;
bf970ee46   Alan Cox   tty: extract the ...
544
  	*o_tty->termios = driver->other->init_termios;
8dff04ea3   Alan Cox   pty: simplify uni...
545
  	o_tty->termios_locked = o_tty->termios + 1;
bf970ee46   Alan Cox   tty: extract the ...
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  
  	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++;
484af54d4   Jiri Slaby   TTY: pty, cleanup...
560
  	pty_count++;
8b0a88d59   Alan Cox   tty: More driver ...
561
  	return 0;
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
562
  err_free_mem:
a9dccddb6   Jiri Slaby   TTY: plug in dein...
563
  	deinitialize_tty_struct(o_tty);
8dff04ea3   Alan Cox   pty: simplify uni...
564
  	kfree(o_tty->termios);
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
565
  	kfree(tty->termios);
bf970ee46   Alan Cox   tty: extract the ...
566
  	module_put(o_tty->driver->owner);
c18d77aa0   Jiri Slaby   TTY: unify pty_un...
567
  err_free_tty:
bf970ee46   Alan Cox   tty: extract the ...
568
  	free_tty_struct(o_tty);
bf970ee46   Alan Cox   tty: extract the ...
569
  	return -ENOMEM;
8b0a88d59   Alan Cox   tty: More driver ...
570
  }
484af54d4   Jiri Slaby   TTY: pty, cleanup...
571
572
573
574
575
576
  static void ptm_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
  {
  	pty_count--;
  }
  
  static void pts_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
8b0a88d59   Alan Cox   tty: More driver ...
577
578
  {
  }
feebed651   Alan Cox   tty: shutdown method
579
  static const struct tty_operations ptm_unix98_ops = {
99f1fe189   Alan Cox   tty: Clean up the...
580
  	.lookup = ptm_unix98_lookup,
bf970ee46   Alan Cox   tty: extract the ...
581
  	.install = pty_unix98_install,
484af54d4   Jiri Slaby   TTY: pty, cleanup...
582
  	.remove = ptm_unix98_remove,
3e8e88ca0   Alan Cox   pty: prepare for ...
583
584
585
586
587
588
589
590
  	.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,
feebed651   Alan Cox   tty: shutdown method
591
  	.ioctl = pty_unix98_ioctl,
fc6f62382   Alan Cox   pty: simplify resize
592
593
  	.shutdown = pty_unix98_shutdown,
  	.resize = pty_resize
3e8e88ca0   Alan Cox   pty: prepare for ...
594
  };
99f1fe189   Alan Cox   tty: Clean up the...
595
596
  static const struct tty_operations pty_unix98_ops = {
  	.lookup = pts_unix98_lookup,
bf970ee46   Alan Cox   tty: extract the ...
597
  	.install = pty_unix98_install,
484af54d4   Jiri Slaby   TTY: pty, cleanup...
598
  	.remove = pts_unix98_remove,
99f1fe189   Alan Cox   tty: Clean up the...
599
600
601
602
603
604
605
606
  	.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,
bf970ee46   Alan Cox   tty: extract the ...
607
  	.shutdown = pty_unix98_shutdown
99f1fe189   Alan Cox   tty: Clean up the...
608
  };
d81ed1030   Alan Cox   tty: Remove more ...
609
610
611
612
613
614
615
616
617
618
619
620
  
  /**
   *	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
   */
64ba3dc31   Arnd Bergmann   tty: never hold B...
621
  static int ptmx_open(struct inode *inode, struct file *filp)
d81ed1030   Alan Cox   tty: Remove more ...
622
623
624
625
626
627
  {
  	struct tty_struct *tty;
  	int retval;
  	int index;
  
  	nonseekable_open(inode, filp);
fa90e1c93   Jiri Slaby   TTY: make tty_add...
628
629
630
  	retval = tty_alloc_file(filp);
  	if (retval)
  		return retval;
d81ed1030   Alan Cox   tty: Remove more ...
631
  	/* find a device that is not in use. */
64ba3dc31   Arnd Bergmann   tty: never hold B...
632
  	tty_lock();
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
633
  	index = devpts_new_index(inode);
64ba3dc31   Arnd Bergmann   tty: never hold B...
634
  	tty_unlock();
fa90e1c93   Jiri Slaby   TTY: make tty_add...
635
636
637
638
  	if (index < 0) {
  		retval = index;
  		goto err_file;
  	}
d81ed1030   Alan Cox   tty: Remove more ...
639
640
  
  	mutex_lock(&tty_mutex);
64ba3dc31   Arnd Bergmann   tty: never hold B...
641
  	tty_lock();
73ec06fc5   Alan Cox   tty: Finish fixin...
642
  	tty = tty_init_dev(ptm_driver, index, 1);
d81ed1030   Alan Cox   tty: Remove more ...
643
  	mutex_unlock(&tty_mutex);
73ec06fc5   Alan Cox   tty: Finish fixin...
644
645
  	if (IS_ERR(tty)) {
  		retval = PTR_ERR(tty);
d81ed1030   Alan Cox   tty: Remove more ...
646
  		goto out;
73ec06fc5   Alan Cox   tty: Finish fixin...
647
  	}
d81ed1030   Alan Cox   tty: Remove more ...
648
649
  
  	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
ee2ffa0df   Nick Piggin   fs: cleanup files...
650

fa90e1c93   Jiri Slaby   TTY: make tty_add...
651
  	tty_add_file(tty, filp);
d81ed1030   Alan Cox   tty: Remove more ...
652

15f1a6338   Sukadev Bhattiprolu   Add an instance p...
653
  	retval = devpts_pty_new(inode, tty->link);
d81ed1030   Alan Cox   tty: Remove more ...
654
  	if (retval)
1177c0efc   Jiri Slaby   TTY: pty, release...
655
  		goto err_release;
d81ed1030   Alan Cox   tty: Remove more ...
656
657
  
  	retval = ptm_driver->ops->open(tty, filp);
64ba3dc31   Arnd Bergmann   tty: never hold B...
658
  	if (retval)
1177c0efc   Jiri Slaby   TTY: pty, release...
659
  		goto err_release;
64ba3dc31   Arnd Bergmann   tty: never hold B...
660
  	tty_unlock();
1177c0efc   Jiri Slaby   TTY: pty, release...
661
662
  	return 0;
  err_release:
64ba3dc31   Arnd Bergmann   tty: never hold B...
663
  	tty_unlock();
eeb89d918   Alan Cox   tty: push the BKL...
664
  	tty_release(inode, filp);
d81ed1030   Alan Cox   tty: Remove more ...
665
666
  	return retval;
  out:
15f1a6338   Sukadev Bhattiprolu   Add an instance p...
667
  	devpts_kill_index(inode, index);
ec79d6056   Arnd Bergmann   tty: replace BKL ...
668
  	tty_unlock();
fa90e1c93   Jiri Slaby   TTY: make tty_add...
669
670
  err_file:
  	tty_free_file(filp);
64ba3dc31   Arnd Bergmann   tty: never hold B...
671
  	return retval;
d81ed1030   Alan Cox   tty: Remove more ...
672
673
674
  }
  
  static struct file_operations ptmx_fops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
  static void __init unix98_pty_init(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
  	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;
606d099cd   Alan Cox   [PATCH] tty: swit...
696
697
  	ptm_driver->init_termios.c_ispeed = 38400;
  	ptm_driver->init_termios.c_ospeed = 38400;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  	ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
331b83198   Greg Kroah-Hartman   [PATCH] devfs: Re...
699
  		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  	ptm_driver->other = pts_driver;
feebed651   Alan Cox   tty: shutdown method
701
  	tty_set_operations(ptm_driver, &ptm_unix98_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
704
705
706
707
708
709
710
711
  
  	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;
606d099cd   Alan Cox   [PATCH] tty: swit...
712
713
  	pts_driver->init_termios.c_ispeed = 38400;
  	pts_driver->init_termios.c_ospeed = 38400;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714
  	pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
331b83198   Greg Kroah-Hartman   [PATCH] devfs: Re...
715
  		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
716
  	pts_driver->other = ptm_driver;
99f1fe189   Alan Cox   tty: Clean up the...
717
  	tty_set_operations(pts_driver, &pty_unix98_ops);
fe9cd962a   Alan Cox   pty: Coding style...
718

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
  	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");
fe9cd962a   Alan Cox   pty: Coding style...
723
  	register_sysctl_table(pty_root_table);
d81ed1030   Alan Cox   tty: Remove more ...
724
725
726
727
728
729
730
731
732
733
734
  
  	/* 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
  ");
  	device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
  }
d81ed1030   Alan Cox   tty: Remove more ...
736

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
737
738
739
740
741
742
743
744
745
746
747
  #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);