Blame view
drivers/tty/pty.c
19.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
1da177e4c 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 Linux-2.6.12-rc2 |
6 |
* |
fe9cd962a 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 Linux-2.6.12-rc2 |
10 |
*/ |
fe9cd962a pty: Coding style... |
11 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 |
#include <linux/errno.h> |
1da177e4c 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 headers: remove s... |
18 |
#include <linux/sched.h> |
1da177e4c 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 Linux-2.6.12-rc2 |
23 |
#include <linux/sysctl.h> |
d81ed1030 tty: Remove more ... |
24 |
#include <linux/device.h> |
fe9cd962a pty: Coding style... |
25 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 |
#include <linux/bitops.h> #include <linux/devpts_fs.h> |
5a0e3ad6a include cleanup: ... |
28 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
29 |
|
fe9cd962a pty: Coding style... |
30 |
#include <asm/system.h> |
1da177e4c Linux-2.6.12-rc2 |
31 |
#ifdef CONFIG_UNIX98_PTYS |
da2bdf9a6 Make various thin... |
32 |
static struct tty_driver *ptm_driver; |
1da177e4c Linux-2.6.12-rc2 |
33 34 |
static struct tty_driver *pts_driver; #endif |
fe9cd962a pty: Coding style... |
35 |
static void pty_close(struct tty_struct *tty, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
36 |
{ |
fe9cd962a pty: Coding style... |
37 38 39 40 |
BUG_ON(!tty); if (tty->driver->subtype == PTY_TYPE_MASTER) WARN_ON(tty->count > 1); else { |
1da177e4c 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 Add an instance p... |
57 |
devpts_pty_kill(tty->link); |
1da177e4c Linux-2.6.12-rc2 |
58 |
#endif |
11dbf2039 tty: avoid recurs... |
59 60 61 |
tty_unlock(); tty_vhangup(tty->link); tty_lock(); |
1da177e4c 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 pty: Coding style... |
69 |
* unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE |
1da177e4c 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 pty: Coding style... |
75 |
static void pty_unthrottle(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
76 |
{ |
d945cb9cc pty: Rework the p... |
77 |
tty_wakeup(tty->link); |
1da177e4c Linux-2.6.12-rc2 |
78 79 |
set_bit(TTY_THROTTLED, &tty->flags); } |
d945cb9cc pty: Rework the p... |
80 81 82 |
/** * pty_space - report space left for writing * @to: tty we are writing into |
1da177e4c Linux-2.6.12-rc2 |
83 |
* |
d945cb9cc 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 pty: Narrow the r... |
102 |
* |
d945cb9cc 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 Linux-2.6.12-rc2 |
107 |
*/ |
d945cb9cc pty: Rework the p... |
108 |
|
ac89a9174 pty: don't limit ... |
109 |
static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) |
1da177e4c Linux-2.6.12-rc2 |
110 111 |
{ struct tty_struct *to = tty->link; |
1da177e4c Linux-2.6.12-rc2 |
112 |
|
d945cb9cc pty: Rework the p... |
113 |
if (tty->stopped) |
1da177e4c Linux-2.6.12-rc2 |
114 |
return 0; |
d945cb9cc pty: Rework the p... |
115 |
|
d945cb9cc 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 pty_write: don't ... |
120 121 122 123 |
if (c) { tty_flip_buffer_push(to); tty_wakeup(tty); } |
762faaed9 pty: Narrow the r... |
124 |
} |
1da177e4c Linux-2.6.12-rc2 |
125 126 |
return c; } |
d945cb9cc 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 Linux-2.6.12-rc2 |
134 135 |
static int pty_write_room(struct tty_struct *tty) { |
85dfd81dc pty: fix data los... |
136 137 |
if (tty->stopped) return 0; |
d945cb9cc pty: Rework the p... |
138 |
return pty_space(tty->link); |
1da177e4c Linux-2.6.12-rc2 |
139 |
} |
d945cb9cc pty: Rework the p... |
140 141 142 |
/** * pty_chars_in_buffer - characters currently in our tx queue * @tty: our tty |
fe9cd962a pty: Coding style... |
143 |
* |
d945cb9cc 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 Linux-2.6.12-rc2 |
146 |
*/ |
d945cb9cc pty: Rework the p... |
147 |
|
1da177e4c Linux-2.6.12-rc2 |
148 149 |
static int pty_chars_in_buffer(struct tty_struct *tty) { |
d945cb9cc pty: Rework the p... |
150 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
151 152 153 |
} /* Set the lock flag on a pty */ |
fe9cd962a pty: Coding style... |
154 |
static int pty_set_lock(struct tty_struct *tty, int __user *arg) |
1da177e4c Linux-2.6.12-rc2 |
155 156 |
{ int val; |
fe9cd962a pty: Coding style... |
157 |
if (get_user(val, arg)) |
1da177e4c 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 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 Linux-2.6.12-rc2 |
181 182 183 |
static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; |
04f378b19 tty: BKL pushdown |
184 |
unsigned long flags; |
fe9cd962a pty: Coding style... |
185 |
|
1da177e4c Linux-2.6.12-rc2 |
186 187 |
if (!to) return; |
d945cb9cc pty: Rework the p... |
188 |
/* tty_buffer_flush(to); FIXME */ |
1da177e4c Linux-2.6.12-rc2 |
189 |
if (to->packet) { |
04f378b19 tty: BKL pushdown |
190 |
spin_lock_irqsave(&tty->ctrl_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
191 192 |
tty->ctrl_status |= TIOCPKT_FLUSHWRITE; wake_up_interruptible(&to->read_wait); |
04f378b19 tty: BKL pushdown |
193 |
spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
1da177e4c Linux-2.6.12-rc2 |
194 195 |
} } |
fe9cd962a pty: Coding style... |
196 |
static int pty_open(struct tty_struct *tty, struct file *filp) |
1da177e4c 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 Linux-2.6.12-rc2 |
213 214 215 216 |
retval = 0; out: return retval; } |
fe9cd962a pty: Coding style... |
217 218 |
static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
1da177e4c Linux-2.6.12-rc2 |
219 |
{ |
fe9cd962a pty: Coding style... |
220 221 |
tty->termios->c_cflag &= ~(CSIZE | PARENB); tty->termios->c_cflag |= (CS8 | CREAD); |
1da177e4c Linux-2.6.12-rc2 |
222 |
} |
fc6f62382 pty: simplify resize |
223 224 225 |
/** * pty_do_resize - resize event * @tty: tty being resized |
c774bda2f pty: Fix document... |
226 |
* @ws: window size being set. |
fc6f62382 pty: simplify resize |
227 |
* |
3ad2f3fbb tree-wide: Assort... |
228 |
* Update the termios variables and send the necessary signals to |
fc6f62382 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 pty: reconnect th... |
269 270 |
/* Traditional BSD devices */ #ifdef CONFIG_LEGACY_PTYS |
bf970ee46 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 TTY: unify pty_in... |
282 283 |
retval = -ENOMEM; goto err_free_tty; |
bf970ee46 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 TTY: plug in dein... |
291 |
goto err_deinit_tty; |
bf970ee46 tty: extract the ... |
292 293 |
retval = tty_init_termios(o_tty); |
8a1b8d70a TTY: unify pty_in... |
294 295 |
if (retval) goto err_free_termios; |
fe9cd962a pty: Coding style... |
296 |
|
bf970ee46 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 TTY: unify pty_in... |
312 313 |
err_free_termios: tty_free_termios(tty); |
a9dccddb6 TTY: plug in dein... |
314 315 |
err_deinit_tty: deinitialize_tty_struct(o_tty); |
bf970ee46 tty: extract the ... |
316 |
module_put(o_tty->driver->owner); |
8a1b8d70a TTY: unify pty_in... |
317 |
err_free_tty: |
bf970ee46 tty: extract the ... |
318 |
free_tty_struct(o_tty); |
8a1b8d70a TTY: unify pty_in... |
319 |
return retval; |
bf970ee46 tty: extract the ... |
320 |
} |
6caa76b77 tty: now phase ou... |
321 |
static int pty_bsd_ioctl(struct tty_struct *tty, |
1da177e4c 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 tty: Add EXTPROC ... |
327 328 |
case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); |
1da177e4c Linux-2.6.12-rc2 |
329 330 331 |
} return -ENOIOCTLCMD; } |
dc8c85871 PTY: add kernel p... |
332 333 |
static int legacy_count = CONFIG_LEGACY_PTY_COUNT; module_param(legacy_count, int, 0); |
342a59714 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 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 pty: simplify resize |
349 |
.resize = pty_resize |
3e8e88ca0 pty: prepare for ... |
350 |
}; |
342a59714 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 Linux-2.6.12-rc2 |
363 364 |
static void __init legacy_pty_init(void) { |
342a59714 pty: reconnect th... |
365 |
struct tty_driver *pty_driver, *pty_slave_driver; |
dc8c85871 PTY: add kernel p... |
366 367 |
if (legacy_count <= 0) return; |
1da177e4c Linux-2.6.12-rc2 |
368 |
|
dc8c85871 PTY: add kernel p... |
369 |
pty_driver = alloc_tty_driver(legacy_count); |
1da177e4c Linux-2.6.12-rc2 |
370 371 |
if (!pty_driver) panic("Couldn't allocate pty driver"); |
dc8c85871 PTY: add kernel p... |
372 |
pty_slave_driver = alloc_tty_driver(legacy_count); |
1da177e4c 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 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 [PATCH] tty: swit... |
388 389 |
pty_driver->init_termios.c_ispeed = 38400; pty_driver->init_termios.c_ospeed = 38400; |
1da177e4c 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 pty: reconnect th... |
392 |
tty_set_operations(pty_driver, &master_pty_ops_bsd); |
1da177e4c 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 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 [PATCH] tty: swit... |
403 404 |
pty_slave_driver->init_termios.c_ispeed = 38400; pty_slave_driver->init_termios.c_ospeed = 38400; |
1da177e4c 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 pty: reconnect th... |
408 |
tty_set_operations(pty_slave_driver, &slave_pty_ops_bsd); |
1da177e4c 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 pty: Coding style... |
426 |
static int pty_limit_min; |
1da177e4c Linux-2.6.12-rc2 |
427 |
static int pty_limit_max = NR_UNIX98_PTY_MAX; |
fe9cd962a pty: Coding style... |
428 |
static int pty_count; |
1da177e4c Linux-2.6.12-rc2 |
429 |
|
d81ed1030 tty: Remove more ... |
430 |
static struct cdev ptmx_cdev; |
35834ca1e sysctl: simplify ... |
431 |
static struct ctl_table pty_table[] = { |
1da177e4c Linux-2.6.12-rc2 |
432 |
{ |
1da177e4c Linux-2.6.12-rc2 |
433 434 435 436 |
.procname = "max", .maxlen = sizeof(int), .mode = 0644, .data = &pty_limit, |
6d4561110 sysctl: Drop & in... |
437 |
.proc_handler = proc_dointvec_minmax, |
1da177e4c Linux-2.6.12-rc2 |
438 439 440 |
.extra1 = &pty_limit_min, .extra2 = &pty_limit_max, }, { |
1da177e4c Linux-2.6.12-rc2 |
441 442 443 |
.procname = "nr", .maxlen = sizeof(int), .mode = 0444, |
bf970ee46 tty: extract the ... |
444 |
.data = &pty_count, |
6d4561110 sysctl: Drop & in... |
445 |
.proc_handler = proc_dointvec, |
894d24911 sysctl drivers: R... |
446 447 |
}, {} |
1da177e4c Linux-2.6.12-rc2 |
448 |
}; |
35834ca1e sysctl: simplify ... |
449 450 |
static struct ctl_table pty_kern_table[] = { { |
35834ca1e 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 sysctl: simplify ... |
460 461 462 463 464 465 |
.procname = "kernel", .mode = 0555, .child = pty_kern_table, }, {} }; |
6caa76b77 tty: now phase ou... |
466 |
static int pty_unix98_ioctl(struct tty_struct *tty, |
1da177e4c 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 tty: Add EXTPROC ... |
474 475 |
case TIOCSIG: /* Send signal to other side of pty */ return pty_signal(tty, (int) arg); |
1da177e4c Linux-2.6.12-rc2 |
476 477 478 479 |
} return -ENOIOCTLCMD; } |
99f1fe189 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 Add an instance p... |
488 489 |
static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, struct inode *ptm_inode, int idx) |
99f1fe189 tty: Clean up the... |
490 |
{ |
15f1a6338 Add an instance p... |
491 |
struct tty_struct *tty = devpts_get_tty(ptm_inode, idx); |
99f1fe189 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 Add an instance p... |
505 506 |
static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, struct inode *pts_inode, int idx) |
99f1fe189 tty: Clean up the... |
507 |
{ |
15f1a6338 Add an instance p... |
508 |
struct tty_struct *tty = devpts_get_tty(pts_inode, idx); |
99f1fe189 tty: Clean up the... |
509 510 511 512 513 |
/* Master must be open before slave */ if (!tty) return ERR_PTR(-EIO); return tty; } |
bf970ee46 tty: extract the ... |
514 |
static void pty_unix98_shutdown(struct tty_struct *tty) |
feebed651 tty: shutdown method |
515 |
{ |
24d406a6b TTY: pty, fix pty... |
516 |
tty_driver_remove_tty(tty->driver, tty); |
feebed651 tty: shutdown method |
517 518 |
/* We have our own method as we don't use the tty index */ kfree(tty->termios); |
feebed651 tty: shutdown method |
519 |
} |
8b0a88d59 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 tty: extract the ... |
522 |
static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) |
8b0a88d59 tty: More driver ... |
523 |
{ |
bf970ee46 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 TTY: unify pty_un... |
532 |
goto err_free_tty; |
bf970ee46 tty: extract the ... |
533 534 |
} initialize_tty_struct(o_tty, driver->other, idx); |
8dff04ea3 pty: simplify uni... |
535 |
tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); |
bf970ee46 tty: extract the ... |
536 |
if (tty->termios == NULL) |
c18d77aa0 TTY: unify pty_un... |
537 |
goto err_free_mem; |
bf970ee46 tty: extract the ... |
538 |
*tty->termios = driver->init_termios; |
8dff04ea3 pty: simplify uni... |
539 540 541 |
tty->termios_locked = tty->termios + 1; o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); |
bf970ee46 tty: extract the ... |
542 |
if (o_tty->termios == NULL) |
c18d77aa0 TTY: unify pty_un... |
543 |
goto err_free_mem; |
bf970ee46 tty: extract the ... |
544 |
*o_tty->termios = driver->other->init_termios; |
8dff04ea3 pty: simplify uni... |
545 |
o_tty->termios_locked = o_tty->termios + 1; |
bf970ee46 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 TTY: pty, cleanup... |
560 |
pty_count++; |
8b0a88d59 tty: More driver ... |
561 |
return 0; |
c18d77aa0 TTY: unify pty_un... |
562 |
err_free_mem: |
a9dccddb6 TTY: plug in dein... |
563 |
deinitialize_tty_struct(o_tty); |
8dff04ea3 pty: simplify uni... |
564 |
kfree(o_tty->termios); |
c18d77aa0 TTY: unify pty_un... |
565 |
kfree(tty->termios); |
bf970ee46 tty: extract the ... |
566 |
module_put(o_tty->driver->owner); |
c18d77aa0 TTY: unify pty_un... |
567 |
err_free_tty: |
bf970ee46 tty: extract the ... |
568 |
free_tty_struct(o_tty); |
bf970ee46 tty: extract the ... |
569 |
return -ENOMEM; |
8b0a88d59 tty: More driver ... |
570 |
} |
484af54d4 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 tty: More driver ... |
577 578 |
{ } |
feebed651 tty: shutdown method |
579 |
static const struct tty_operations ptm_unix98_ops = { |
99f1fe189 tty: Clean up the... |
580 |
.lookup = ptm_unix98_lookup, |
bf970ee46 tty: extract the ... |
581 |
.install = pty_unix98_install, |
484af54d4 TTY: pty, cleanup... |
582 |
.remove = ptm_unix98_remove, |
3e8e88ca0 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 tty: shutdown method |
591 |
.ioctl = pty_unix98_ioctl, |
fc6f62382 pty: simplify resize |
592 593 |
.shutdown = pty_unix98_shutdown, .resize = pty_resize |
3e8e88ca0 pty: prepare for ... |
594 |
}; |
99f1fe189 tty: Clean up the... |
595 596 |
static const struct tty_operations pty_unix98_ops = { .lookup = pts_unix98_lookup, |
bf970ee46 tty: extract the ... |
597 |
.install = pty_unix98_install, |
484af54d4 TTY: pty, cleanup... |
598 |
.remove = pts_unix98_remove, |
99f1fe189 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 tty: extract the ... |
607 |
.shutdown = pty_unix98_shutdown |
99f1fe189 tty: Clean up the... |
608 |
}; |
d81ed1030 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 tty: never hold B... |
621 |
static int ptmx_open(struct inode *inode, struct file *filp) |
d81ed1030 tty: Remove more ... |
622 623 624 625 626 627 |
{ struct tty_struct *tty; int retval; int index; nonseekable_open(inode, filp); |
fa90e1c93 TTY: make tty_add... |
628 629 630 |
retval = tty_alloc_file(filp); if (retval) return retval; |
d81ed1030 tty: Remove more ... |
631 |
/* find a device that is not in use. */ |
64ba3dc31 tty: never hold B... |
632 |
tty_lock(); |
15f1a6338 Add an instance p... |
633 |
index = devpts_new_index(inode); |
64ba3dc31 tty: never hold B... |
634 |
tty_unlock(); |
fa90e1c93 TTY: make tty_add... |
635 636 637 638 |
if (index < 0) { retval = index; goto err_file; } |
d81ed1030 tty: Remove more ... |
639 640 |
mutex_lock(&tty_mutex); |
64ba3dc31 tty: never hold B... |
641 |
tty_lock(); |
73ec06fc5 tty: Finish fixin... |
642 |
tty = tty_init_dev(ptm_driver, index, 1); |
d81ed1030 tty: Remove more ... |
643 |
mutex_unlock(&tty_mutex); |
73ec06fc5 tty: Finish fixin... |
644 645 |
if (IS_ERR(tty)) { retval = PTR_ERR(tty); |
d81ed1030 tty: Remove more ... |
646 |
goto out; |
73ec06fc5 tty: Finish fixin... |
647 |
} |
d81ed1030 tty: Remove more ... |
648 649 |
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
ee2ffa0df fs: cleanup files... |
650 |
|
fa90e1c93 TTY: make tty_add... |
651 |
tty_add_file(tty, filp); |
d81ed1030 tty: Remove more ... |
652 |
|
15f1a6338 Add an instance p... |
653 |
retval = devpts_pty_new(inode, tty->link); |
d81ed1030 tty: Remove more ... |
654 |
if (retval) |
1177c0efc TTY: pty, release... |
655 |
goto err_release; |
d81ed1030 tty: Remove more ... |
656 657 |
retval = ptm_driver->ops->open(tty, filp); |
64ba3dc31 tty: never hold B... |
658 |
if (retval) |
1177c0efc TTY: pty, release... |
659 |
goto err_release; |
64ba3dc31 tty: never hold B... |
660 |
tty_unlock(); |
1177c0efc TTY: pty, release... |
661 662 |
return 0; err_release: |
64ba3dc31 tty: never hold B... |
663 |
tty_unlock(); |
eeb89d918 tty: push the BKL... |
664 |
tty_release(inode, filp); |
d81ed1030 tty: Remove more ... |
665 666 |
return retval; out: |
15f1a6338 Add an instance p... |
667 |
devpts_kill_index(inode, index); |
ec79d6056 tty: replace BKL ... |
668 |
tty_unlock(); |
fa90e1c93 TTY: make tty_add... |
669 670 |
err_file: tty_free_file(filp); |
64ba3dc31 tty: never hold B... |
671 |
return retval; |
d81ed1030 tty: Remove more ... |
672 673 674 |
} static struct file_operations ptmx_fops; |
1da177e4c Linux-2.6.12-rc2 |
675 676 |
static void __init unix98_pty_init(void) { |
1da177e4c 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 [PATCH] tty: swit... |
696 697 |
ptm_driver->init_termios.c_ispeed = 38400; ptm_driver->init_termios.c_ospeed = 38400; |
1da177e4c Linux-2.6.12-rc2 |
698 |
ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | |
331b83198 [PATCH] devfs: Re... |
699 |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; |
1da177e4c Linux-2.6.12-rc2 |
700 |
ptm_driver->other = pts_driver; |
feebed651 tty: shutdown method |
701 |
tty_set_operations(ptm_driver, &ptm_unix98_ops); |
1da177e4c 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 [PATCH] tty: swit... |
712 713 |
pts_driver->init_termios.c_ispeed = 38400; pts_driver->init_termios.c_ospeed = 38400; |
1da177e4c Linux-2.6.12-rc2 |
714 |
pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | |
331b83198 [PATCH] devfs: Re... |
715 |
TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; |
1da177e4c Linux-2.6.12-rc2 |
716 |
pts_driver->other = ptm_driver; |
99f1fe189 tty: Clean up the... |
717 |
tty_set_operations(pts_driver, &pty_unix98_ops); |
fe9cd962a pty: Coding style... |
718 |
|
1da177e4c 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 pty: Coding style... |
723 |
register_sysctl_table(pty_root_table); |
d81ed1030 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 Linux-2.6.12-rc2 |
735 |
} |
d81ed1030 tty: Remove more ... |
736 |
|
1da177e4c 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); |