Blame view
drivers/tty/n_tty.c
60.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
/* * n_tty.c --- implements the N_TTY line discipline. |
4edf1827e n_tty: clean up o... |
3 |
* |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 10 |
* This code used to be in tty_io.c, but things are getting hairy * enough that it made sense to split things off. (The N_TTY * processing has changed so much that it's hardly recognizable, * anyway...) * * Note that the open routine for N_TTY is guaranteed never to return * an error. This is because Linux will fall back to setting a line |
4edf1827e n_tty: clean up o... |
11 |
* to N_TTY if it can not switch to any other line discipline. |
1da177e4c Linux-2.6.12-rc2 |
12 13 |
* * Written by Theodore Ts'o, Copyright 1994. |
4edf1827e n_tty: clean up o... |
14 |
* |
1da177e4c Linux-2.6.12-rc2 |
15 16 |
* This file also contains code originally written by Linus Torvalds, * Copyright 1991, 1992, 1993, and by Julian Cowley, Copyright 1994. |
4edf1827e n_tty: clean up o... |
17 |
* |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 21 22 |
* This file may be redistributed under the terms of the GNU General Public * License. * * Reduced memory usage for older ARM systems - Russell King. * |
4edf1827e n_tty: clean up o... |
23 |
* 2000/01/20 Fixed SMP locking on put_tty_queue using bits of |
1da177e4c Linux-2.6.12-rc2 |
24 25 26 27 28 |
* the patch by Andrew J. Kroll <ag784@freenet.buffalo.edu> * who actually finally proved there really was a race. * * 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to * waiting writing processes-Sapan Bhatia <sapan@corewars.org>. |
11a96d182 tty: rename the r... |
29 |
* Also fixed a bug in BLOCKING mode where n_tty_write returns |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
* EAGAIN */ #include <linux/types.h> #include <linux/major.h> #include <linux/errno.h> #include <linux/signal.h> #include <linux/fcntl.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/tty.h> #include <linux/timer.h> #include <linux/ctype.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/slab.h> #include <linux/poll.h> #include <linux/bitops.h> |
522ed7767 Audit: add TTY in... |
48 49 |
#include <linux/audit.h> #include <linux/file.h> |
300a6204b n_tty: clean up c... |
50 |
#include <linux/uaccess.h> |
572b9adbd ldisc n_tty: add ... |
51 |
#include <linux/module.h> |
593fb1ae4 pps: Move timesta... |
52 |
#include <linux/ratelimit.h> |
86e35aea4 n_tty: Fix build ... |
53 |
#include <linux/vmalloc.h> |
1da177e4c Linux-2.6.12-rc2 |
54 |
|
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 60 61 62 63 64 |
/* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 /* * This defines the low- and high-watermarks for throttling and * unthrottling the TTY driver. These watermarks are used for * controlling the space in the read buffer. */ #define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */ |
bbd20759d drivers/tty: Remo... |
65 |
#define TTY_THRESHOLD_UNTHROTTLE 128 |
1da177e4c Linux-2.6.12-rc2 |
66 |
|
a88a69c91 n_tty: Fix loss o... |
67 68 69 70 71 72 73 74 75 76 |
/* * Special byte codes used in the echo buffer to represent operations * or special handling of characters. Bytes in the echo buffer that * are not part of such special blocks are treated as normal character * codes. */ #define ECHO_OP_START 0xff #define ECHO_OP_MOVE_BACK_COL 0x80 #define ECHO_OP_SET_CANON_COL 0x81 #define ECHO_OP_ERASE_TAB 0x82 |
cbfd0340a n_tty: Process ec... |
77 78 79 |
#define ECHO_COMMIT_WATERMARK 256 #define ECHO_BLOCK 256 #define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32) |
32f13521c n_tty: Line copy ... |
80 81 82 83 84 85 |
#undef N_TTY_TRACE #ifdef N_TTY_TRACE # define n_tty_trace(f, args...) trace_printk(f, ##args) #else # define n_tty_trace(f, args...) #endif |
70ece7a73 TTY: n_tty, add l... |
86 |
struct n_tty_data { |
fb7aa03db n_tty: Separate b... |
87 88 |
/* producer-published */ size_t read_head; |
70aca71f9 n_tty: Fix unorde... |
89 |
size_t commit_head; |
fb7aa03db n_tty: Separate b... |
90 |
size_t canon_head; |
9dfd16dde n_tty: Avoid fals... |
91 92 |
size_t echo_head; size_t echo_commit; |
1075a6e2d n_tty: Fix appare... |
93 |
size_t echo_mark; |
1bb9d5628 n_tty: Rename pro... |
94 |
DECLARE_BITMAP(char_map, 256); |
fb7aa03db n_tty: Separate b... |
95 96 |
/* private to n_tty_receive_overrun (single-threaded) */ |
53c5ee2cf TTY: move ldisc d... |
97 98 |
unsigned long overrun_time; int num_overrun; |
24a89d1cb tty: Make ldisc i... |
99 100 |
/* non-atomic */ bool no_room; |
fb7aa03db n_tty: Separate b... |
101 |
/* must hold exclusive termios_rwsem to reset these */ |
53c5ee2cf TTY: move ldisc d... |
102 |
unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; |
4d0ed1827 n_tty: Fix buffer... |
103 |
unsigned char push:1; |
3fe780b37 TTY: move ldisc d... |
104 |
|
fb7aa03db n_tty: Separate b... |
105 |
/* shared by producer and consumer */ |
20bafb3d2 n_tty: Move buffe... |
106 |
char read_buf[N_TTY_BUF_SIZE]; |
3fe780b37 TTY: move ldisc d... |
107 |
DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); |
20bafb3d2 n_tty: Move buffe... |
108 |
unsigned char echo_buf[N_TTY_BUF_SIZE]; |
ba2e68ac6 TTY: move ldisc d... |
109 |
|
fb7aa03db n_tty: Separate b... |
110 111 |
/* consumer-published */ size_t read_tail; |
40d5e0905 n_tty: Fix EOF pu... |
112 |
size_t line_start; |
fb7aa03db n_tty: Separate b... |
113 |
|
fb7aa03db n_tty: Separate b... |
114 115 |
/* protected by output lock */ unsigned int column; |
ba2e68ac6 TTY: move ldisc d... |
116 |
unsigned int canon_column; |
9dfd16dde n_tty: Avoid fals... |
117 |
size_t echo_tail; |
bddc7152f TTY: move ldisc d... |
118 119 120 |
struct mutex atomic_read_lock; struct mutex output_lock; |
70ece7a73 TTY: n_tty, add l... |
121 |
}; |
ce74117a1 n_tty: Get read_c... |
122 123 |
static inline size_t read_cnt(struct n_tty_data *ldata) { |
a2f73be8e n_tty: Remove rea... |
124 |
return ldata->read_head - ldata->read_tail; |
ce74117a1 n_tty: Get read_c... |
125 |
} |
bc5a5e3f4 n_tty: Don't wrap... |
126 127 128 129 130 131 132 133 134 |
static inline unsigned char read_buf(struct n_tty_data *ldata, size_t i) { return ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)]; } static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i) { return &ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)]; } |
addaebccf n_tty: Use separa... |
135 136 137 138 139 140 141 142 143 |
static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) { return ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) { return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } |
679e7c299 n_tty: Uninline t... |
144 145 |
static int tty_copy_to_user(struct tty_struct *tty, void __user *to, size_t tail, size_t n) |
72586c606 n_tty: Fix auditi... |
146 147 |
{ struct n_tty_data *ldata = tty->disc_data; |
679e7c299 n_tty: Uninline t... |
148 149 150 151 152 |
size_t size = N_TTY_BUF_SIZE - tail; const void *from = read_buf_addr(ldata, tail); int uncopied; if (n > size) { |
309426ae6 tty: audit: Remov... |
153 |
tty_audit_add_data(tty, from, size); |
679e7c299 n_tty: Uninline t... |
154 155 156 157 158 159 160 |
uncopied = copy_to_user(to, from, size); if (uncopied) return uncopied; to += size; n -= size; from = ldata->read_buf; } |
72586c606 n_tty: Fix auditi... |
161 |
|
309426ae6 tty: audit: Remov... |
162 |
tty_audit_add_data(tty, from, n); |
72586c606 n_tty: Fix auditi... |
163 164 |
return copy_to_user(to, from, n); } |
24a89d1cb tty: Make ldisc i... |
165 |
/** |
2c5dc4641 n_tty: Eliminate ... |
166 |
* n_tty_kick_worker - start input worker (if required) |
24a89d1cb tty: Make ldisc i... |
167 168 |
* @tty: terminal * |
2c5dc4641 n_tty: Eliminate ... |
169 |
* Re-schedules the flip buffer work if it may have stopped |
24a89d1cb tty: Make ldisc i... |
170 |
* |
6d76bd261 n_tty: Make N_TTY... |
171 172 173 174 |
* Caller holds exclusive termios_rwsem * or * n_tty_read()/consumer path: * holds non-exclusive termios_rwsem |
24a89d1cb tty: Make ldisc i... |
175 |
*/ |
2c5dc4641 n_tty: Eliminate ... |
176 |
static void n_tty_kick_worker(struct tty_struct *tty) |
7879a9f9f n_tty: Buffer wor... |
177 |
{ |
24a89d1cb tty: Make ldisc i... |
178 |
struct n_tty_data *ldata = tty->disc_data; |
2c5dc4641 n_tty: Eliminate ... |
179 180 |
/* Did the input worker stop? Restart it */ if (unlikely(ldata->no_room)) { |
24a89d1cb tty: Make ldisc i... |
181 |
ldata->no_room = 0; |
ecbbfd44a TTY: move tty buf... |
182 |
WARN_RATELIMIT(tty->port->itty == NULL, |
cadf74869 tty: add missing ... |
183 184 |
"scheduling with invalid itty "); |
21622939f tty: Add diagnost... |
185 186 187 188 189 190 191 |
/* see if ldisc has been killed - if so, this means that * even though the ldisc has been halted and ->buf.work * cancelled, ->buf.work is about to be rescheduled */ WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags), "scheduling buffer work for halted ldisc "); |
e176058f0 tty: Abstract tty... |
192 |
tty_buffer_restart_work(tty->port); |
ecbbfd44a TTY: move tty buf... |
193 |
} |
55db4c64e Revert "tty: make... |
194 |
} |
9a4aec2dd n_tty: Move chars... |
195 196 197 198 199 200 |
static ssize_t chars_in_buffer(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; ssize_t n = 0; if (!ldata->icanon) |
70aca71f9 n_tty: Fix unorde... |
201 |
n = ldata->commit_head - ldata->read_tail; |
9a4aec2dd n_tty: Move chars... |
202 203 204 205 |
else n = ldata->canon_head - ldata->read_tail; return n; } |
ee0bab83c n_tty: Move n_tty... |
206 207 208 209 210 211 212 213 214 215 216 |
/** * n_tty_write_wakeup - asynchronous I/O notifier * @tty: tty device * * Required for the ptys, serial driver etc. since processes * that attach themselves to the master and rely on ASYNC * IO must be woken up */ static void n_tty_write_wakeup(struct tty_struct *tty) { |
7bccc3654 n_tty: Fix stuck ... |
217 218 |
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); kill_fasync(&tty->fasync, SIGIO, POLL_OUT); |
ee0bab83c n_tty: Move n_tty... |
219 |
} |
4a23a4df5 n_tty: Factor 're... |
220 |
static void n_tty_check_throttle(struct tty_struct *tty) |
6367ca72f n_tty: Factor thr... |
221 |
{ |
a342846f9 n_tty: Fix thrott... |
222 |
struct n_tty_data *ldata = tty->disc_data; |
6367ca72f n_tty: Factor thr... |
223 224 225 226 227 |
/* * Check the remaining room for the input canonicalization * mode. We don't want to throttle the driver if we're in * canonical mode and don't have a newline yet! */ |
a342846f9 n_tty: Fix thrott... |
228 229 |
if (ldata->icanon && ldata->canon_head == ldata->read_tail) return; |
6367ca72f n_tty: Factor thr... |
230 231 232 |
while (1) { int throttled; tty_set_flow_change(tty, TTY_THROTTLE_SAFE); |
5e28cca15 n_tty: Simplify t... |
233 |
if (N_TTY_BUF_SIZE - read_cnt(ldata) >= TTY_THRESHOLD_THROTTLE) |
6367ca72f n_tty: Factor thr... |
234 235 236 237 238 239 240 |
break; throttled = tty_throttle_safe(tty); if (!throttled) break; } __tty_set_flow_change(tty, 0); } |
4b293492a n_tty: Un-inline ... |
241 |
static void n_tty_check_unthrottle(struct tty_struct *tty) |
6367ca72f n_tty: Factor thr... |
242 |
{ |
6d27a63ca n_tty: Fix unsafe... |
243 |
if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { |
3afb1b394 n_tty: Special ca... |
244 245 |
if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) return; |
2c5dc4641 n_tty: Eliminate ... |
246 |
n_tty_kick_worker(tty); |
6d27a63ca n_tty: Fix unsafe... |
247 |
tty_wakeup(tty->link); |
3afb1b394 n_tty: Special ca... |
248 249 |
return; } |
6367ca72f n_tty: Factor thr... |
250 251 252 253 254 255 256 257 258 259 260 261 262 |
/* If there is enough space in the read buffer now, let the * low-level driver know. We use chars_in_buffer() to * check the buffer, as it now knows about canonical mode. * Otherwise, if the driver is throttled and the line is * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, * we won't get any more characters. */ while (1) { int unthrottled; tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; |
2c5dc4641 n_tty: Eliminate ... |
263 |
n_tty_kick_worker(tty); |
6367ca72f n_tty: Factor thr... |
264 265 266 267 268 269 |
unthrottled = tty_unthrottle_safe(tty); if (!unthrottled) break; } __tty_set_flow_change(tty, 0); } |
17b820606 tty: Minor tidyup... |
270 271 272 |
/** * put_tty_queue - add character to tty * @c: character |
57c941212 TTY: n_tty, propa... |
273 |
* @ldata: n_tty data |
17b820606 tty: Minor tidyup... |
274 |
* |
6d76bd261 n_tty: Make N_TTY... |
275 276 277 278 |
* Add a character to the tty read_buf queue. * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem |
17b820606 tty: Minor tidyup... |
279 |
*/ |
19e2ad6a0 n_tty: Remove ove... |
280 |
static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) |
1da177e4c Linux-2.6.12-rc2 |
281 |
{ |
8bfbe2de7 n_tty: Fix read_b... |
282 283 |
*read_buf_addr(ldata, ldata->read_head) = c; ldata->read_head++; |
1da177e4c Linux-2.6.12-rc2 |
284 285 286 |
} /** |
1da177e4c Linux-2.6.12-rc2 |
287 288 289 |
* reset_buffer_flags - reset buffer state * @tty: terminal to reset * |
25518c68b n_tty: Correct un... |
290 291 |
* Reset the read buffer counters and clear the flags. * Called from n_tty_open() and n_tty_flush_buffer(). |
17b820606 tty: Minor tidyup... |
292 |
* |
6d76bd261 n_tty: Make N_TTY... |
293 294 |
* Locking: caller holds exclusive termios_rwsem * (or locking is not required) |
1da177e4c Linux-2.6.12-rc2 |
295 |
*/ |
a88a69c91 n_tty: Fix loss o... |
296 |
|
b66f4fa50 n_tty: Fully init... |
297 |
static void reset_buffer_flags(struct n_tty_data *ldata) |
1da177e4c Linux-2.6.12-rc2 |
298 |
{ |
a73d3d698 n_tty: Replace ca... |
299 |
ldata->read_head = ldata->canon_head = ldata->read_tail = 0; |
17bd79074 n_tty: Remove ech... |
300 |
ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; |
70aca71f9 n_tty: Fix unorde... |
301 |
ldata->commit_head = 0; |
1075a6e2d n_tty: Fix appare... |
302 |
ldata->echo_mark = 0; |
40d5e0905 n_tty: Fix EOF pu... |
303 |
ldata->line_start = 0; |
a88a69c91 n_tty: Fix loss o... |
304 |
|
a73d3d698 n_tty: Replace ca... |
305 |
ldata->erasing = 0; |
3fe780b37 TTY: move ldisc d... |
306 |
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); |
4d0ed1827 n_tty: Fix buffer... |
307 |
ldata->push = 0; |
1da177e4c Linux-2.6.12-rc2 |
308 |
} |
a30737ab7 n_tty: Factor pac... |
309 310 311 |
static void n_tty_packet_mode_flush(struct tty_struct *tty) { unsigned long flags; |
a30737ab7 n_tty: Factor pac... |
312 |
if (tty->link->packet) { |
54e8e5fca pty: Don't claim ... |
313 |
spin_lock_irqsave(&tty->ctrl_lock, flags); |
a30737ab7 n_tty: Factor pac... |
314 |
tty->ctrl_status |= TIOCPKT_FLUSHREAD; |
54e8e5fca pty: Don't claim ... |
315 |
spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
e81107d4c tty: fix stall ca... |
316 |
wake_up_interruptible(&tty->link->read_wait); |
a30737ab7 n_tty: Factor pac... |
317 |
} |
a30737ab7 n_tty: Factor pac... |
318 |
} |
1da177e4c Linux-2.6.12-rc2 |
319 320 321 322 |
/** * n_tty_flush_buffer - clean input queue * @tty: terminal device * |
25518c68b n_tty: Correct un... |
323 324 325 |
* Flush the input buffer. Called when the tty layer wants the * buffer flushed (eg at hangup) or when the N_TTY line discipline * internally has to clean the pending queue (for example some signals). |
1da177e4c Linux-2.6.12-rc2 |
326 |
* |
6d76bd261 n_tty: Make N_TTY... |
327 328 329 330 |
* Holds termios_rwsem to exclude producer/consumer while * buffer indices are reset. * * Locking: ctrl_lock, exclusive termios_rwsem |
1da177e4c Linux-2.6.12-rc2 |
331 |
*/ |
4edf1827e n_tty: clean up o... |
332 333 |
static void n_tty_flush_buffer(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
334 |
{ |
6d76bd261 n_tty: Make N_TTY... |
335 |
down_write(&tty->termios_rwsem); |
b66f4fa50 n_tty: Fully init... |
336 |
reset_buffer_flags(tty->disc_data); |
2c5dc4641 n_tty: Eliminate ... |
337 |
n_tty_kick_worker(tty); |
4edf1827e n_tty: clean up o... |
338 |
|
a30737ab7 n_tty: Factor pac... |
339 340 |
if (tty->link) n_tty_packet_mode_flush(tty); |
6d76bd261 n_tty: Make N_TTY... |
341 |
up_write(&tty->termios_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
342 |
} |
6d76bd261 n_tty: Make N_TTY... |
343 |
/** |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 347 348 349 350 |
* is_utf8_continuation - utf8 multibyte check * @c: byte to check * * Returns true if the utf8 character 'c' is a multibyte continuation * character. We use this to correctly compute the on screen size * of the character when printing */ |
4edf1827e n_tty: clean up o... |
351 |
|
1da177e4c Linux-2.6.12-rc2 |
352 353 354 355 356 357 358 359 360 361 362 363 |
static inline int is_utf8_continuation(unsigned char c) { return (c & 0xc0) == 0x80; } /** * is_continuation - multibyte check * @c: byte to check * * Returns true if the utf8 character 'c' is a multibyte continuation * character and the terminal is in unicode mode. */ |
4edf1827e n_tty: clean up o... |
364 |
|
1da177e4c Linux-2.6.12-rc2 |
365 366 367 368 369 370 |
static inline int is_continuation(unsigned char c, struct tty_struct *tty) { return I_IUTF8(tty) && is_utf8_continuation(c); } /** |
a88a69c91 n_tty: Fix loss o... |
371 |
* do_output_char - output one character |
1da177e4c Linux-2.6.12-rc2 |
372 373 |
* @c: character (or partial unicode symbol) * @tty: terminal device |
a88a69c91 n_tty: Fix loss o... |
374 |
* @space: space available in tty driver write buffer |
1da177e4c Linux-2.6.12-rc2 |
375 |
* |
a88a69c91 n_tty: Fix loss o... |
376 377 |
* This is a helper function that handles one output character * (including special characters like TAB, CR, LF, etc.), |
ee5aa7b8b n_tty: honor opos... |
378 379 |
* doing OPOST processing and putting the results in the * tty driver's write buffer. |
a88a69c91 n_tty: Fix loss o... |
380 381 382 383 |
* * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY * and NLDLY. They simply aren't relevant in the world today. * If you ever need them, add them here. |
1da177e4c Linux-2.6.12-rc2 |
384 |
* |
a88a69c91 n_tty: Fix loss o... |
385 386 387 388 389 |
* Returns the number of bytes of buffer space used or -1 if * no space left. * * Locking: should be called under the output_lock to protect * the column state and space left in the buffer |
1da177e4c Linux-2.6.12-rc2 |
390 |
*/ |
4edf1827e n_tty: clean up o... |
391 |
|
a88a69c91 n_tty: Fix loss o... |
392 |
static int do_output_char(unsigned char c, struct tty_struct *tty, int space) |
1da177e4c Linux-2.6.12-rc2 |
393 |
{ |
53c5ee2cf TTY: move ldisc d... |
394 |
struct n_tty_data *ldata = tty->disc_data; |
a88a69c91 n_tty: Fix loss o... |
395 |
int spaces; |
1da177e4c Linux-2.6.12-rc2 |
396 |
|
1da177e4c Linux-2.6.12-rc2 |
397 398 |
if (!space) return -1; |
300a6204b n_tty: clean up c... |
399 |
|
a88a69c91 n_tty: Fix loss o... |
400 401 402 403 |
switch (c) { case ' ': if (O_ONLRET(tty)) |
53c5ee2cf TTY: move ldisc d... |
404 |
ldata->column = 0; |
a88a69c91 n_tty: Fix loss o... |
405 406 407 |
if (O_ONLCR(tty)) { if (space < 2) return -1; |
ba2e68ac6 TTY: move ldisc d... |
408 |
ldata->canon_column = ldata->column = 0; |
37f81fa1f n_tty: do O_ONLCR... |
409 410 |
tty->ops->write(tty, "\r ", 2); |
a88a69c91 n_tty: Fix loss o... |
411 412 |
return 2; } |
ba2e68ac6 TTY: move ldisc d... |
413 |
ldata->canon_column = ldata->column; |
a88a69c91 n_tty: Fix loss o... |
414 415 |
break; case '\r': |
53c5ee2cf TTY: move ldisc d... |
416 |
if (O_ONOCR(tty) && ldata->column == 0) |
a88a69c91 n_tty: Fix loss o... |
417 418 419 420 421 |
return 0; if (O_OCRNL(tty)) { c = ' '; if (O_ONLRET(tty)) |
ba2e68ac6 TTY: move ldisc d... |
422 |
ldata->canon_column = ldata->column = 0; |
1da177e4c Linux-2.6.12-rc2 |
423 |
break; |
a88a69c91 n_tty: Fix loss o... |
424 |
} |
ba2e68ac6 TTY: move ldisc d... |
425 |
ldata->canon_column = ldata->column = 0; |
a88a69c91 n_tty: Fix loss o... |
426 427 |
break; case '\t': |
53c5ee2cf TTY: move ldisc d... |
428 |
spaces = 8 - (ldata->column & 7); |
a88a69c91 n_tty: Fix loss o... |
429 430 431 |
if (O_TABDLY(tty) == XTABS) { if (space < spaces) return -1; |
53c5ee2cf TTY: move ldisc d... |
432 |
ldata->column += spaces; |
a88a69c91 n_tty: Fix loss o... |
433 434 |
tty->ops->write(tty, " ", spaces); return spaces; |
1da177e4c Linux-2.6.12-rc2 |
435 |
} |
53c5ee2cf TTY: move ldisc d... |
436 |
ldata->column += spaces; |
a88a69c91 n_tty: Fix loss o... |
437 438 |
break; case '\b': |
53c5ee2cf TTY: move ldisc d... |
439 440 |
if (ldata->column > 0) ldata->column--; |
a88a69c91 n_tty: Fix loss o... |
441 442 |
break; default: |
a59c0d6f1 n_tty: Fix handli... |
443 444 445 446 |
if (!iscntrl(c)) { if (O_OLCUC(tty)) c = toupper(c); if (!is_continuation(c, tty)) |
53c5ee2cf TTY: move ldisc d... |
447 |
ldata->column++; |
a59c0d6f1 n_tty: Fix handli... |
448 |
} |
a88a69c91 n_tty: Fix loss o... |
449 |
break; |
1da177e4c Linux-2.6.12-rc2 |
450 |
} |
a88a69c91 n_tty: Fix loss o... |
451 |
|
f34d7a5b7 tty: The big oper... |
452 |
tty_put_char(tty, c); |
a88a69c91 n_tty: Fix loss o... |
453 454 455 456 457 458 459 460 |
return 1; } /** * process_output - output post processor * @c: character (or partial unicode symbol) * @tty: terminal device * |
ee5aa7b8b n_tty: honor opos... |
461 462 463 |
* Output one character with OPOST processing. * Returns -1 when the output device is full and the character * must be retried. |
a88a69c91 n_tty: Fix loss o... |
464 465 466 467 468 469 470 471 |
* * Locking: output_lock to protect column state and space left * (also, this is called from n_tty_write under the * tty layer write lock) */ static int process_output(unsigned char c, struct tty_struct *tty) { |
bddc7152f TTY: move ldisc d... |
472 |
struct n_tty_data *ldata = tty->disc_data; |
a88a69c91 n_tty: Fix loss o... |
473 |
int space, retval; |
bddc7152f TTY: move ldisc d... |
474 |
mutex_lock(&ldata->output_lock); |
a88a69c91 n_tty: Fix loss o... |
475 476 477 |
space = tty_write_room(tty); retval = do_output_char(c, tty, space); |
bddc7152f TTY: move ldisc d... |
478 |
mutex_unlock(&ldata->output_lock); |
a88a69c91 n_tty: Fix loss o... |
479 480 481 482 |
if (retval < 0) return -1; else return 0; |
1da177e4c Linux-2.6.12-rc2 |
483 484 485 |
} /** |
a88a69c91 n_tty: Fix loss o... |
486 |
* process_output_block - block post processor |
1da177e4c Linux-2.6.12-rc2 |
487 |
* @tty: terminal device |
ee5aa7b8b n_tty: honor opos... |
488 489 490 491 492 |
* @buf: character buffer * @nr: number of bytes to output * * Output a block of characters with OPOST processing. * Returns the number of characters output. |
1da177e4c Linux-2.6.12-rc2 |
493 494 495 496 497 498 |
* * This path is used to speed up block console writes, among other * things when processing blocks of output data. It handles only * the simple cases normally found and helps to generate blocks of * symbols for the console driver and thus improve performance. * |
a88a69c91 n_tty: Fix loss o... |
499 500 501 |
* Locking: output_lock to protect column state and space left * (also, this is called from n_tty_write under the * tty layer write lock) |
1da177e4c Linux-2.6.12-rc2 |
502 |
*/ |
4edf1827e n_tty: clean up o... |
503 |
|
a88a69c91 n_tty: Fix loss o... |
504 505 |
static ssize_t process_output_block(struct tty_struct *tty, const unsigned char *buf, unsigned int nr) |
1da177e4c Linux-2.6.12-rc2 |
506 |
{ |
53c5ee2cf TTY: move ldisc d... |
507 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
508 |
int space; |
bbd20759d drivers/tty: Remo... |
509 |
int i; |
1da177e4c Linux-2.6.12-rc2 |
510 |
const unsigned char *cp; |
bddc7152f TTY: move ldisc d... |
511 |
mutex_lock(&ldata->output_lock); |
a88a69c91 n_tty: Fix loss o... |
512 |
|
f34d7a5b7 tty: The big oper... |
513 |
space = tty_write_room(tty); |
300a6204b n_tty: clean up c... |
514 |
if (!space) { |
bddc7152f TTY: move ldisc d... |
515 |
mutex_unlock(&ldata->output_lock); |
1da177e4c Linux-2.6.12-rc2 |
516 |
return 0; |
a88a69c91 n_tty: Fix loss o... |
517 |
} |
1da177e4c Linux-2.6.12-rc2 |
518 519 520 521 |
if (nr > space) nr = space; for (i = 0, cp = buf; i < nr; i++, cp++) { |
a59c0d6f1 n_tty: Fix handli... |
522 523 524 |
unsigned char c = *cp; switch (c) { |
1da177e4c Linux-2.6.12-rc2 |
525 526 527 |
case ' ': if (O_ONLRET(tty)) |
53c5ee2cf TTY: move ldisc d... |
528 |
ldata->column = 0; |
1da177e4c Linux-2.6.12-rc2 |
529 530 |
if (O_ONLCR(tty)) goto break_out; |
ba2e68ac6 TTY: move ldisc d... |
531 |
ldata->canon_column = ldata->column; |
1da177e4c Linux-2.6.12-rc2 |
532 533 |
break; case '\r': |
53c5ee2cf TTY: move ldisc d... |
534 |
if (O_ONOCR(tty) && ldata->column == 0) |
1da177e4c Linux-2.6.12-rc2 |
535 536 537 |
goto break_out; if (O_OCRNL(tty)) goto break_out; |
ba2e68ac6 TTY: move ldisc d... |
538 |
ldata->canon_column = ldata->column = 0; |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 542 |
break; case '\t': goto break_out; case '\b': |
53c5ee2cf TTY: move ldisc d... |
543 544 |
if (ldata->column > 0) ldata->column--; |
1da177e4c Linux-2.6.12-rc2 |
545 546 |
break; default: |
a59c0d6f1 n_tty: Fix handli... |
547 548 549 550 |
if (!iscntrl(c)) { if (O_OLCUC(tty)) goto break_out; if (!is_continuation(c, tty)) |
53c5ee2cf TTY: move ldisc d... |
551 |
ldata->column++; |
a59c0d6f1 n_tty: Fix handli... |
552 |
} |
1da177e4c Linux-2.6.12-rc2 |
553 554 555 556 |
break; } } break_out: |
f34d7a5b7 tty: The big oper... |
557 |
i = tty->ops->write(tty, buf, i); |
a88a69c91 n_tty: Fix loss o... |
558 |
|
bddc7152f TTY: move ldisc d... |
559 |
mutex_unlock(&ldata->output_lock); |
1da177e4c Linux-2.6.12-rc2 |
560 561 |
return i; } |
a88a69c91 n_tty: Fix loss o... |
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
/** * process_echoes - write pending echo characters * @tty: terminal device * * Write previously buffered echo (and other ldisc-generated) * characters to the tty. * * Characters generated by the ldisc (including echoes) need to * be buffered because the driver's write buffer can fill during * heavy program output. Echoing straight to the driver will * often fail under these conditions, causing lost characters and * resulting mismatches of ldisc state information. * * Since the ldisc state must represent the characters actually sent * to the driver at the time of the write, operations like certain * changes in column state are also saved in the buffer and executed * here. * * A circular fifo buffer is used so that the most recent characters * are prioritized. Also, when control characters are echoed with a * prefixed "^", the pair is treated atomically and thus not separated. * |
019ebdf9f n_tty: Eliminate ... |
584 |
* Locking: callers must hold output_lock |
a88a69c91 n_tty: Fix loss o... |
585 |
*/ |
bc5b1ec58 n_tty: Only flush... |
586 |
static size_t __process_echoes(struct tty_struct *tty) |
a88a69c91 n_tty: Fix loss o... |
587 |
{ |
53c5ee2cf TTY: move ldisc d... |
588 |
struct n_tty_data *ldata = tty->disc_data; |
bc5b1ec58 n_tty: Only flush... |
589 |
int space, old_space; |
addaebccf n_tty: Use separa... |
590 |
size_t tail; |
a88a69c91 n_tty: Fix loss o... |
591 |
unsigned char c; |
a88a69c91 n_tty: Fix loss o... |
592 |
|
bc5b1ec58 n_tty: Only flush... |
593 |
old_space = space = tty_write_room(tty); |
a88a69c91 n_tty: Fix loss o... |
594 |
|
addaebccf n_tty: Use separa... |
595 |
tail = ldata->echo_tail; |
29c7c5ca3 n_tty: Eliminate ... |
596 |
while (ldata->echo_commit != tail) { |
addaebccf n_tty: Use separa... |
597 |
c = echo_buf(ldata, tail); |
a88a69c91 n_tty: Fix loss o... |
598 599 |
if (c == ECHO_OP_START) { unsigned char op; |
a88a69c91 n_tty: Fix loss o... |
600 601 602 603 604 605 606 |
int no_space_left = 0; /* * If the buffer byte is the start of a multi-byte * operation, get the next byte, which is either the * op code or a control character value. */ |
addaebccf n_tty: Use separa... |
607 |
op = echo_buf(ldata, tail + 1); |
300a6204b n_tty: clean up c... |
608 |
|
a88a69c91 n_tty: Fix loss o... |
609 610 611 612 |
switch (op) { unsigned int num_chars, num_bs; case ECHO_OP_ERASE_TAB: |
addaebccf n_tty: Use separa... |
613 |
num_chars = echo_buf(ldata, tail + 2); |
a88a69c91 n_tty: Fix loss o... |
614 615 616 617 618 619 620 621 622 623 624 625 |
/* * Determine how many columns to go back * in order to erase the tab. * This depends on the number of columns * used by other characters within the tab * area. If this (modulo 8) count is from * the start of input rather than from a * previous tab, we offset by canon column. * Otherwise, tab spacing is normal. */ if (!(num_chars & 0x80)) |
ba2e68ac6 TTY: move ldisc d... |
626 |
num_chars += ldata->canon_column; |
a88a69c91 n_tty: Fix loss o... |
627 628 629 630 631 632 633 634 635 |
num_bs = 8 - (num_chars & 7); if (num_bs > space) { no_space_left = 1; break; } space -= num_bs; while (num_bs--) { tty_put_char(tty, '\b'); |
53c5ee2cf TTY: move ldisc d... |
636 637 |
if (ldata->column > 0) ldata->column--; |
a88a69c91 n_tty: Fix loss o... |
638 |
} |
addaebccf n_tty: Use separa... |
639 |
tail += 3; |
a88a69c91 n_tty: Fix loss o... |
640 641 642 |
break; case ECHO_OP_SET_CANON_COL: |
ba2e68ac6 TTY: move ldisc d... |
643 |
ldata->canon_column = ldata->column; |
addaebccf n_tty: Use separa... |
644 |
tail += 2; |
a88a69c91 n_tty: Fix loss o... |
645 646 647 |
break; case ECHO_OP_MOVE_BACK_COL: |
53c5ee2cf TTY: move ldisc d... |
648 649 |
if (ldata->column > 0) ldata->column--; |
addaebccf n_tty: Use separa... |
650 |
tail += 2; |
a88a69c91 n_tty: Fix loss o... |
651 652 653 654 655 656 657 658 659 |
break; case ECHO_OP_START: /* This is an escaped echo op start code */ if (!space) { no_space_left = 1; break; } tty_put_char(tty, ECHO_OP_START); |
53c5ee2cf TTY: move ldisc d... |
660 |
ldata->column++; |
a88a69c91 n_tty: Fix loss o... |
661 |
space--; |
addaebccf n_tty: Use separa... |
662 |
tail += 2; |
a88a69c91 n_tty: Fix loss o... |
663 664 665 |
break; default: |
a88a69c91 n_tty: Fix loss o... |
666 |
/* |
62b263585 n_tty: move echoc... |
667 668 669 670 671 672 673 |
* If the op is not a special byte code, * it is a ctrl char tagged to be echoed * as "^X" (where X is the letter * representing the control char). * Note that we must ensure there is * enough space for the whole ctrl pair. * |
a88a69c91 n_tty: Fix loss o... |
674 |
*/ |
62b263585 n_tty: move echoc... |
675 676 677 678 679 680 |
if (space < 2) { no_space_left = 1; break; } tty_put_char(tty, '^'); tty_put_char(tty, op ^ 0100); |
53c5ee2cf TTY: move ldisc d... |
681 |
ldata->column += 2; |
62b263585 n_tty: move echoc... |
682 |
space -= 2; |
addaebccf n_tty: Use separa... |
683 |
tail += 2; |
a88a69c91 n_tty: Fix loss o... |
684 685 686 687 688 |
} if (no_space_left) break; } else { |
582f55907 tty: Remove TTY_H... |
689 |
if (O_OPOST(tty)) { |
ee5aa7b8b n_tty: honor opos... |
690 691 692 693 694 695 696 697 698 699 |
int retval = do_output_char(c, tty, space); if (retval < 0) break; space -= retval; } else { if (!space) break; tty_put_char(tty, c); space -= 1; } |
addaebccf n_tty: Use separa... |
700 |
tail += 1; |
a88a69c91 n_tty: Fix loss o... |
701 |
} |
a88a69c91 n_tty: Fix loss o... |
702 |
} |
cbfd0340a n_tty: Process ec... |
703 704 705 706 |
/* If the echo buffer is nearly full (so that the possibility exists * of echo overrun before the next commit), then discard enough * data at the tail to prevent a subsequent overrun */ while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { |
c476f6584 tty: incorrect te... |
707 |
if (echo_buf(ldata, tail) == ECHO_OP_START) { |
6f2225363 n_tty: Fix echo o... |
708 |
if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB) |
cbfd0340a n_tty: Process ec... |
709 710 711 712 713 714 |
tail += 3; else tail += 2; } else tail++; } |
addaebccf n_tty: Use separa... |
715 |
ldata->echo_tail = tail; |
bc5b1ec58 n_tty: Only flush... |
716 |
return old_space - space; |
019ebdf9f n_tty: Eliminate ... |
717 718 719 720 721 |
} static void commit_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; |
bc5b1ec58 n_tty: Only flush... |
722 |
size_t nr, old, echoed; |
cbfd0340a n_tty: Process ec... |
723 724 725 |
size_t head; head = ldata->echo_head; |
1075a6e2d n_tty: Fix appare... |
726 |
ldata->echo_mark = head; |
cbfd0340a n_tty: Process ec... |
727 728 729 730 731 732 733 734 |
old = ldata->echo_commit - ldata->echo_tail; /* Process committed echoes if the accumulated # of bytes * is over the threshold (and try again each time another * block is accumulated) */ nr = head - ldata->echo_tail; if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) return; |
a88a69c91 n_tty: Fix loss o... |
735 |
|
019ebdf9f n_tty: Eliminate ... |
736 |
mutex_lock(&ldata->output_lock); |
cbfd0340a n_tty: Process ec... |
737 |
ldata->echo_commit = head; |
bc5b1ec58 n_tty: Only flush... |
738 |
echoed = __process_echoes(tty); |
bddc7152f TTY: move ldisc d... |
739 |
mutex_unlock(&ldata->output_lock); |
a88a69c91 n_tty: Fix loss o... |
740 |
|
bc5b1ec58 n_tty: Only flush... |
741 |
if (echoed && tty->ops->flush_chars) |
a88a69c91 n_tty: Fix loss o... |
742 743 |
tty->ops->flush_chars(tty); } |
019ebdf9f n_tty: Eliminate ... |
744 |
static void process_echoes(struct tty_struct *tty) |
17bd79074 n_tty: Remove ech... |
745 746 |
{ struct n_tty_data *ldata = tty->disc_data; |
bc5b1ec58 n_tty: Only flush... |
747 |
size_t echoed; |
17bd79074 n_tty: Remove ech... |
748 |
|
e2613be50 n_tty: Fix stale ... |
749 |
if (ldata->echo_mark == ldata->echo_tail) |
019ebdf9f n_tty: Eliminate ... |
750 751 752 |
return; mutex_lock(&ldata->output_lock); |
1075a6e2d n_tty: Fix appare... |
753 |
ldata->echo_commit = ldata->echo_mark; |
bc5b1ec58 n_tty: Only flush... |
754 |
echoed = __process_echoes(tty); |
019ebdf9f n_tty: Eliminate ... |
755 |
mutex_unlock(&ldata->output_lock); |
bc5b1ec58 n_tty: Only flush... |
756 |
if (echoed && tty->ops->flush_chars) |
019ebdf9f n_tty: Eliminate ... |
757 |
tty->ops->flush_chars(tty); |
17bd79074 n_tty: Remove ech... |
758 |
} |
1075a6e2d n_tty: Fix appare... |
759 |
/* NB: echo_mark and echo_head should be equivalent here */ |
cbfd0340a n_tty: Process ec... |
760 761 762 |
static void flush_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; |
39434abd9 n_tty: Fix missin... |
763 764 |
if ((!L_ECHO(tty) && !L_ECHONL(tty)) || ldata->echo_commit == ldata->echo_head) |
cbfd0340a n_tty: Process ec... |
765 766 767 768 769 770 771 |
return; mutex_lock(&ldata->output_lock); ldata->echo_commit = ldata->echo_head; __process_echoes(tty); mutex_unlock(&ldata->output_lock); } |
a88a69c91 n_tty: Fix loss o... |
772 773 774 |
/** * add_echo_byte - add a byte to the echo buffer * @c: unicode byte to echo |
57c941212 TTY: n_tty, propa... |
775 |
* @ldata: n_tty data |
a88a69c91 n_tty: Fix loss o... |
776 777 |
* * Add a character or operation byte to the echo buffer. |
a88a69c91 n_tty: Fix loss o... |
778 |
*/ |
cbfd0340a n_tty: Process ec... |
779 |
static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) |
a88a69c91 n_tty: Fix loss o... |
780 |
{ |
addaebccf n_tty: Use separa... |
781 |
*echo_buf_addr(ldata, ldata->echo_head++) = c; |
a88a69c91 n_tty: Fix loss o... |
782 783 784 785 |
} /** * echo_move_back_col - add operation to move back a column |
57c941212 TTY: n_tty, propa... |
786 |
* @ldata: n_tty data |
a88a69c91 n_tty: Fix loss o... |
787 788 |
* * Add an operation to the echo buffer to move back one column. |
a88a69c91 n_tty: Fix loss o... |
789 |
*/ |
57c941212 TTY: n_tty, propa... |
790 |
static void echo_move_back_col(struct n_tty_data *ldata) |
a88a69c91 n_tty: Fix loss o... |
791 |
{ |
57c941212 TTY: n_tty, propa... |
792 793 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata); |
a88a69c91 n_tty: Fix loss o... |
794 795 796 797 |
} /** * echo_set_canon_col - add operation to set the canon column |
57c941212 TTY: n_tty, propa... |
798 |
* @ldata: n_tty data |
a88a69c91 n_tty: Fix loss o... |
799 800 801 |
* * Add an operation to the echo buffer to set the canon column * to the current column. |
a88a69c91 n_tty: Fix loss o... |
802 |
*/ |
57c941212 TTY: n_tty, propa... |
803 |
static void echo_set_canon_col(struct n_tty_data *ldata) |
a88a69c91 n_tty: Fix loss o... |
804 |
{ |
57c941212 TTY: n_tty, propa... |
805 806 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_SET_CANON_COL, ldata); |
a88a69c91 n_tty: Fix loss o... |
807 808 809 810 811 812 |
} /** * echo_erase_tab - add operation to erase a tab * @num_chars: number of character columns already used * @after_tab: true if num_chars starts after a previous tab |
57c941212 TTY: n_tty, propa... |
813 |
* @ldata: n_tty data |
a88a69c91 n_tty: Fix loss o... |
814 815 816 817 818 819 820 821 |
* * Add an operation to the echo buffer to erase a tab. * * Called by the eraser function, which knows how many character * columns have been used since either a previous tab or the start * of input. This information will be used later, along with * canon column (if applicable), to go back the correct number * of columns. |
a88a69c91 n_tty: Fix loss o... |
822 823 824 |
*/ static void echo_erase_tab(unsigned int num_chars, int after_tab, |
57c941212 TTY: n_tty, propa... |
825 |
struct n_tty_data *ldata) |
a88a69c91 n_tty: Fix loss o... |
826 |
{ |
57c941212 TTY: n_tty, propa... |
827 828 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_ERASE_TAB, ldata); |
a88a69c91 n_tty: Fix loss o... |
829 830 831 832 833 834 835 |
/* We only need to know this modulo 8 (tab spacing) */ num_chars &= 7; /* Set the high bit as a flag if num_chars is after a previous tab */ if (after_tab) num_chars |= 0x80; |
300a6204b n_tty: clean up c... |
836 |
|
57c941212 TTY: n_tty, propa... |
837 |
add_echo_byte(num_chars, ldata); |
a88a69c91 n_tty: Fix loss o... |
838 839 840 841 842 843 844 845 846 847 848 |
} /** * echo_char_raw - echo a character raw * @c: unicode byte to echo * @tty: terminal device * * Echo user input back onto the screen. This must be called only when * L_ECHO(tty) is true. Called from the driver receive_buf path. * * This variant does not treat control characters specially. |
a88a69c91 n_tty: Fix loss o... |
849 |
*/ |
57c941212 TTY: n_tty, propa... |
850 |
static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) |
a88a69c91 n_tty: Fix loss o... |
851 |
{ |
a88a69c91 n_tty: Fix loss o... |
852 |
if (c == ECHO_OP_START) { |
57c941212 TTY: n_tty, propa... |
853 854 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); |
a88a69c91 n_tty: Fix loss o... |
855 |
} else { |
57c941212 TTY: n_tty, propa... |
856 |
add_echo_byte(c, ldata); |
a88a69c91 n_tty: Fix loss o... |
857 |
} |
a88a69c91 n_tty: Fix loss o... |
858 |
} |
1da177e4c Linux-2.6.12-rc2 |
859 860 |
/** |
a88a69c91 n_tty: Fix loss o... |
861 |
* echo_char - echo a character |
1da177e4c Linux-2.6.12-rc2 |
862 863 864 |
* @c: unicode byte to echo * @tty: terminal device * |
4edf1827e n_tty: clean up o... |
865 |
* Echo user input back onto the screen. This must be called only when |
1da177e4c Linux-2.6.12-rc2 |
866 |
* L_ECHO(tty) is true. Called from the driver receive_buf path. |
17b820606 tty: Minor tidyup... |
867 |
* |
62b263585 n_tty: move echoc... |
868 869 |
* This variant tags control characters to be echoed as "^X" * (where X is the letter representing the control char). |
1da177e4c Linux-2.6.12-rc2 |
870 871 872 873 |
*/ static void echo_char(unsigned char c, struct tty_struct *tty) { |
bddc7152f TTY: move ldisc d... |
874 |
struct n_tty_data *ldata = tty->disc_data; |
a88a69c91 n_tty: Fix loss o... |
875 |
if (c == ECHO_OP_START) { |
57c941212 TTY: n_tty, propa... |
876 877 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); |
a88a69c91 n_tty: Fix loss o... |
878 |
} else { |
62b263585 n_tty: move echoc... |
879 |
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') |
57c941212 TTY: n_tty, propa... |
880 881 |
add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(c, ldata); |
a88a69c91 n_tty: Fix loss o... |
882 |
} |
1da177e4c Linux-2.6.12-rc2 |
883 |
} |
17b820606 tty: Minor tidyup... |
884 |
/** |
a88a69c91 n_tty: Fix loss o... |
885 |
* finish_erasing - complete erase |
57c941212 TTY: n_tty, propa... |
886 |
* @ldata: n_tty data |
17b820606 tty: Minor tidyup... |
887 |
*/ |
a88a69c91 n_tty: Fix loss o... |
888 |
|
57c941212 TTY: n_tty, propa... |
889 |
static inline void finish_erasing(struct n_tty_data *ldata) |
1da177e4c Linux-2.6.12-rc2 |
890 |
{ |
53c5ee2cf TTY: move ldisc d... |
891 |
if (ldata->erasing) { |
57c941212 TTY: n_tty, propa... |
892 |
echo_char_raw('/', ldata); |
53c5ee2cf TTY: move ldisc d... |
893 |
ldata->erasing = 0; |
1da177e4c Linux-2.6.12-rc2 |
894 895 896 897 898 899 900 901 |
} } /** * eraser - handle erase function * @c: character input * @tty: terminal device * |
3a4fa0a25 Fix misspellings ... |
902 |
* Perform erase and necessary output when an erase character is |
1da177e4c Linux-2.6.12-rc2 |
903 904 |
* present in the stream from the driver layer. Handles the complexities * of UTF-8 multibyte symbols. |
17b820606 tty: Minor tidyup... |
905 |
* |
6d76bd261 n_tty: Make N_TTY... |
906 907 |
* n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem |
1da177e4c Linux-2.6.12-rc2 |
908 |
*/ |
4edf1827e n_tty: clean up o... |
909 |
|
1da177e4c Linux-2.6.12-rc2 |
910 911 |
static void eraser(unsigned char c, struct tty_struct *tty) { |
53c5ee2cf TTY: move ldisc d... |
912 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
913 |
enum { ERASE, WERASE, KILL } kill_type; |
bc5a5e3f4 n_tty: Don't wrap... |
914 915 916 |
size_t head; size_t cnt; int seen_alnums; |
1da177e4c Linux-2.6.12-rc2 |
917 |
|
ba2e68ac6 TTY: move ldisc d... |
918 |
if (ldata->read_head == ldata->canon_head) { |
7e94b1d9b n_tty: Output bel... |
919 |
/* process_output('\a', tty); */ /* what do you think? */ |
1da177e4c Linux-2.6.12-rc2 |
920 921 922 923 924 925 926 927 |
return; } if (c == ERASE_CHAR(tty)) kill_type = ERASE; else if (c == WERASE_CHAR(tty)) kill_type = WERASE; else { if (!L_ECHO(tty)) { |
ba2e68ac6 TTY: move ldisc d... |
928 |
ldata->read_head = ldata->canon_head; |
1da177e4c Linux-2.6.12-rc2 |
929 930 931 |
return; } if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) { |
ba2e68ac6 TTY: move ldisc d... |
932 |
ldata->read_head = ldata->canon_head; |
57c941212 TTY: n_tty, propa... |
933 |
finish_erasing(ldata); |
1da177e4c Linux-2.6.12-rc2 |
934 935 936 |
echo_char(KILL_CHAR(tty), tty); /* Add a newline if ECHOK is on and ECHOKE is off. */ if (L_ECHOK(tty)) |
57c941212 TTY: n_tty, propa... |
937 938 |
echo_char_raw(' ', ldata); |
1da177e4c Linux-2.6.12-rc2 |
939 940 941 942 943 944 |
return; } kill_type = KILL; } seen_alnums = 0; |
ba2e68ac6 TTY: move ldisc d... |
945 946 |
while (ldata->read_head != ldata->canon_head) { head = ldata->read_head; |
1da177e4c Linux-2.6.12-rc2 |
947 948 949 |
/* erase a single possibly multibyte character */ do { |
bc5a5e3f4 n_tty: Don't wrap... |
950 951 |
head--; c = read_buf(ldata, head); |
ba2e68ac6 TTY: move ldisc d... |
952 |
} while (is_continuation(c, tty) && head != ldata->canon_head); |
1da177e4c Linux-2.6.12-rc2 |
953 954 955 956 957 958 959 960 961 962 963 964 |
/* do not partially erase */ if (is_continuation(c, tty)) break; if (kill_type == WERASE) { /* Equivalent to BSD's ALTWERASE. */ if (isalnum(c) || c == '_') seen_alnums++; else if (seen_alnums) break; } |
bc5a5e3f4 n_tty: Don't wrap... |
965 |
cnt = ldata->read_head - head; |
ba2e68ac6 TTY: move ldisc d... |
966 |
ldata->read_head = head; |
1da177e4c Linux-2.6.12-rc2 |
967 968 |
if (L_ECHO(tty)) { if (L_ECHOPRT(tty)) { |
53c5ee2cf TTY: move ldisc d... |
969 |
if (!ldata->erasing) { |
57c941212 TTY: n_tty, propa... |
970 |
echo_char_raw('\\', ldata); |
53c5ee2cf TTY: move ldisc d... |
971 |
ldata->erasing = 1; |
1da177e4c Linux-2.6.12-rc2 |
972 973 974 975 |
} /* if cnt > 1, output a multi-byte character */ echo_char(c, tty); while (--cnt > 0) { |
bc5a5e3f4 n_tty: Don't wrap... |
976 977 |
head++; echo_char_raw(read_buf(ldata, head), ldata); |
57c941212 TTY: n_tty, propa... |
978 |
echo_move_back_col(ldata); |
1da177e4c Linux-2.6.12-rc2 |
979 980 981 982 |
} } else if (kill_type == ERASE && !L_ECHOE(tty)) { echo_char(ERASE_CHAR(tty), tty); } else if (c == '\t') { |
a88a69c91 n_tty: Fix loss o... |
983 984 |
unsigned int num_chars = 0; int after_tab = 0; |
bc5a5e3f4 n_tty: Don't wrap... |
985 |
size_t tail = ldata->read_head; |
a88a69c91 n_tty: Fix loss o... |
986 987 988 989 990 991 992 993 |
/* * Count the columns used for characters * since the start of input or after a * previous tab. * This info is used to go back the correct * number of columns. */ |
ba2e68ac6 TTY: move ldisc d... |
994 |
while (tail != ldata->canon_head) { |
bc5a5e3f4 n_tty: Don't wrap... |
995 996 |
tail--; c = read_buf(ldata, tail); |
a88a69c91 n_tty: Fix loss o... |
997 998 999 |
if (c == '\t') { after_tab = 1; break; |
300a6204b n_tty: clean up c... |
1000 |
} else if (iscntrl(c)) { |
1da177e4c Linux-2.6.12-rc2 |
1001 |
if (L_ECHOCTL(tty)) |
a88a69c91 n_tty: Fix loss o... |
1002 1003 1004 1005 |
num_chars += 2; } else if (!is_continuation(c, tty)) { num_chars++; } |
1da177e4c Linux-2.6.12-rc2 |
1006 |
} |
57c941212 TTY: n_tty, propa... |
1007 |
echo_erase_tab(num_chars, after_tab, ldata); |
1da177e4c Linux-2.6.12-rc2 |
1008 1009 |
} else { if (iscntrl(c) && L_ECHOCTL(tty)) { |
57c941212 TTY: n_tty, propa... |
1010 1011 1012 |
echo_char_raw('\b', ldata); echo_char_raw(' ', ldata); echo_char_raw('\b', ldata); |
1da177e4c Linux-2.6.12-rc2 |
1013 1014 |
} if (!iscntrl(c) || L_ECHOCTL(tty)) { |
57c941212 TTY: n_tty, propa... |
1015 1016 1017 |
echo_char_raw('\b', ldata); echo_char_raw(' ', ldata); echo_char_raw('\b', ldata); |
1da177e4c Linux-2.6.12-rc2 |
1018 1019 1020 1021 1022 1023 |
} } } if (kill_type == ERASE) break; } |
ba2e68ac6 TTY: move ldisc d... |
1024 |
if (ldata->read_head == ldata->canon_head && L_ECHO(tty)) |
57c941212 TTY: n_tty, propa... |
1025 |
finish_erasing(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1026 1027 1028 1029 1030 1031 |
} /** * isig - handle the ISIG optio * @sig: signal * @tty: terminal |
1da177e4c Linux-2.6.12-rc2 |
1032 |
* |
8c985d18b n_tty: Fix unsafe... |
1033 1034 |
* Called when a signal is being sent due to terminal input. * Called from the driver receive_buf path so serialized. |
17b820606 tty: Minor tidyup... |
1035 |
* |
d2b6f4477 n_tty: Fix signal... |
1036 1037 1038 1039 |
* Performs input and output flush if !NOFLSH. In this context, the echo * buffer is 'output'. The signal is processed first to alert any current * readers or writers to discontinue and exit their i/o loops. * |
8c985d18b n_tty: Fix unsafe... |
1040 |
* Locking: ctrl_lock |
1da177e4c Linux-2.6.12-rc2 |
1041 |
*/ |
4edf1827e n_tty: clean up o... |
1042 |
|
3b19e0322 n_tty: signal and... |
1043 |
static void __isig(int sig, struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1044 |
{ |
8c985d18b n_tty: Fix unsafe... |
1045 1046 1047 1048 |
struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { kill_pgrp(tty_pgrp, sig, 1); put_pid(tty_pgrp); |
1da177e4c Linux-2.6.12-rc2 |
1049 |
} |
3b19e0322 n_tty: signal and... |
1050 |
} |
d2b6f4477 n_tty: Fix signal... |
1051 |
|
3b19e0322 n_tty: signal and... |
1052 1053 1054 1055 1056 1057 1058 1059 1060 |
static void isig(int sig, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; if (L_NOFLSH(tty)) { /* signal only */ __isig(sig, tty); } else { /* signal and flush */ |
d2b6f4477 n_tty: Fix signal... |
1061 1062 |
up_read(&tty->termios_rwsem); down_write(&tty->termios_rwsem); |
3b19e0322 n_tty: signal and... |
1063 |
__isig(sig, tty); |
d2b6f4477 n_tty: Fix signal... |
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
/* clear echo buffer */ mutex_lock(&ldata->output_lock); ldata->echo_head = ldata->echo_tail = 0; ldata->echo_mark = ldata->echo_commit = 0; mutex_unlock(&ldata->output_lock); /* clear output buffer */ tty_driver_flush_buffer(tty); /* clear input buffer */ reset_buffer_flags(tty->disc_data); /* notify pty master of flush */ if (tty->link) n_tty_packet_mode_flush(tty); up_write(&tty->termios_rwsem); down_read(&tty->termios_rwsem); } |
1da177e4c Linux-2.6.12-rc2 |
1083 1084 1085 1086 1087 1088 1089 1090 1091 |
} /** * n_tty_receive_break - handle break * @tty: terminal * * An RS232 break event has been hit in the incoming bitstream. This * can cause a variety of events depending upon the termios settings. * |
6d76bd261 n_tty: Make N_TTY... |
1092 1093 |
* n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem |
6d76bd261 n_tty: Make N_TTY... |
1094 1095 |
* * Note: may get exclusive termios_rwsem if flushing input buffer |
1da177e4c Linux-2.6.12-rc2 |
1096 |
*/ |
4edf1827e n_tty: clean up o... |
1097 |
|
4b293492a n_tty: Un-inline ... |
1098 |
static void n_tty_receive_break(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1099 |
{ |
57c941212 TTY: n_tty, propa... |
1100 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
1101 1102 1103 |
if (I_IGNBRK(tty)) return; if (I_BRKINT(tty)) { |
8c985d18b n_tty: Fix unsafe... |
1104 |
isig(SIGINT, tty); |
1da177e4c Linux-2.6.12-rc2 |
1105 1106 1107 |
return; } if (I_PARMRK(tty)) { |
57c941212 TTY: n_tty, propa... |
1108 1109 |
put_tty_queue('\377', ldata); put_tty_queue('\0', ldata); |
1da177e4c Linux-2.6.12-rc2 |
1110 |
} |
57c941212 TTY: n_tty, propa... |
1111 |
put_tty_queue('\0', ldata); |
1da177e4c Linux-2.6.12-rc2 |
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 |
} /** * n_tty_receive_overrun - handle overrun reporting * @tty: terminal * * Data arrived faster than we could process it. While the tty * driver has flagged this the bits that were missed are gone * forever. * * Called from the receive_buf path so single threaded. Does not * need locking as num_overrun and overrun_time are function * private. */ |
4edf1827e n_tty: clean up o... |
1126 |
|
4b293492a n_tty: Un-inline ... |
1127 |
static void n_tty_receive_overrun(struct tty_struct *tty) |
1da177e4c Linux-2.6.12-rc2 |
1128 |
{ |
53c5ee2cf TTY: move ldisc d... |
1129 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
1130 |
|
53c5ee2cf TTY: move ldisc d... |
1131 1132 1133 |
ldata->num_overrun++; if (time_after(jiffies, ldata->overrun_time + HZ) || time_after(ldata->overrun_time, jiffies)) { |
339f36ba1 tty: Define tty_*... |
1134 1135 |
tty_warn(tty, "%d input overrun(s) ", ldata->num_overrun); |
53c5ee2cf TTY: move ldisc d... |
1136 1137 |
ldata->overrun_time = jiffies; ldata->num_overrun = 0; |
1da177e4c Linux-2.6.12-rc2 |
1138 1139 1140 1141 1142 1143 1144 1145 1146 |
} } /** * n_tty_receive_parity_error - error notifier * @tty: terminal device * @c: character * * Process a parity error and queue the right data to indicate |
6d76bd261 n_tty: Make N_TTY... |
1147 1148 1149 1150 |
* the error case if necessary. * * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem |
1da177e4c Linux-2.6.12-rc2 |
1151 |
*/ |
4b293492a n_tty: Un-inline ... |
1152 |
static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) |
1da177e4c Linux-2.6.12-rc2 |
1153 |
{ |
57c941212 TTY: n_tty, propa... |
1154 |
struct n_tty_data *ldata = tty->disc_data; |
66528f906 tty: Correct INPC... |
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 |
if (I_INPCK(tty)) { if (I_IGNPAR(tty)) return; if (I_PARMRK(tty)) { put_tty_queue('\377', ldata); put_tty_queue('\0', ldata); put_tty_queue(c, ldata); } else put_tty_queue('\0', ldata); } else |
57c941212 TTY: n_tty, propa... |
1165 |
put_tty_queue(c, ldata); |
1da177e4c Linux-2.6.12-rc2 |
1166 |
} |
b0ac50be1 n_tty: Factor sig... |
1167 1168 1169 |
static void n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) { |
d2b6f4477 n_tty: Fix signal... |
1170 |
isig(signal, tty); |
b0ac50be1 n_tty: Factor sig... |
1171 1172 1173 1174 1175 |
if (I_IXON(tty)) start_tty(tty); if (L_ECHO(tty)) { echo_char(c, tty); commit_echoes(tty); |
e2613be50 n_tty: Fix stale ... |
1176 1177 |
} else process_echoes(tty); |
b0ac50be1 n_tty: Factor sig... |
1178 1179 |
return; } |
1da177e4c Linux-2.6.12-rc2 |
1180 1181 1182 1183 1184 1185 |
/** * n_tty_receive_char - perform processing * @tty: terminal device * @c: character * * Process an individual character of input received from the driver. |
4edf1827e n_tty: clean up o... |
1186 |
* This is serialized with respect to itself by the rules for the |
1da177e4c Linux-2.6.12-rc2 |
1187 |
* driver above. |
6d76bd261 n_tty: Make N_TTY... |
1188 1189 1190 1191 |
* * n_tty_receive_buf()/producer path: * caller holds non-exclusive termios_rwsem * publishes canon_head if canonical mode is active |
e60d27c4d n_tty: Factor LNE... |
1192 1193 |
* * Returns 1 if LNEXT was received, else returns 0 |
1da177e4c Linux-2.6.12-rc2 |
1194 |
*/ |
e60d27c4d n_tty: Factor LNE... |
1195 |
static int |
4b1f79c2d n_tty: Split n_tt... |
1196 |
n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) |
1da177e4c Linux-2.6.12-rc2 |
1197 |
{ |
53c5ee2cf TTY: move ldisc d... |
1198 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
1199 |
|
1da177e4c Linux-2.6.12-rc2 |
1200 1201 1202 |
if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); |
e2613be50 n_tty: Fix stale ... |
1203 |
process_echoes(tty); |
e60d27c4d n_tty: Factor LNE... |
1204 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1205 1206 1207 |
} if (c == STOP_CHAR(tty)) { stop_tty(tty); |
e60d27c4d n_tty: Factor LNE... |
1208 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1209 1210 |
} } |
575537b32 Resume TTY on SUS... |
1211 |
|
1da177e4c Linux-2.6.12-rc2 |
1212 |
if (L_ISIG(tty)) { |
b0ac50be1 n_tty: Factor sig... |
1213 1214 |
if (c == INTR_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGINT, c); |
e60d27c4d n_tty: Factor LNE... |
1215 |
return 0; |
b0ac50be1 n_tty: Factor sig... |
1216 1217 |
} else if (c == QUIT_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGQUIT, c); |
e60d27c4d n_tty: Factor LNE... |
1218 |
return 0; |
b0ac50be1 n_tty: Factor sig... |
1219 1220 |
} else if (c == SUSP_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGTSTP, c); |
e60d27c4d n_tty: Factor LNE... |
1221 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1222 1223 |
} } |
575537b32 Resume TTY on SUS... |
1224 |
|
855df3c08 n_tty: Eliminate ... |
1225 1226 1227 1228 |
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } |
575537b32 Resume TTY on SUS... |
1229 1230 |
if (c == '\r') { if (I_IGNCR(tty)) |
e60d27c4d n_tty: Factor LNE... |
1231 |
return 0; |
575537b32 Resume TTY on SUS... |
1232 1233 1234 1235 1236 1237 |
if (I_ICRNL(tty)) c = ' '; } else if (c == ' ' && I_INLCR(tty)) c = '\r'; |
53c5ee2cf TTY: move ldisc d... |
1238 |
if (ldata->icanon) { |
1da177e4c Linux-2.6.12-rc2 |
1239 1240 1241 |
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); |
17bd79074 n_tty: Remove ech... |
1242 |
commit_echoes(tty); |
e60d27c4d n_tty: Factor LNE... |
1243 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1244 1245 |
} if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { |
53c5ee2cf TTY: move ldisc d... |
1246 |
ldata->lnext = 1; |
1da177e4c Linux-2.6.12-rc2 |
1247 |
if (L_ECHO(tty)) { |
57c941212 TTY: n_tty, propa... |
1248 |
finish_erasing(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1249 |
if (L_ECHOCTL(tty)) { |
57c941212 TTY: n_tty, propa... |
1250 1251 |
echo_char_raw('^', ldata); echo_char_raw('\b', ldata); |
17bd79074 n_tty: Remove ech... |
1252 |
commit_echoes(tty); |
1da177e4c Linux-2.6.12-rc2 |
1253 1254 |
} } |
e60d27c4d n_tty: Factor LNE... |
1255 |
return 1; |
1da177e4c Linux-2.6.12-rc2 |
1256 |
} |
e60d27c4d n_tty: Factor LNE... |
1257 |
if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { |
bc5a5e3f4 n_tty: Don't wrap... |
1258 |
size_t tail = ldata->canon_head; |
1da177e4c Linux-2.6.12-rc2 |
1259 |
|
57c941212 TTY: n_tty, propa... |
1260 |
finish_erasing(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1261 |
echo_char(c, tty); |
57c941212 TTY: n_tty, propa... |
1262 1263 |
echo_char_raw(' ', ldata); |
ba2e68ac6 TTY: move ldisc d... |
1264 |
while (tail != ldata->read_head) { |
bc5a5e3f4 n_tty: Don't wrap... |
1265 1266 |
echo_char(read_buf(ldata, tail), tty); tail++; |
1da177e4c Linux-2.6.12-rc2 |
1267 |
} |
17bd79074 n_tty: Remove ech... |
1268 |
commit_echoes(tty); |
e60d27c4d n_tty: Factor LNE... |
1269 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1270 1271 1272 |
} if (c == ' ') { |
acc71bbad n_tty: Fix hanfli... |
1273 |
if (L_ECHO(tty) || L_ECHONL(tty)) { |
57c941212 TTY: n_tty, propa... |
1274 1275 |
echo_char_raw(' ', ldata); |
17bd79074 n_tty: Remove ech... |
1276 |
commit_echoes(tty); |
1da177e4c Linux-2.6.12-rc2 |
1277 1278 1279 1280 |
} goto handle_newline; } if (c == EOF_CHAR(tty)) { |
1da177e4c Linux-2.6.12-rc2 |
1281 1282 1283 1284 1285 1286 1287 1288 1289 |
c = __DISABLED_CHAR; goto handle_newline; } if ((c == EOL_CHAR(tty)) || (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { /* * XXX are EOL_CHAR and EOL2_CHAR echoed?!? */ if (L_ECHO(tty)) { |
1da177e4c Linux-2.6.12-rc2 |
1290 |
/* Record the column of first canon char. */ |
ba2e68ac6 TTY: move ldisc d... |
1291 |
if (ldata->canon_head == ldata->read_head) |
57c941212 TTY: n_tty, propa... |
1292 |
echo_set_canon_col(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1293 |
echo_char(c, tty); |
17bd79074 n_tty: Remove ech... |
1294 |
commit_echoes(tty); |
1da177e4c Linux-2.6.12-rc2 |
1295 1296 1297 1298 1299 |
} /* * XXX does PARMRK doubling happen for * EOL_CHAR and EOL2_CHAR? */ |
001ba9237 n_tty: Refactor P... |
1300 |
if (c == (unsigned char) '\377' && I_PARMRK(tty)) |
57c941212 TTY: n_tty, propa... |
1301 |
put_tty_queue(c, ldata); |
1da177e4c Linux-2.6.12-rc2 |
1302 |
|
4edf1827e n_tty: clean up o... |
1303 |
handle_newline: |
bc5a5e3f4 n_tty: Don't wrap... |
1304 |
set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); |
6d76bd261 n_tty: Make N_TTY... |
1305 |
put_tty_queue(c, ldata); |
70aca71f9 n_tty: Fix unorde... |
1306 |
smp_store_release(&ldata->canon_head, ldata->read_head); |
1da177e4c Linux-2.6.12-rc2 |
1307 |
kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
e81107d4c tty: fix stall ca... |
1308 |
wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
e60d27c4d n_tty: Factor LNE... |
1309 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1310 1311 |
} } |
4edf1827e n_tty: clean up o... |
1312 |
|
acc71bbad n_tty: Fix hanfli... |
1313 |
if (L_ECHO(tty)) { |
57c941212 TTY: n_tty, propa... |
1314 |
finish_erasing(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1315 1316 |
if (c == ' ') |
57c941212 TTY: n_tty, propa... |
1317 1318 |
echo_char_raw(' ', ldata); |
1da177e4c Linux-2.6.12-rc2 |
1319 1320 |
else { /* Record the column of first canon char. */ |
ba2e68ac6 TTY: move ldisc d... |
1321 |
if (ldata->canon_head == ldata->read_head) |
57c941212 TTY: n_tty, propa... |
1322 |
echo_set_canon_col(ldata); |
1da177e4c Linux-2.6.12-rc2 |
1323 1324 |
echo_char(c, tty); } |
17bd79074 n_tty: Remove ech... |
1325 |
commit_echoes(tty); |
1da177e4c Linux-2.6.12-rc2 |
1326 |
} |
001ba9237 n_tty: Refactor P... |
1327 1328 |
/* PARMRK doubling check */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) |
57c941212 TTY: n_tty, propa... |
1329 |
put_tty_queue(c, ldata); |
1da177e4c Linux-2.6.12-rc2 |
1330 |
|
57c941212 TTY: n_tty, propa... |
1331 |
put_tty_queue(c, ldata); |
e60d27c4d n_tty: Factor LNE... |
1332 |
return 0; |
4edf1827e n_tty: clean up o... |
1333 |
} |
1da177e4c Linux-2.6.12-rc2 |
1334 |
|
e60d27c4d n_tty: Factor LNE... |
1335 1336 |
static inline void n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) |
4b1f79c2d n_tty: Split n_tt... |
1337 1338 |
{ struct n_tty_data *ldata = tty->disc_data; |
4b1f79c2d n_tty: Split n_tt... |
1339 |
|
e60d27c4d n_tty: Factor LNE... |
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 |
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); } if (L_ECHO(tty)) { finish_erasing(ldata); /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) echo_set_canon_col(ldata); echo_char(c, tty); commit_echoes(tty); |
4b1f79c2d n_tty: Split n_tt... |
1351 |
} |
001ba9237 n_tty: Refactor P... |
1352 1353 |
/* PARMRK doubling check */ if (c == (unsigned char) '\377' && I_PARMRK(tty)) |
e60d27c4d n_tty: Factor LNE... |
1354 1355 1356 |
put_tty_queue(c, ldata); put_tty_queue(c, ldata); } |
4b1f79c2d n_tty: Split n_tt... |
1357 |
|
eb3e4668b n_tty: Un-inline ... |
1358 |
static void n_tty_receive_char(struct tty_struct *tty, unsigned char c) |
e60d27c4d n_tty: Factor LNE... |
1359 1360 |
{ n_tty_receive_char_inline(tty, c); |
4b1f79c2d n_tty: Split n_tt... |
1361 |
} |
ad0cc7baf n_tty: Factor tty... |
1362 |
static inline void |
7de971b05 n_tty: Factor PAR... |
1363 1364 1365 |
n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; |
e60d27c4d n_tty: Factor LNE... |
1366 1367 1368 |
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { start_tty(tty); process_echoes(tty); |
7de971b05 n_tty: Factor PAR... |
1369 |
} |
e60d27c4d n_tty: Factor LNE... |
1370 1371 1372 1373 1374 1375 1376 1377 1378 |
if (L_ECHO(tty)) { finish_erasing(ldata); /* Record the column of first canon char. */ if (ldata->canon_head == ldata->read_head) echo_set_canon_col(ldata); echo_char(c, tty); commit_echoes(tty); } put_tty_queue(c, ldata); |
7de971b05 n_tty: Factor PAR... |
1379 |
} |
8dc4b25d2 n_tty: Un-inline ... |
1380 |
static void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) |
ad0cc7baf n_tty: Factor tty... |
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 |
{ if (I_ISTRIP(tty)) c &= 0x7f; if (I_IUCLC(tty) && L_IEXTEN(tty)) c = tolower(c); if (I_IXON(tty)) { if (c == STOP_CHAR(tty)) stop_tty(tty); else if (c == START_CHAR(tty) || (tty->stopped && !tty->flow_stopped && I_IXANY(tty) && c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty))) { start_tty(tty); process_echoes(tty); } } } |
d2f8d7abd n_tty: Factor fla... |
1399 1400 1401 |
static void n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag) { |
d2f8d7abd n_tty: Factor fla... |
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 |
switch (flag) { case TTY_BREAK: n_tty_receive_break(tty); break; case TTY_PARITY: case TTY_FRAME: n_tty_receive_parity_error(tty, c); break; case TTY_OVERRUN: n_tty_receive_overrun(tty); break; default: |
339f36ba1 tty: Define tty_*... |
1414 1415 |
tty_err(tty, "unknown flag %d ", flag); |
d2f8d7abd n_tty: Factor fla... |
1416 1417 1418 |
break; } } |
e60d27c4d n_tty: Factor LNE... |
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 |
static void n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) { struct n_tty_data *ldata = tty->disc_data; ldata->lnext = 0; if (likely(flag == TTY_NORMAL)) { if (I_ISTRIP(tty)) c &= 0x7f; if (I_IUCLC(tty) && L_IEXTEN(tty)) c = tolower(c); n_tty_receive_char(tty, c); } else n_tty_receive_char_flagged(tty, c, flag); } |
4a23a4df5 n_tty: Factor 're... |
1434 1435 1436 1437 1438 1439 1440 1441 |
static void n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; size_t n, head; head = ldata->read_head & (N_TTY_BUF_SIZE - 1); |
70aca71f9 n_tty: Fix unorde... |
1442 |
n = min_t(size_t, count, N_TTY_BUF_SIZE - head); |
4a23a4df5 n_tty: Factor 're... |
1443 1444 1445 1446 1447 1448 |
memcpy(read_buf_addr(ldata, head), cp, n); ldata->read_head += n; cp += n; count -= n; head = ldata->read_head & (N_TTY_BUF_SIZE - 1); |
70aca71f9 n_tty: Fix unorde... |
1449 |
n = min_t(size_t, count, N_TTY_BUF_SIZE - head); |
4a23a4df5 n_tty: Factor 're... |
1450 1451 1452 |
memcpy(read_buf_addr(ldata, head), cp, n); ldata->read_head += n; } |
554117bdc n_tty: Factor raw... |
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 |
static void n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; while (count--) { if (fp) flag = *fp++; if (likely(flag == TTY_NORMAL)) put_tty_queue(*cp++, ldata); else n_tty_receive_char_flagged(tty, *cp++, flag); } } |
ad0cc7baf n_tty: Factor tty... |
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
static void n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { char flag = TTY_NORMAL; while (count--) { if (fp) flag = *fp++; if (likely(flag == TTY_NORMAL)) n_tty_receive_char_closing(tty, *cp++); |
ad0cc7baf n_tty: Factor tty... |
1480 1481 |
} } |
7d88d637a n_tty: Factor sta... |
1482 1483 |
static void n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, |
6baad0086 n_tty: Factor IST... |
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 |
char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; while (count--) { if (fp) flag = *fp++; if (likely(flag == TTY_NORMAL)) { unsigned char c = *cp++; if (I_ISTRIP(tty)) c &= 0x7f; if (I_IUCLC(tty) && L_IEXTEN(tty)) c = tolower(c); if (L_EXTPROC(tty)) { put_tty_queue(c, ldata); continue; } |
e60d27c4d n_tty: Factor LNE... |
1503 1504 1505 1506 1507 1508 1509 1510 |
if (!test_bit(c, ldata->char_map)) n_tty_receive_char_inline(tty, c); else if (n_tty_receive_char_special(tty, c) && count) { if (fp) flag = *fp++; n_tty_receive_char_lnext(tty, *cp++, flag); count--; } |
6baad0086 n_tty: Factor IST... |
1511 1512 1513 1514 1515 1516 1517 1518 |
} else n_tty_receive_char_flagged(tty, *cp++, flag); } } static void n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) |
7d88d637a n_tty: Factor sta... |
1519 |
{ |
e60d27c4d n_tty: Factor LNE... |
1520 |
struct n_tty_data *ldata = tty->disc_data; |
7d88d637a n_tty: Factor sta... |
1521 1522 1523 1524 1525 |
char flag = TTY_NORMAL; while (count--) { if (fp) flag = *fp++; |
e60d27c4d n_tty: Factor LNE... |
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 |
if (likely(flag == TTY_NORMAL)) { unsigned char c = *cp++; if (!test_bit(c, ldata->char_map)) n_tty_receive_char_fast(tty, c); else if (n_tty_receive_char_special(tty, c) && count) { if (fp) flag = *fp++; n_tty_receive_char_lnext(tty, *cp++, flag); count--; } } else |
7d88d637a n_tty: Factor sta... |
1538 1539 1540 |
n_tty_receive_char_flagged(tty, *cp++, flag); } } |
24a89d1cb tty: Make ldisc i... |
1541 1542 |
static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) |
1da177e4c Linux-2.6.12-rc2 |
1543 |
{ |
53c5ee2cf TTY: move ldisc d... |
1544 |
struct n_tty_data *ldata = tty->disc_data; |
a1dd30e9b n_tty: Special ca... |
1545 |
bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty)); |
1da177e4c Linux-2.6.12-rc2 |
1546 |
|
4a23a4df5 n_tty: Factor 're... |
1547 1548 |
if (ldata->real_raw) n_tty_receive_buf_real_raw(tty, cp, fp, count); |
a1dd30e9b n_tty: Special ca... |
1549 |
else if (ldata->raw || (L_EXTPROC(tty) && !preops)) |
554117bdc n_tty: Factor raw... |
1550 |
n_tty_receive_buf_raw(tty, cp, fp, count); |
ad0cc7baf n_tty: Factor tty... |
1551 1552 |
else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); |
4a23a4df5 n_tty: Factor 're... |
1553 |
else { |
e60d27c4d n_tty: Factor LNE... |
1554 1555 1556 1557 1558 1559 1560 1561 |
if (ldata->lnext) { char flag = TTY_NORMAL; if (fp) flag = *fp++; n_tty_receive_char_lnext(tty, *cp++, flag); count--; } |
7de971b05 n_tty: Factor PAR... |
1562 |
if (!preops && !I_PARMRK(tty)) |
6baad0086 n_tty: Factor IST... |
1563 1564 1565 |
n_tty_receive_buf_fast(tty, cp, fp, count); else n_tty_receive_buf_standard(tty, cp, fp, count); |
cbfd0340a n_tty: Process ec... |
1566 1567 |
flush_echoes(tty); |
f34d7a5b7 tty: The big oper... |
1568 1569 |
if (tty->ops->flush_chars) tty->ops->flush_chars(tty); |
1da177e4c Linux-2.6.12-rc2 |
1570 |
} |
70aca71f9 n_tty: Fix unorde... |
1571 1572 1573 1574 1575 |
if (ldata->icanon && !L_EXTPROC(tty)) return; /* publish read_head to consumer */ smp_store_release(&ldata->commit_head, ldata->read_head); |
33d713633 n_tty: Always wak... |
1576 |
if (read_cnt(ldata)) { |
1da177e4c Linux-2.6.12-rc2 |
1577 |
kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
e81107d4c tty: fix stall ca... |
1578 |
wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
1da177e4c Linux-2.6.12-rc2 |
1579 |
} |
1da177e4c Linux-2.6.12-rc2 |
1580 |
} |
fb5ef9e7d n_tty: Fix read b... |
1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 |
/** * n_tty_receive_buf_common - process input * @tty: device to receive input * @cp: input chars * @fp: flags for each char (if NULL, all chars are TTY_NORMAL) * @count: number of input chars in @cp * * Called by the terminal driver when a block of characters has * been received. This function must be called from soft contexts * not from interrupt context. The driver is responsible for making * calls one at a time and in order (or using flush_to_ldisc) * * Returns the # of input chars from @cp which were processed. * * In canonical mode, the maximum line length is 4096 chars (including * the line termination char); lines longer than 4096 chars are * truncated. After 4095 chars, input data is still processed but * not stored. Overflow processing ensures the tty can always * receive more input until at least one line can be read. * * In non-canonical mode, the read buffer will only accept 4095 chars; * this provides the necessary space for a newline char if the input * mode is switched to canonical. * * Note it is possible for the read buffer to _contain_ 4096 chars * in non-canonical mode: the read buffer could already contain the * maximum canon line of 4096 chars when the mode is switched to * non-canonical. * * n_tty_receive_buf()/producer path: * claims non-exclusive termios_rwsem * publishes commit_head or canon_head */ |
5c32d1237 n_tty: Merge .rec... |
1614 1615 1616 |
static int n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, char *fp, int count, int flow) |
24a89d1cb tty: Make ldisc i... |
1617 1618 |
{ struct n_tty_data *ldata = tty->disc_data; |
fb5ef9e7d n_tty: Fix read b... |
1619 |
int room, n, rcvd = 0, overflow; |
24a89d1cb tty: Make ldisc i... |
1620 |
|
9356b535f n_tty: Access ter... |
1621 |
down_read(&tty->termios_rwsem); |
19e2ad6a0 n_tty: Remove ove... |
1622 |
while (1) { |
70aca71f9 n_tty: Fix unorde... |
1623 |
/* |
06c49f9fa n_tty: Fix PARMRK... |
1624 1625 |
* When PARMRK is set, each input char may take up to 3 chars * in the read buf; reduce the buffer space avail by 3x |
70aca71f9 n_tty: Fix unorde... |
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 |
* * If we are doing input canonicalization, and there are no * pending newlines, let characters through without limit, so * that erase characters will be handled. Other excess * characters will be beeped. * * paired with store in *_copy_from_read_buf() -- guarantees * the consumer has loaded the data in read_buf up to the new * read_tail (so this producer will not overwrite unread data) */ size_t tail = smp_load_acquire(&ldata->read_tail); |
70aca71f9 n_tty: Fix unorde... |
1637 |
|
fb5ef9e7d n_tty: Fix read b... |
1638 |
room = N_TTY_BUF_SIZE - (ldata->read_head - tail); |
70aca71f9 n_tty: Fix unorde... |
1639 |
if (I_PARMRK(tty)) |
fb5ef9e7d n_tty: Fix read b... |
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 |
room = (room + 2) / 3; room--; if (room <= 0) { overflow = ldata->icanon && ldata->canon_head == tail; if (overflow && room < 0) ldata->read_head--; room = overflow; ldata->no_room = flow && !room; } else overflow = 0; |
70aca71f9 n_tty: Fix unorde... |
1650 |
|
19e2ad6a0 n_tty: Remove ove... |
1651 |
n = min(count, room); |
fb5ef9e7d n_tty: Fix read b... |
1652 |
if (!n) |
19e2ad6a0 n_tty: Remove ove... |
1653 |
break; |
fb5ef9e7d n_tty: Fix read b... |
1654 1655 1656 1657 |
/* ignore parity errors if handling overflow */ if (!overflow || !fp || *fp != TTY_PARITY) __receive_buf(tty, cp, fp, n); |
19e2ad6a0 n_tty: Remove ove... |
1658 1659 1660 1661 1662 |
cp += n; if (fp) fp += n; count -= n; rcvd += n; |
4a23a4df5 n_tty: Factor 're... |
1663 |
} |
24a89d1cb tty: Make ldisc i... |
1664 |
|
19e2ad6a0 n_tty: Remove ove... |
1665 |
tty->receive_room = room; |
fb5ef9e7d n_tty: Fix read b... |
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 |
/* Unthrottle if handling overflow on pty */ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { if (overflow) { tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); tty_unthrottle_safe(tty); __tty_set_flow_change(tty, 0); } } else n_tty_check_throttle(tty); |
9356b535f n_tty: Access ter... |
1676 |
up_read(&tty->termios_rwsem); |
19e2ad6a0 n_tty: Remove ove... |
1677 |
return rcvd; |
24a89d1cb tty: Make ldisc i... |
1678 |
} |
5c32d1237 n_tty: Merge .rec... |
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 |
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { n_tty_receive_buf_common(tty, cp, fp, count, 0); } static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { return n_tty_receive_buf_common(tty, cp, fp, count, 1); } |
1da177e4c Linux-2.6.12-rc2 |
1690 1691 1692 1693 1694 1695 1696 |
/** * n_tty_set_termios - termios data changed * @tty: terminal * @old: previous data * * Called by the tty layer when the user changes termios flags so * that the line discipline can plan ahead. This function cannot sleep |
4edf1827e n_tty: clean up o... |
1697 |
* and is protected from re-entry by the tty layer. The user is |
1da177e4c Linux-2.6.12-rc2 |
1698 1699 |
* guaranteed that this function will not be re-entered or in progress * when the ldisc is closed. |
17b820606 tty: Minor tidyup... |
1700 |
* |
6a1c0680c tty: Convert term... |
1701 |
* Locking: Caller holds tty->termios_rwsem |
1da177e4c Linux-2.6.12-rc2 |
1702 |
*/ |
4edf1827e n_tty: clean up o... |
1703 1704 |
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) |
1da177e4c Linux-2.6.12-rc2 |
1705 |
{ |
53c5ee2cf TTY: move ldisc d... |
1706 |
struct n_tty_data *ldata = tty->disc_data; |
47afa7a5a tty: some ICANON ... |
1707 |
|
c786f74e0 n_tty: Remove unn... |
1708 |
if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) { |
3fe780b37 TTY: move ldisc d... |
1709 |
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); |
4d0ed1827 n_tty: Fix buffer... |
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 |
ldata->line_start = ldata->read_tail; if (!L_ICANON(tty) || !read_cnt(ldata)) { ldata->canon_head = ldata->read_tail; ldata->push = 0; } else { set_bit((ldata->read_head - 1) & (N_TTY_BUF_SIZE - 1), ldata->read_flags); ldata->canon_head = ldata->read_head; ldata->push = 1; } |
70aca71f9 n_tty: Fix unorde... |
1720 |
ldata->commit_head = ldata->read_head; |
53c5ee2cf TTY: move ldisc d... |
1721 |
ldata->erasing = 0; |
6f9b028a8 n_tty: Reset lnex... |
1722 |
ldata->lnext = 0; |
47afa7a5a tty: some ICANON ... |
1723 |
} |
53c5ee2cf TTY: move ldisc d... |
1724 |
ldata->icanon = (L_ICANON(tty) != 0); |
582f55907 tty: Remove TTY_H... |
1725 |
|
1da177e4c Linux-2.6.12-rc2 |
1726 1727 1728 1729 |
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || I_PARMRK(tty)) { |
1bb9d5628 n_tty: Rename pro... |
1730 |
bitmap_zero(ldata->char_map, 256); |
1da177e4c Linux-2.6.12-rc2 |
1731 1732 |
if (I_IGNCR(tty) || I_ICRNL(tty)) |
1bb9d5628 n_tty: Rename pro... |
1733 |
set_bit('\r', ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1734 |
if (I_INLCR(tty)) |
1bb9d5628 n_tty: Rename pro... |
1735 1736 |
set_bit(' ', ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1737 1738 |
if (L_ICANON(tty)) { |
1bb9d5628 n_tty: Rename pro... |
1739 1740 1741 1742 1743 1744 |
set_bit(ERASE_CHAR(tty), ldata->char_map); set_bit(KILL_CHAR(tty), ldata->char_map); set_bit(EOF_CHAR(tty), ldata->char_map); set_bit(' ', ldata->char_map); set_bit(EOL_CHAR(tty), ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1745 |
if (L_IEXTEN(tty)) { |
1bb9d5628 n_tty: Rename pro... |
1746 1747 1748 |
set_bit(WERASE_CHAR(tty), ldata->char_map); set_bit(LNEXT_CHAR(tty), ldata->char_map); set_bit(EOL2_CHAR(tty), ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1749 1750 |
if (L_ECHO(tty)) set_bit(REPRINT_CHAR(tty), |
1bb9d5628 n_tty: Rename pro... |
1751 |
ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1752 1753 1754 |
} } if (I_IXON(tty)) { |
1bb9d5628 n_tty: Rename pro... |
1755 1756 |
set_bit(START_CHAR(tty), ldata->char_map); set_bit(STOP_CHAR(tty), ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1757 1758 |
} if (L_ISIG(tty)) { |
1bb9d5628 n_tty: Rename pro... |
1759 1760 1761 |
set_bit(INTR_CHAR(tty), ldata->char_map); set_bit(QUIT_CHAR(tty), ldata->char_map); set_bit(SUSP_CHAR(tty), ldata->char_map); |
1da177e4c Linux-2.6.12-rc2 |
1762 |
} |
1bb9d5628 n_tty: Rename pro... |
1763 |
clear_bit(__DISABLED_CHAR, ldata->char_map); |
53c5ee2cf TTY: move ldisc d... |
1764 1765 |
ldata->raw = 0; ldata->real_raw = 0; |
1da177e4c Linux-2.6.12-rc2 |
1766 |
} else { |
53c5ee2cf TTY: move ldisc d... |
1767 |
ldata->raw = 1; |
1da177e4c Linux-2.6.12-rc2 |
1768 1769 1770 |
if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) && (I_IGNPAR(tty) || !I_INPCK(tty)) && (tty->driver->flags & TTY_DRIVER_REAL_RAW)) |
53c5ee2cf TTY: move ldisc d... |
1771 |
ldata->real_raw = 1; |
1da177e4c Linux-2.6.12-rc2 |
1772 |
else |
53c5ee2cf TTY: move ldisc d... |
1773 |
ldata->real_raw = 0; |
1da177e4c Linux-2.6.12-rc2 |
1774 |
} |
dab73b4eb TTY: Fix tty miss... |
1775 1776 1777 1778 |
/* * Fix tty hang when I_IXON(tty) is cleared, but the tty * been stopped by STOP_CHAR(tty) before it. */ |
e2613be50 n_tty: Fix stale ... |
1779 |
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { |
dab73b4eb TTY: Fix tty miss... |
1780 |
start_tty(tty); |
e2613be50 n_tty: Fix stale ... |
1781 1782 |
process_echoes(tty); } |
dab73b4eb TTY: Fix tty miss... |
1783 |
|
f34d7a5b7 tty: The big oper... |
1784 |
/* The termios change make the tty ready for I/O */ |
e81107d4c tty: fix stall ca... |
1785 1786 |
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); |
1da177e4c Linux-2.6.12-rc2 |
1787 1788 1789 1790 1791 1792 |
} /** * n_tty_close - close the ldisc for this tty * @tty: device * |
4edf1827e n_tty: clean up o... |
1793 1794 |
* Called from the terminal layer when this line discipline is * being shut down, either because of a close or becsuse of a |
1da177e4c Linux-2.6.12-rc2 |
1795 1796 1797 |
* discipline change. The function will not be called while other * ldisc methods are in progress. */ |
4edf1827e n_tty: clean up o... |
1798 |
|
1da177e4c Linux-2.6.12-rc2 |
1799 1800 |
static void n_tty_close(struct tty_struct *tty) { |
70ece7a73 TTY: n_tty, add l... |
1801 |
struct n_tty_data *ldata = tty->disc_data; |
79901317c n_tty: Don't flus... |
1802 1803 |
if (tty->link) n_tty_packet_mode_flush(tty); |
20bafb3d2 n_tty: Move buffe... |
1804 |
vfree(ldata); |
70ece7a73 TTY: n_tty, add l... |
1805 |
tty->disc_data = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1806 1807 1808 1809 1810 1811 |
} /** * n_tty_open - open an ldisc * @tty: terminal to open * |
4edf1827e n_tty: clean up o... |
1812 |
* Called when this line discipline is being attached to the |
1da177e4c Linux-2.6.12-rc2 |
1813 1814 1815 1816 1817 1818 1819 |
* terminal device. Can sleep. Called serialized so that no * other events will occur in parallel. No further open will occur * until a close. */ static int n_tty_open(struct tty_struct *tty) { |
70ece7a73 TTY: n_tty, add l... |
1820 |
struct n_tty_data *ldata; |
20bafb3d2 n_tty: Move buffe... |
1821 1822 |
/* Currently a malloc failure here can panic */ ldata = vmalloc(sizeof(*ldata)); |
70ece7a73 TTY: n_tty, add l... |
1823 1824 |
if (!ldata) goto err; |
53c5ee2cf TTY: move ldisc d... |
1825 |
ldata->overrun_time = jiffies; |
bddc7152f TTY: move ldisc d... |
1826 1827 |
mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); |
53c5ee2cf TTY: move ldisc d... |
1828 |
|
70ece7a73 TTY: n_tty, add l... |
1829 |
tty->disc_data = ldata; |
b66f4fa50 n_tty: Fully init... |
1830 |
reset_buffer_flags(tty->disc_data); |
53c5ee2cf TTY: move ldisc d... |
1831 |
ldata->column = 0; |
20bafb3d2 n_tty: Move buffe... |
1832 |
ldata->canon_column = 0; |
20bafb3d2 n_tty: Move buffe... |
1833 1834 1835 |
ldata->num_overrun = 0; ldata->no_room = 0; ldata->lnext = 0; |
1da177e4c Linux-2.6.12-rc2 |
1836 |
tty->closing = 0; |
b66f4fa50 n_tty: Fully init... |
1837 1838 1839 1840 |
/* indicate buffer work may resume */ clear_bit(TTY_LDISC_HALTED, &tty->flags); n_tty_set_termios(tty, NULL); tty_unthrottle(tty); |
70ece7a73 TTY: n_tty, add l... |
1841 |
|
1da177e4c Linux-2.6.12-rc2 |
1842 |
return 0; |
70ece7a73 TTY: n_tty, add l... |
1843 |
err: |
b91939f52 TTY: n_tty, simpl... |
1844 |
return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
1845 |
} |
eafbe67f8 n_tty: Refactor i... |
1846 |
static inline int input_available_p(struct tty_struct *tty, int poll) |
1da177e4c Linux-2.6.12-rc2 |
1847 |
{ |
53c5ee2cf TTY: move ldisc d... |
1848 |
struct n_tty_data *ldata = tty->disc_data; |
a5934804a n_tty: Fix poll()... |
1849 |
int amt = poll && !TIME_CHAR(tty) && MIN_CHAR(tty) ? MIN_CHAR(tty) : 1; |
53c5ee2cf TTY: move ldisc d... |
1850 |
|
25e8d0ed7 n_tty: Simplify i... |
1851 1852 1853 |
if (ldata->icanon && !L_EXTPROC(tty)) return ldata->canon_head != ldata->read_tail; else |
70aca71f9 n_tty: Fix unorde... |
1854 |
return ldata->commit_head - ldata->read_tail >= amt; |
1da177e4c Linux-2.6.12-rc2 |
1855 1856 1857 |
} /** |
bbd20759d drivers/tty: Remo... |
1858 |
* copy_from_read_buf - copy read data directly |
1da177e4c Linux-2.6.12-rc2 |
1859 1860 1861 1862 |
* @tty: terminal device * @b: user data * @nr: size of data * |
11a96d182 tty: rename the r... |
1863 |
* Helper function to speed up n_tty_read. It is only called when |
1da177e4c Linux-2.6.12-rc2 |
1864 1865 1866 1867 1868 1869 |
* ICANON is off; it copies characters straight from the tty queue to * user space directly. It can be profitably called twice; once to * drain the space from the tail pointer to the (physical) end of the * buffer, and once to drain the space from the (physical) beginning of * the buffer to head pointer. * |
bddc7152f TTY: move ldisc d... |
1870 |
* Called under the ldata->atomic_read_lock sem |
1da177e4c Linux-2.6.12-rc2 |
1871 |
* |
6d76bd261 n_tty: Make N_TTY... |
1872 1873 1874 |
* n_tty_read()/consumer path: * caller holds non-exclusive termios_rwsem * read_tail published |
1da177e4c Linux-2.6.12-rc2 |
1875 |
*/ |
4edf1827e n_tty: clean up o... |
1876 |
|
33f0f88f1 [PATCH] TTY layer... |
1877 |
static int copy_from_read_buf(struct tty_struct *tty, |
1da177e4c Linux-2.6.12-rc2 |
1878 1879 1880 1881 |
unsigned char __user **b, size_t *nr) { |
53c5ee2cf TTY: move ldisc d... |
1882 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
1883 1884 |
int retval; size_t n; |
3fa10cc83 TTY: n_tty, do no... |
1885 |
bool is_eof; |
70aca71f9 n_tty: Fix unorde... |
1886 |
size_t head = smp_load_acquire(&ldata->commit_head); |
bc5a5e3f4 n_tty: Don't wrap... |
1887 |
size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
1da177e4c Linux-2.6.12-rc2 |
1888 1889 |
retval = 0; |
70aca71f9 n_tty: Fix unorde... |
1890 |
n = min(head - ldata->read_tail, N_TTY_BUF_SIZE - tail); |
1da177e4c Linux-2.6.12-rc2 |
1891 |
n = min(*nr, n); |
1da177e4c Linux-2.6.12-rc2 |
1892 |
if (n) { |
e661cf702 n_tty: Clarify co... |
1893 1894 |
const unsigned char *from = read_buf_addr(ldata, tail); retval = copy_to_user(*b, from, n); |
1da177e4c Linux-2.6.12-rc2 |
1895 |
n -= retval; |
e661cf702 n_tty: Clarify co... |
1896 |
is_eof = n == 1 && *from == EOF_CHAR(tty); |
309426ae6 tty: audit: Remov... |
1897 |
tty_audit_add_data(tty, from, n); |
70aca71f9 n_tty: Fix unorde... |
1898 |
smp_store_release(&ldata->read_tail, ldata->read_tail + n); |
26df6d134 tty: Add EXTPROC ... |
1899 |
/* Turn single EOF into zero-length read */ |
70aca71f9 n_tty: Fix unorde... |
1900 1901 |
if (L_EXTPROC(tty) && ldata->icanon && is_eof && (head == ldata->read_tail)) |
3fa10cc83 TTY: n_tty, do no... |
1902 |
n = 0; |
1da177e4c Linux-2.6.12-rc2 |
1903 1904 1905 1906 1907 |
*b += n; *nr -= n; } return retval; } |
88bb0de38 n_tty: Factor can... |
1908 |
/** |
32f13521c n_tty: Line copy ... |
1909 |
* canon_copy_from_read_buf - copy read data in canonical mode |
88bb0de38 n_tty: Factor can... |
1910 1911 1912 1913 1914 |
* @tty: terminal device * @b: user data * @nr: size of data * * Helper function for n_tty_read. It is only called when ICANON is on; |
32f13521c n_tty: Line copy ... |
1915 1916 |
* it copies one line of input up to and including the line-delimiting * character into the user-space buffer. |
88bb0de38 n_tty: Factor can... |
1917 |
* |
4d0ed1827 n_tty: Fix buffer... |
1918 1919 1920 1921 1922 1923 |
* NB: When termios is changed from non-canonical to canonical mode and * the read buffer contains data, n_tty_set_termios() simulates an EOF * push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer. * This causes data already processed as input to be immediately available * as input although a newline has not been received. * |
88bb0de38 n_tty: Factor can... |
1924 |
* Called under the atomic_read_lock mutex |
6d76bd261 n_tty: Make N_TTY... |
1925 1926 1927 1928 |
* * n_tty_read()/consumer path: * caller holds non-exclusive termios_rwsem * read_tail published |
88bb0de38 n_tty: Factor can... |
1929 |
*/ |
32f13521c n_tty: Line copy ... |
1930 1931 1932 |
static int canon_copy_from_read_buf(struct tty_struct *tty, unsigned char __user **b, size_t *nr) |
88bb0de38 n_tty: Factor can... |
1933 1934 |
{ struct n_tty_data *ldata = tty->disc_data; |
32f13521c n_tty: Line copy ... |
1935 |
size_t n, size, more, c; |
bc5a5e3f4 n_tty: Don't wrap... |
1936 1937 1938 |
size_t eol; size_t tail; int ret, found = 0; |
88bb0de38 n_tty: Factor can... |
1939 1940 |
/* N.B. avoid overrun if nr == 0 */ |
ac8f3bf88 n_tty: Fix poll()... |
1941 |
if (!*nr) |
32f13521c n_tty: Line copy ... |
1942 |
return 0; |
88bb0de38 n_tty: Factor can... |
1943 |
|
ac8f3bf88 n_tty: Fix poll()... |
1944 |
n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail); |
bc5a5e3f4 n_tty: Don't wrap... |
1945 |
tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); |
32f13521c n_tty: Line copy ... |
1946 |
size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); |
bc5a5e3f4 n_tty: Don't wrap... |
1947 1948 |
n_tty_trace("%s: nr:%zu tail:%zu n:%zu size:%zu ", |
32f13521c n_tty: Line copy ... |
1949 1950 1951 1952 1953 1954 1955 |
__func__, *nr, tail, n, size); eol = find_next_bit(ldata->read_flags, size, tail); more = n - (size - tail); if (eol == N_TTY_BUF_SIZE && more) { /* scan wrapped without finding set bit */ eol = find_next_bit(ldata->read_flags, more, 0); |
b985e9e36 n_tty: Reduce bra... |
1956 1957 1958 |
found = eol != more; } else found = eol != size; |
32f13521c n_tty: Line copy ... |
1959 |
|
c77569d2f n_tty: Fix 4096-b... |
1960 |
n = eol - tail; |
da555db6b n_tty: Fix calcul... |
1961 1962 |
if (n > N_TTY_BUF_SIZE) n += N_TTY_BUF_SIZE; |
ac8f3bf88 n_tty: Fix poll()... |
1963 |
c = n + found; |
32f13521c n_tty: Line copy ... |
1964 |
|
ac8f3bf88 n_tty: Fix poll()... |
1965 1966 1967 |
if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) { c = min(*nr, c); n = c; |
40d5e0905 n_tty: Fix EOF pu... |
1968 |
} |
32f13521c n_tty: Line copy ... |
1969 |
|
679e7c299 n_tty: Uninline t... |
1970 1971 1972 |
n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu tail:%zu more:%zu ", __func__, eol, found, n, c, tail, more); |
32f13521c n_tty: Line copy ... |
1973 |
|
679e7c299 n_tty: Uninline t... |
1974 |
ret = tty_copy_to_user(tty, *b, tail, n); |
32f13521c n_tty: Line copy ... |
1975 1976 1977 1978 |
if (ret) return -EFAULT; *b += n; *nr -= n; |
a73d3d698 n_tty: Replace ca... |
1979 |
if (found) |
6d76bd261 n_tty: Make N_TTY... |
1980 |
clear_bit(eol, ldata->read_flags); |
70aca71f9 n_tty: Fix unorde... |
1981 |
smp_store_release(&ldata->read_tail, ldata->read_tail + c); |
88bb0de38 n_tty: Factor can... |
1982 |
|
40d5e0905 n_tty: Fix EOF pu... |
1983 |
if (found) { |
4d0ed1827 n_tty: Fix buffer... |
1984 1985 1986 1987 |
if (!ldata->push) ldata->line_start = ldata->read_tail; else ldata->push = 0; |
b50819f43 tty: audit: Ignor... |
1988 |
tty_audit_push(); |
40d5e0905 n_tty: Fix EOF pu... |
1989 |
} |
ac8f3bf88 n_tty: Fix poll()... |
1990 |
return 0; |
88bb0de38 n_tty: Factor can... |
1991 |
} |
cc4191dc1 drivers/char/n_tt... |
1992 |
extern ssize_t redirected_tty_write(struct file *, const char __user *, |
4edf1827e n_tty: clean up o... |
1993 |
size_t, loff_t *); |
1da177e4c Linux-2.6.12-rc2 |
1994 1995 1996 1997 1998 1999 2000 |
/** * job_control - check job control * @tty: tty * @file: file handle * * Perform job control management checks on this file/tty descriptor |
4edf1827e n_tty: clean up o... |
2001 |
* and if appropriate send any needed signals and return a negative |
1da177e4c Linux-2.6.12-rc2 |
2002 |
* error code if action should be taken. |
04f378b19 tty: BKL pushdown |
2003 |
* |
01a5e440c n_tty: Lock acces... |
2004 2005 2006 |
* Locking: redirected write test is safe * current->signal->tty check is safe * ctrl_lock to safely reference tty->pgrp |
1da177e4c Linux-2.6.12-rc2 |
2007 |
*/ |
4edf1827e n_tty: clean up o... |
2008 |
|
1da177e4c Linux-2.6.12-rc2 |
2009 2010 2011 2012 2013 2014 2015 |
static int job_control(struct tty_struct *tty, struct file *file) { /* Job control check -- must be done at start and after every sleep (POSIX.1 7.1.1.4). */ /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ |
2812d9e9f tty: Combine SIGT... |
2016 |
if (file->f_op->write == redirected_tty_write) |
01a5e440c n_tty: Lock acces... |
2017 |
return 0; |
2812d9e9f tty: Combine SIGT... |
2018 |
return __tty_check_change(tty, SIGTTIN); |
1da177e4c Linux-2.6.12-rc2 |
2019 |
} |
4edf1827e n_tty: clean up o... |
2020 |
|
1da177e4c Linux-2.6.12-rc2 |
2021 2022 |
/** |
11a96d182 tty: rename the r... |
2023 |
* n_tty_read - read function for tty |
1da177e4c Linux-2.6.12-rc2 |
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 |
* @tty: tty device * @file: file object * @buf: userspace buffer pointer * @nr: size of I/O * * Perform reads for the line discipline. We are guaranteed that the * line discipline will not be closed under us but we may get multiple * parallel readers and must handle this ourselves. We may also get * a hangup. Always called in user context, may sleep. * * This code must be sure never to sleep through a hangup. |
6d76bd261 n_tty: Make N_TTY... |
2035 2036 2037 2038 |
* * n_tty_read()/consumer path: * claims non-exclusive termios_rwsem * publishes read_tail |
1da177e4c Linux-2.6.12-rc2 |
2039 |
*/ |
4edf1827e n_tty: clean up o... |
2040 |
|
11a96d182 tty: rename the r... |
2041 |
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, |
1da177e4c Linux-2.6.12-rc2 |
2042 2043 |
unsigned char __user *buf, size_t nr) { |
53c5ee2cf TTY: move ldisc d... |
2044 |
struct n_tty_data *ldata = tty->disc_data; |
1da177e4c Linux-2.6.12-rc2 |
2045 |
unsigned char __user *b = buf; |
97d9e28d1 sched, tty: Deal ... |
2046 |
DEFINE_WAIT_FUNC(wait, woken_wake_function); |
0f40fbbcc Fix OpenSSH pty r... |
2047 |
int c; |
1da177e4c Linux-2.6.12-rc2 |
2048 2049 |
int minimum, time; ssize_t retval = 0; |
1da177e4c Linux-2.6.12-rc2 |
2050 |
long timeout; |
04f378b19 tty: BKL pushdown |
2051 |
int packet; |
2c5dc4641 n_tty: Eliminate ... |
2052 |
size_t tail; |
1da177e4c Linux-2.6.12-rc2 |
2053 |
|
1da177e4c Linux-2.6.12-rc2 |
2054 |
c = job_control(tty, file); |
4edf1827e n_tty: clean up o... |
2055 |
if (c < 0) |
1da177e4c Linux-2.6.12-rc2 |
2056 |
return c; |
4edf1827e n_tty: clean up o... |
2057 |
|
aefceaf45 n_tty: Fix termio... |
2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 |
/* * Internal serialization of reads. */ if (file->f_flags & O_NONBLOCK) { if (!mutex_trylock(&ldata->atomic_read_lock)) return -EAGAIN; } else { if (mutex_lock_interruptible(&ldata->atomic_read_lock)) return -ERESTARTSYS; } |
9356b535f n_tty: Access ter... |
2068 |
down_read(&tty->termios_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
2069 2070 |
minimum = time = 0; timeout = MAX_SCHEDULE_TIMEOUT; |
53c5ee2cf TTY: move ldisc d... |
2071 |
if (!ldata->icanon) { |
1da177e4c Linux-2.6.12-rc2 |
2072 2073 |
minimum = MIN_CHAR(tty); if (minimum) { |
a6e54319a n_tty: Untangle r... |
2074 |
time = (HZ / 10) * TIME_CHAR(tty); |
1da177e4c Linux-2.6.12-rc2 |
2075 |
} else { |
a6e54319a n_tty: Untangle r... |
2076 |
timeout = (HZ / 10) * TIME_CHAR(tty); |
33d713633 n_tty: Always wak... |
2077 |
minimum = 1; |
1da177e4c Linux-2.6.12-rc2 |
2078 2079 |
} } |
04f378b19 tty: BKL pushdown |
2080 |
packet = tty->packet; |
2c5dc4641 n_tty: Eliminate ... |
2081 |
tail = ldata->read_tail; |
1da177e4c Linux-2.6.12-rc2 |
2082 2083 |
add_wait_queue(&tty->read_wait, &wait); |
1da177e4c Linux-2.6.12-rc2 |
2084 2085 |
while (nr) { /* First test for status change. */ |
04f378b19 tty: BKL pushdown |
2086 |
if (packet && tty->link->ctrl_status) { |
1da177e4c Linux-2.6.12-rc2 |
2087 2088 2089 |
unsigned char cs; if (b != buf) break; |
6054c16e8 tty: Use spin_loc... |
2090 |
spin_lock_irq(&tty->link->ctrl_lock); |
1da177e4c Linux-2.6.12-rc2 |
2091 2092 |
cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; |
6054c16e8 tty: Use spin_loc... |
2093 |
spin_unlock_irq(&tty->link->ctrl_lock); |
eab25a5cd tty: audit: Never... |
2094 |
if (put_user(cs, b)) { |
1da177e4c Linux-2.6.12-rc2 |
2095 |
retval = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
2096 2097 |
break; } |
eab25a5cd tty: audit: Never... |
2098 |
b++; |
1da177e4c Linux-2.6.12-rc2 |
2099 2100 2101 |
nr--; break; } |
4edf1827e n_tty: clean up o... |
2102 |
|
1da177e4c Linux-2.6.12-rc2 |
2103 |
if (!input_available_p(tty, 0)) { |
52bce7f8d pty, n_tty: Simpl... |
2104 |
up_read(&tty->termios_rwsem); |
0f40fbbcc Fix OpenSSH pty r... |
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 |
tty_buffer_flush_work(tty->port); down_read(&tty->termios_rwsem); if (!input_available_p(tty, 0)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { retval = -EIO; break; } if (tty_hung_up_p(file)) break; if (!timeout) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } if (signal_pending(current)) { retval = -ERESTARTSYS; break; } up_read(&tty->termios_rwsem); |
9356b535f n_tty: Access ter... |
2125 |
|
0f40fbbcc Fix OpenSSH pty r... |
2126 2127 |
timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout); |
9356b535f n_tty: Access ter... |
2128 |
|
0f40fbbcc Fix OpenSSH pty r... |
2129 2130 2131 |
down_read(&tty->termios_rwsem); continue; } |
1da177e4c Linux-2.6.12-rc2 |
2132 |
} |
53c5ee2cf TTY: move ldisc d... |
2133 |
if (ldata->icanon && !L_EXTPROC(tty)) { |
32f13521c n_tty: Line copy ... |
2134 |
retval = canon_copy_from_read_buf(tty, &b, &nr); |
ac8f3bf88 n_tty: Fix poll()... |
2135 |
if (retval) |
1da177e4c Linux-2.6.12-rc2 |
2136 2137 2138 |
break; } else { int uncopied; |
95ea90db0 n_tty: Only proce... |
2139 2140 2141 |
/* Deal with packet mode. */ if (packet && b == buf) { |
eab25a5cd tty: audit: Never... |
2142 |
if (put_user(TIOCPKT_DATA, b)) { |
95ea90db0 n_tty: Only proce... |
2143 |
retval = -EFAULT; |
95ea90db0 n_tty: Only proce... |
2144 2145 |
break; } |
eab25a5cd tty: audit: Never... |
2146 |
b++; |
95ea90db0 n_tty: Only proce... |
2147 2148 |
nr--; } |
1da177e4c Linux-2.6.12-rc2 |
2149 2150 2151 2152 2153 2154 2155 |
uncopied = copy_from_read_buf(tty, &b, &nr); uncopied += copy_from_read_buf(tty, &b, &nr); if (uncopied) { retval = -EFAULT; break; } } |
6367ca72f n_tty: Factor thr... |
2156 |
n_tty_check_unthrottle(tty); |
1da177e4c Linux-2.6.12-rc2 |
2157 2158 2159 2160 2161 2162 |
if (b - buf >= minimum) break; if (time) timeout = time; } |
2c5dc4641 n_tty: Eliminate ... |
2163 2164 |
if (tail != ldata->read_tail) n_tty_kick_worker(tty); |
42458f41d n_tty: Ensure rea... |
2165 |
up_read(&tty->termios_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
2166 |
remove_wait_queue(&tty->read_wait, &wait); |
aebf04538 n_tty: Protect mi... |
2167 |
mutex_unlock(&ldata->atomic_read_lock); |
40d5e0905 n_tty: Fix EOF pu... |
2168 2169 |
if (b - buf) retval = b - buf; |
1da177e4c Linux-2.6.12-rc2 |
2170 2171 2172 2173 2174 |
return retval; } /** |
11a96d182 tty: rename the r... |
2175 |
* n_tty_write - write function for tty |
1da177e4c Linux-2.6.12-rc2 |
2176 2177 2178 2179 2180 |
* @tty: tty device * @file: file object * @buf: userspace buffer pointer * @nr: size of I/O * |
a88a69c91 n_tty: Fix loss o... |
2181 |
* Write function of the terminal device. This is serialized with |
1da177e4c Linux-2.6.12-rc2 |
2182 |
* respect to other write callers but not to termios changes, reads |
a88a69c91 n_tty: Fix loss o... |
2183 2184 2185 2186 2187 |
* and other such events. Since the receive code will echo characters, * thus calling driver write methods, the output_lock is used in * the output processing functions called here as well as in the * echo processing function to protect the column state and space * left in the buffer. |
1da177e4c Linux-2.6.12-rc2 |
2188 2189 |
* * This code must be sure never to sleep through a hangup. |
a88a69c91 n_tty: Fix loss o... |
2190 2191 2192 2193 |
* * Locking: output_lock to protect column state and space left * (note that the process_output*() functions take this * lock themselves) |
1da177e4c Linux-2.6.12-rc2 |
2194 |
*/ |
4edf1827e n_tty: clean up o... |
2195 |
|
11a96d182 tty: rename the r... |
2196 |
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, |
a88a69c91 n_tty: Fix loss o... |
2197 |
const unsigned char *buf, size_t nr) |
1da177e4c Linux-2.6.12-rc2 |
2198 2199 |
{ const unsigned char *b = buf; |
97d9e28d1 sched, tty: Deal ... |
2200 |
DEFINE_WAIT_FUNC(wait, woken_wake_function); |
1da177e4c Linux-2.6.12-rc2 |
2201 2202 2203 2204 2205 2206 2207 2208 2209 |
int c; ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; } |
9356b535f n_tty: Access ter... |
2210 |
down_read(&tty->termios_rwsem); |
a88a69c91 n_tty: Fix loss o... |
2211 2212 |
/* Write out any echoed characters that are still pending */ process_echoes(tty); |
300a6204b n_tty: clean up c... |
2213 |
|
1da177e4c Linux-2.6.12-rc2 |
2214 2215 |
add_wait_queue(&tty->write_wait, &wait); while (1) { |
1da177e4c Linux-2.6.12-rc2 |
2216 2217 2218 2219 2220 2221 2222 2223 |
if (signal_pending(current)) { retval = -ERESTARTSYS; break; } if (tty_hung_up_p(file) || (tty->link && !tty->link->count)) { retval = -EIO; break; } |
582f55907 tty: Remove TTY_H... |
2224 |
if (O_OPOST(tty)) { |
1da177e4c Linux-2.6.12-rc2 |
2225 |
while (nr > 0) { |
a88a69c91 n_tty: Fix loss o... |
2226 |
ssize_t num = process_output_block(tty, b, nr); |
1da177e4c Linux-2.6.12-rc2 |
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 |
if (num < 0) { if (num == -EAGAIN) break; retval = num; goto break_out; } b += num; nr -= num; if (nr == 0) break; c = *b; |
a88a69c91 n_tty: Fix loss o... |
2238 |
if (process_output(c, tty) < 0) |
1da177e4c Linux-2.6.12-rc2 |
2239 2240 2241 |
break; b++; nr--; } |
f34d7a5b7 tty: The big oper... |
2242 2243 |
if (tty->ops->flush_chars) tty->ops->flush_chars(tty); |
1da177e4c Linux-2.6.12-rc2 |
2244 |
} else { |
4291086b1 n_tty: Fix n_tty_... |
2245 |
struct n_tty_data *ldata = tty->disc_data; |
d6afe27bf [PATCH] tty outpu... |
2246 |
while (nr > 0) { |
4291086b1 n_tty: Fix n_tty_... |
2247 |
mutex_lock(&ldata->output_lock); |
f34d7a5b7 tty: The big oper... |
2248 |
c = tty->ops->write(tty, b, nr); |
4291086b1 n_tty: Fix n_tty_... |
2249 |
mutex_unlock(&ldata->output_lock); |
d6afe27bf [PATCH] tty outpu... |
2250 2251 2252 2253 2254 2255 2256 2257 |
if (c < 0) { retval = c; goto break_out; } if (!c) break; b += c; nr -= c; |
1da177e4c Linux-2.6.12-rc2 |
2258 |
} |
1da177e4c Linux-2.6.12-rc2 |
2259 2260 2261 2262 2263 2264 2265 |
} if (!nr) break; if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } |
9356b535f n_tty: Access ter... |
2266 |
up_read(&tty->termios_rwsem); |
97d9e28d1 sched, tty: Deal ... |
2267 |
wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); |
9356b535f n_tty: Access ter... |
2268 2269 |
down_read(&tty->termios_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
2270 2271 |
} break_out: |
1da177e4c Linux-2.6.12-rc2 |
2272 |
remove_wait_queue(&tty->write_wait, &wait); |
87108bc98 tty: n_tty: fix S... |
2273 |
if (nr && tty->fasync) |
ff8cb0fd6 tty: N_TTY SIGIO ... |
2274 |
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); |
9356b535f n_tty: Access ter... |
2275 |
up_read(&tty->termios_rwsem); |
1da177e4c Linux-2.6.12-rc2 |
2276 2277 2278 2279 |
return (b - buf) ? b - buf : retval; } /** |
11a96d182 tty: rename the r... |
2280 |
* n_tty_poll - poll method for N_TTY |
1da177e4c Linux-2.6.12-rc2 |
2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 |
* @tty: terminal device * @file: file accessing it * @wait: poll table * * Called when the line discipline is asked to poll() for data or * for special events. This code is not serialized with respect to * other events save open/close. * * This code must be sure never to sleep through a hangup. * Called without the kernel lock held - fine |
1da177e4c Linux-2.6.12-rc2 |
2291 |
*/ |
4edf1827e n_tty: clean up o... |
2292 |
|
11a96d182 tty: rename the r... |
2293 |
static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, |
4edf1827e n_tty: clean up o... |
2294 |
poll_table *wait) |
1da177e4c Linux-2.6.12-rc2 |
2295 2296 2297 2298 2299 |
{ unsigned int mask = 0; poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); |
eafbe67f8 n_tty: Refactor i... |
2300 |
if (input_available_p(tty, 1)) |
1da177e4c Linux-2.6.12-rc2 |
2301 |
mask |= POLLIN | POLLRDNORM; |
0f40fbbcc Fix OpenSSH pty r... |
2302 2303 2304 2305 2306 |
else { tty_buffer_flush_work(tty->port); if (input_available_p(tty, 1)) mask |= POLLIN | POLLRDNORM; } |
1da177e4c Linux-2.6.12-rc2 |
2307 2308 |
if (tty->packet && tty->link->ctrl_status) mask |= POLLPRI | POLLIN | POLLRDNORM; |
0f40fbbcc Fix OpenSSH pty r... |
2309 2310 |
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) mask |= POLLHUP; |
1da177e4c Linux-2.6.12-rc2 |
2311 2312 |
if (tty_hung_up_p(file)) mask |= POLLHUP; |
f34d7a5b7 tty: The big oper... |
2313 2314 2315 |
if (tty->ops->write && !tty_is_writelocked(tty) && tty_chars_in_buffer(tty) < WAKEUP_CHARS && tty_write_room(tty) > 0) |
1da177e4c Linux-2.6.12-rc2 |
2316 2317 2318 |
mask |= POLLOUT | POLLWRNORM; return mask; } |
57c941212 TTY: n_tty, propa... |
2319 |
static unsigned long inq_canon(struct n_tty_data *ldata) |
47afa7a5a tty: some ICANON ... |
2320 |
{ |
bc5a5e3f4 n_tty: Don't wrap... |
2321 |
size_t nr, head, tail; |
47afa7a5a tty: some ICANON ... |
2322 |
|
a73d3d698 n_tty: Replace ca... |
2323 |
if (ldata->canon_head == ldata->read_tail) |
47afa7a5a tty: some ICANON ... |
2324 |
return 0; |
ba2e68ac6 TTY: move ldisc d... |
2325 2326 |
head = ldata->canon_head; tail = ldata->read_tail; |
bc5a5e3f4 n_tty: Don't wrap... |
2327 |
nr = head - tail; |
47afa7a5a tty: some ICANON ... |
2328 2329 |
/* Skip EOF-chars.. */ while (head != tail) { |
bc5a5e3f4 n_tty: Don't wrap... |
2330 2331 |
if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) && read_buf(ldata, tail) == __DISABLED_CHAR) |
47afa7a5a tty: some ICANON ... |
2332 |
nr--; |
bc5a5e3f4 n_tty: Don't wrap... |
2333 |
tail++; |
47afa7a5a tty: some ICANON ... |
2334 2335 2336 2337 2338 2339 2340 |
} return nr; } static int n_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { |
ba2e68ac6 TTY: move ldisc d... |
2341 |
struct n_tty_data *ldata = tty->disc_data; |
47afa7a5a tty: some ICANON ... |
2342 2343 2344 2345 2346 2347 |
int retval; switch (cmd) { case TIOCOUTQ: return put_user(tty_chars_in_buffer(tty), (int __user *) arg); case TIOCINQ: |
6d76bd261 n_tty: Make N_TTY... |
2348 |
down_write(&tty->termios_rwsem); |
47afa7a5a tty: some ICANON ... |
2349 |
if (L_ICANON(tty)) |
57c941212 TTY: n_tty, propa... |
2350 |
retval = inq_canon(ldata); |
6d76bd261 n_tty: Make N_TTY... |
2351 2352 2353 |
else retval = read_cnt(ldata); up_write(&tty->termios_rwsem); |
47afa7a5a tty: some ICANON ... |
2354 2355 2356 2357 2358 |
return put_user(retval, (unsigned int __user *) arg); default: return n_tty_ioctl_helper(tty, file, cmd, arg); } } |
27228732a tty: Eliminate gl... |
2359 |
static struct tty_ldisc_ops n_tty_ops = { |
e10cc1df1 tty: add compat_i... |
2360 2361 2362 2363 2364 |
.magic = TTY_LDISC_MAGIC, .name = "n_tty", .open = n_tty_open, .close = n_tty_close, .flush_buffer = n_tty_flush_buffer, |
11a96d182 tty: rename the r... |
2365 2366 |
.read = n_tty_read, .write = n_tty_write, |
e10cc1df1 tty: add compat_i... |
2367 2368 |
.ioctl = n_tty_ioctl, .set_termios = n_tty_set_termios, |
11a96d182 tty: rename the r... |
2369 |
.poll = n_tty_poll, |
e10cc1df1 tty: add compat_i... |
2370 |
.receive_buf = n_tty_receive_buf, |
f6c8dbe6e n_tty: Encapsulat... |
2371 |
.write_wakeup = n_tty_write_wakeup, |
24a89d1cb tty: Make ldisc i... |
2372 |
.receive_buf2 = n_tty_receive_buf2, |
1da177e4c Linux-2.6.12-rc2 |
2373 |
}; |
572b9adbd ldisc n_tty: add ... |
2374 2375 2376 2377 2378 |
/** * n_tty_inherit_ops - inherit N_TTY methods * @ops: struct tty_ldisc_ops where to save N_TTY methods * |
27228732a tty: Eliminate gl... |
2379 |
* Enables a 'subclass' line discipline to 'inherit' N_TTY methods. |
572b9adbd ldisc n_tty: add ... |
2380 2381 2382 2383 |
*/ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { |
27228732a tty: Eliminate gl... |
2384 |
*ops = n_tty_ops; |
572b9adbd ldisc n_tty: add ... |
2385 2386 2387 2388 |
ops->owner = NULL; ops->refcount = ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); |
27228732a tty: Eliminate gl... |
2389 2390 2391 2392 2393 |
void __init n_tty_init(void) { tty_register_ldisc(N_TTY, &n_tty_ops); } |