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