update from Rick Macklem to generate proper error messages
[unix-history] / usr / src / sys / kern / tty.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
c4ec2128 6 * @(#)tty.c 7.17 (Berkeley) %G%
da7c5cc6 7 */
961945a8 8
94368568
JB
9#include "param.h"
10#include "systm.h"
94368568
JB
11#include "user.h"
12#include "ioctl.h"
13#include "tty.h"
2c6a4e11
MT
14#define TTYDEFCHARS
15#include "ttydefaults.h"
16#undef TTYDEFCHARS
17#include "termios.h"
e39f9ea6
MT
18#define TTYDEFCHARS
19#include "ttydefaults.h"
20#undef TTYDEFCHARS
21#include "termios.h"
94368568 22#include "proc.h"
94368568
JB
23#include "file.h"
24#include "conf.h"
fb1db32c 25#include "dkstat.h"
94368568
JB
26#include "uio.h"
27#include "kernel.h"
c4ec2128 28#include "vnode.h"
2c6a4e11 29#include "syslog.h"
d301d150
KM
30
31#include "machine/reg.h"
e39f9ea6 32#include "syslog.h"
89dc6dfb 33
8bba2b8f
RE
34/*
35 * Table giving parity for characters and indicating
e39f9ea6
MT
36 * character classes to tty driver. The 8th bit
37 * indicates parity, the 7th bit indicates the character
38 * is an alphameric or underscore (for ALTWERASE), and the
39 * low 6 bits indicate delay type. If the low 6 bits are 0
40 * then the character needs no special processing on output.
8bba2b8f
RE
41 */
42
43char partab[] = {
e39f9ea6
MT
44 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */
45 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */
46 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */
47 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */
48 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */
49 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */
50 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */
51 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */
52 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */
53 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */
54 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */
55 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */
56 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */
57 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */
58 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */
59 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */
8bba2b8f 60 /*
e39f9ea6 61 * meta chars
8bba2b8f 62 */
e39f9ea6
MT
63 0001,0201,0201,0001,0201,0001,0001,0201, /* nul - bel */
64 0202,0004,0003,0201,0005,0206,0201,0001, /* bs - si */
65 0201,0001,0001,0201,0001,0201,0201,0001, /* dle - etb */
66 0001,0201,0201,0001,0201,0001,0001,0201, /* can - us */
67 0200,0000,0000,0200,0000,0200,0200,0000, /* sp - ' */
68 0000,0200,0200,0000,0200,0000,0000,0200, /* ( - / */
69 0100,0300,0300,0100,0300,0100,0100,0300, /* 0 - 7 */
70 0300,0100,0000,0200,0000,0200,0200,0000, /* 8 - ? */
71 0200,0100,0100,0300,0100,0300,0300,0100, /* @ - G */
72 0100,0300,0300,0100,0300,0100,0100,0300, /* H - O */
73 0100,0300,0300,0100,0300,0100,0100,0300, /* P - W */
74 0300,0100,0100,0200,0000,0200,0200,0300, /* X - _ */
75 0000,0300,0300,0100,0300,0100,0100,0300, /* ` - g */
76 0300,0100,0100,0300,0100,0300,0300,0100, /* h - o */
77 0300,0100,0100,0300,0100,0300,0300,0100, /* p - w */
78 0100,0300,0300,0000,0200,0000,0000,0201, /* x - del */
89dc6dfb
BJ
79};
80
adf4bc89 81extern struct tty *constty; /* temporary virtual console */
2c6a4e11
MT
82extern char partab[], maptab[];
83
e39f9ea6
MT
84/*
85 * Is 'c' a line delimiter ("break" character)?
86 */
87#define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \
88 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c))
89
2c6a4e11
MT
90/*
91 * Debugging aids
92 */
93#define dprintf if (tp->t_trace & TTRACE_IO)printf
94
95/*
96 * Is 'c' a line delimiter ("break" character)?
97 */
98#define ttbreakc(c) (c == '\n' || CCEQ(cc[VEOF], c) || \
99 CCEQ(cc[VEOL], c) || CCEQ(cc[VEOL2], c))
adf4bc89 100
89dc6dfb 101ttychars(tp)
becb115c 102 struct tty *tp;
89dc6dfb 103{
2c6a4e11 104 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
89dc6dfb
BJ
105}
106
107/*
2c6a4e11 108 *
50e2732b 109 * Wait for output to drain, then flush input waiting.
89dc6dfb 110 */
88a7a62a 111ttywflush(tp)
66ad69d6 112 struct tty *tp;
89dc6dfb
BJ
113{
114
88a7a62a
SL
115 ttywait(tp);
116 ttyflush(tp, FREAD);
117}
118
e39f9ea6
MT
119/*
120 * Wait for output to drain.
121 */
2c6a4e11
MT
122/*
123 * Wait for output to drain.
124 */
88a7a62a
SL
125ttywait(tp)
126 register struct tty *tp;
127{
66ad69d6 128 int s = spltty();
88a7a62a 129
5de287d9 130 while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
66ad69d6
MT
131 (tp->t_state&TS_CARR_ON || tp->t_cflag&CLOCAL) &&
132 tp->t_oproc) {
50e2732b 133 (*tp->t_oproc)(tp);
941944c9 134 tp->t_state |= TS_ASLEEP;
50e2732b
BJ
135 sleep((caddr_t)&tp->t_outq, TTOPRI);
136 }
875a1e2c 137 splx(s);
89dc6dfb
BJ
138}
139
140/*
becb115c 141 * Flush all TTY queues
89dc6dfb 142 */
88a7a62a 143ttyflush(tp, rw)
4b72e2f9 144 register struct tty *tp;
89dc6dfb 145{
50e2732b
BJ
146 register s;
147
4f3a716e 148 s = spltty();
50e2732b
BJ
149 if (rw & FREAD) {
150 while (getc(&tp->t_canq) >= 0)
151 ;
66ad69d6 152 ttwakeup(tp);
50e2732b
BJ
153 }
154 if (rw & FWRITE) {
66ad69d6 155 wakeup((caddr_t)&tp->t_outq); /* XXX? what about selwakeup? */
941944c9 156 tp->t_state &= ~TS_TTSTOP;
39697bd8 157 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
50e2732b
BJ
158 while (getc(&tp->t_outq) >= 0)
159 ;
160 }
161 if (rw & FREAD) {
162 while (getc(&tp->t_rawq) >= 0)
163 ;
becb115c 164 tp->t_rocount = 0;
50e2732b 165 tp->t_rocol = 0;
becb115c 166 tp->t_state &= ~TS_LOCAL;
50e2732b
BJ
167 }
168 splx(s);
89dc6dfb
BJ
169}
170
50e2732b
BJ
171/*
172 * Send stop character on input overflow.
173 */
174ttyblock(tp)
4b72e2f9 175 register struct tty *tp;
89dc6dfb 176{
50e2732b 177 register x;
becb115c 178
50e2732b
BJ
179 x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
180 if (tp->t_rawq.c_cc > TTYHOG) {
88a7a62a 181 ttyflush(tp, FREAD|FWRITE);
941944c9 182 tp->t_state &= ~TS_TBLOCK;
50e2732b 183 }
600d5712
MK
184 /*
185 * Block further input iff:
186 * Current input > threshold AND input is available to user program
187 */
28b2d854 188 if (x >= TTYHOG/2 &&
2c6a4e11
MT
189 (!(tp->t_lflag&ICANON)) || (tp->t_canq.c_cc > 0) &&
190 tp->t_cc[VSTOP] != POSIX_V_DISABLE) {
191 if (putc(tp->t_cc[VSTOP], &tp->t_outq)==0) {
600d5712
MK
192 tp->t_state |= TS_TBLOCK;
193 ttstart(tp);
194 }
50e2732b 195 }
89dc6dfb
BJ
196}
197
101ba270 198/*
50e2732b
BJ
199 * Restart typewriter output following a delay
200 * timeout.
201 * The name of the routine is passed to the timeout
202 * subroutine and it is called during a clock interrupt.
101ba270 203 */
50e2732b 204ttrstrt(tp)
66ad69d6 205 struct tty *tp;
101ba270
BJ
206{
207
becb115c
SL
208 if (tp == 0)
209 panic("ttrstrt");
941944c9 210 tp->t_state &= ~TS_TIMEOUT;
50e2732b 211 ttstart(tp);
101ba270
BJ
212}
213
89dc6dfb 214/*
50e2732b
BJ
215 * Start output on the typewriter. It is used from the top half
216 * after some characters have been put on the output queue,
217 * from the interrupt routine to transmit the next
218 * character, and after a timeout has finished.
89dc6dfb 219 */
50e2732b 220ttstart(tp)
66ad69d6 221 struct tty *tp;
89dc6dfb 222{
8062c8a7 223
b482b2c8 224 if (tp->t_oproc) /* kludge for pty */
50e2732b 225 (*tp->t_oproc)(tp);
89dc6dfb
BJ
226}
227
228/*
50e2732b 229 * Common code for tty ioctls.
89dc6dfb 230 */
49c84d3f 231/*ARGSUSED*/
4b72e2f9
SL
232ttioctl(tp, com, data, flag)
233 register struct tty *tp;
234 caddr_t data;
89dc6dfb 235{
89dc6dfb 236 extern int nldisp;
e39f9ea6 237 int softset = 0;
2c6a4e11 238 int soft;
849cbd39 239 int s, error;
89dc6dfb 240
adf4bc89 241
50e2732b
BJ
242 /*
243 * If the ioctl involves modification,
4f3a716e 244 * hang if in the background.
50e2732b 245 */
4b72e2f9 246 switch (com) {
50e2732b 247
2c6a4e11 248 case TIOCSETD:
50e2732b 249 case TIOCFLUSH:
8203fe05 250 case TIOCSTI:
f9eea644 251 case TIOCSWINSZ:
2c6a4e11
MT
252 case TIOCSETA:
253 case TIOCSETAW:
254 case TIOCSETAF:
255 case TIOCSETAS:
256 case TIOCSETAWS:
257 case TIOCSETAFS:
e39f9ea6
MT
258 while (u.u_procp->p_pgid != tp->t_pgid &&
259 tp == u.u_ttyp &&
260 u.u_procp->p_pgrp->pg_jobc &&
50e2732b 261 (u.u_procp->p_flag&SVFORK) == 0 &&
52c041cd
MK
262 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
263 !(u.u_procp->p_sigmask & sigmask(SIGTTOU))) {
e39f9ea6 264 pgsignal(u.u_procp->p_pgrp, SIGTTOU);
50e2732b
BJ
265 sleep((caddr_t)&lbolt, TTOPRI);
266 }
267 break;
268 }
269
becb115c
SL
270 /*
271 * Process the ioctl.
272 */
4b72e2f9 273 switch (com) {
89dc6dfb 274
fc6972ae 275 /* get discipline number */
89dc6dfb 276 case TIOCGETD:
4b72e2f9 277 *(int *)data = tp->t_line;
89dc6dfb
BJ
278 break;
279
fc6972ae 280 /* set line discipline */
4b72e2f9
SL
281 case TIOCSETD: {
282 register int t = *(int *)data;
2c6a4e11 283 dev_t dev = tp->t_dev;
e39f9ea6 284 dev_t dev = tp->t_dev;
becb115c 285 int error = 0;
4b72e2f9 286
e39f9ea6 287 if ((unsigned)t >= nldisp)
4a003df3 288 return (ENXIO);
2eaeef4d
MK
289 if (t != tp->t_line) {
290 s = spltty();
291 (*linesw[tp->t_line].l_close)(tp);
292 error = (*linesw[t].l_open)(dev, tp);
293 if (error) {
2c6a4e11 294 (void)(*linesw[tp->t_line].l_open)(dev, tp);
2eaeef4d
MK
295 splx(s);
296 return (error);
297 }
298 tp->t_line = t;
4a003df3 299 splx(s);
4a003df3 300 }
2c6a4e11
MT
301 if (tp->t_trace & TTRACE_STATE)
302 ttytrace(com, tp);
89dc6dfb 303 break;
4b72e2f9 304 }
89dc6dfb 305
fc6972ae 306 /* prevent more opens on channel */
152c2598
BJ
307 case TIOCEXCL:
308 tp->t_state |= TS_XCLUDE;
309 break;
310
311 case TIOCNXCL:
312 tp->t_state &= ~TS_XCLUDE;
313 break;
314
89dc6dfb 315 case TIOCHPCL:
2c6a4e11 316 tp->t_cflag |= HUPCL;
89dc6dfb
BJ
317 break;
318
7d973a4d 319 case TIOCFLUSH: {
4b72e2f9
SL
320 register int flags = *(int *)data;
321
322 if (flags == 0)
7d973a4d 323 flags = FREAD|FWRITE;
4b72e2f9
SL
324 else
325 flags &= FREAD|FWRITE;
88a7a62a 326 ttyflush(tp, flags);
89dc6dfb 327 break;
4568c08e 328 }
89dc6dfb 329
66ad69d6
MT
330 case FIOASYNC:
331 if (*(int *)data)
332 tp->t_state |= TS_ASYNC;
333 else
334 tp->t_state &= ~TS_ASYNC;
335 break;
336
337 case FIONBIO:
338 break; /* XXX remove */
339
fc6972ae 340 /* return number of characters immediately available */
4b72e2f9
SL
341 case FIONREAD:
342 *(off_t *)data = ttnread(tp);
8062c8a7 343 break;
8062c8a7 344
b968e450
SL
345 case TIOCOUTQ:
346 *(int *)data = tp->t_outq.c_cc;
347 break;
348
a8d3bf7f 349 case TIOCSTOP:
4f3a716e 350 s = spltty();
becb115c 351 if ((tp->t_state&TS_TTSTOP) == 0) {
bfcf09ee
BJ
352 tp->t_state |= TS_TTSTOP;
353 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
354 }
4b72e2f9 355 splx(s);
bfcf09ee
BJ
356 break;
357
a8d3bf7f 358 case TIOCSTART:
4f3a716e 359 s = spltty();
2c6a4e11 360 if ((tp->t_state&TS_TTSTOP) || (tp->t_lflag&FLUSHO)) {
bfcf09ee 361 tp->t_state &= ~TS_TTSTOP;
2c6a4e11 362 tp->t_lflag &= ~FLUSHO;
bfcf09ee
BJ
363 ttstart(tp);
364 }
4b72e2f9 365 splx(s);
bfcf09ee
BJ
366 break;
367
8203fe05
SL
368 /*
369 * Simulate typing of a character at the terminal.
370 */
371 case TIOCSTI:
477d62ec
KM
372 if (u.u_uid && (flag & FREAD) == 0)
373 return (EPERM);
8203fe05
SL
374 if (u.u_uid && u.u_ttyp != tp)
375 return (EACCES);
becb115c 376 (*linesw[tp->t_line].l_rint)(*(char *)data, tp);
8203fe05
SL
377 break;
378
2c6a4e11
MT
379 case TIOCGETA: {
380 struct termios *t = (struct termios *)data;
381 bcopy(&tp->t_termio, t, sizeof(struct termios));
382 if (tp->t_trace & TTRACE_STATE)
383 ttytrace(com, tp);
384 break;
385 }
386
2c6a4e11
MT
387 if (com == TIOCSETAF || com == TIOCSETAFS)
388 ttywflush(tp);
389 else {
390 if (com == TIOCSETAW || com == TIOCSETAWS)
391 ttywait(tp);
392 if ((t->c_lflag&ICANON) != (tp->t_lflag&ICANON))
393 if (t->c_lflag&ICANON) {
394 tp->t_lflag |= PENDIN;
395 ttwakeup(tp);
396 }
397 else {
398 struct clist tq;
399
400 catq(&tp->t_rawq, &tp->t_canq);
401 tq = tp->t_rawq;
402 tp->t_rawq = tp->t_canq;
403 tp->t_canq = tq;
404 }
88a7a62a 405 }
2c6a4e11
MT
406 tp->t_iflag = t->c_iflag;
407 tp->t_oflag = t->c_oflag;
408 tp->t_lflag = t->c_lflag;
409 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
410 if (!soft) {
411 tp->t_cflag = t->c_cflag;
412 tp->t_ispeed = t->c_ispeed;
413 tp->t_ospeed = t->c_ospeed;
88a7a62a 414 }
e39f9ea6
MT
415 tp->t_iflag = t->c_iflag;
416 tp->t_oflag = t->c_oflag;
417 tp->t_lflag = t->c_lflag;
418 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
88a7a62a 419 splx(s);
2c6a4e11
MT
420 if (tp->t_trace & TTRACE_STATE)
421 ttytrace(com, tp);
88a7a62a
SL
422 break;
423 }
424
4f3a716e 425 /*
e39f9ea6 426 * Set terminal process group.
4f3a716e 427 */
245aeefa 428 case TIOCSPGRP: {
e39f9ea6
MT
429 register struct proc *p = u.u_procp;
430 register struct pgrp *pgrp = pgfind(*(int *)data);
431
432 if (u.u_uid &&
433 (tp != u.u_ttyp ||
434 (pgrp && pgrp->pg_session != p->p_session))) {
435 if (u.u_ttyp == NULL)
436 return (ENOTTY);
437 else
438 return (EPERM);
439 }
440 tp->t_pgid = *(int *)data;
88a7a62a 441 break;
245aeefa 442 }
88a7a62a
SL
443
444 case TIOCGPGRP:
e39f9ea6 445 *(int *)data = tp->t_pgid;
88a7a62a
SL
446 break;
447
f9eea644 448 case TIOCSWINSZ:
245aeefa
JB
449 if (bcmp((caddr_t)&tp->t_winsize, data,
450 sizeof (struct winsize))) {
f9eea644 451 tp->t_winsize = *(struct winsize *)data;
e39f9ea6 452 gsignal(tp->t_pgid, SIGWINCH);
f9eea644
JB
453 }
454 break;
455
456 case TIOCGWINSZ:
457 *(struct winsize *)data = tp->t_winsize;
458 break;
459
adf4bc89
MK
460 case TIOCCONS:
461 if (*(int *)data) {
462 if (constty != NULL)
463 return (EBUSY);
464#ifndef UCONSOLE
849cbd39
KM
465 if (error = suser(u.u_cred, &u.u_acflag))
466 return (error);
adf4bc89
MK
467#endif
468 constty = tp;
469 } else if (tp == constty)
1eebc1a7 470 constty = NULL;
adf4bc89
MK
471 break;
472
e39f9ea6
MT
473#ifdef COMPAT_43
474 case TIOCGETP:
475 case TIOCSETP:
476 case TIOCSETN:
477 case TIOCGETC:
478 case TIOCSETC:
479 case TIOCSLTC:
480 case TIOCGLTC:
481 case TIOCLBIS:
482 case TIOCLBIC:
483 case TIOCLSET:
484 case TIOCLGET:
485 case TIOCGETDCOMPAT:
486 case TIOCSETDCOMPAT:
487 return(ttcompat(tp, com, data, flag));
488#endif
489
2c6a4e11
MT
490 /* allow old ioctls for now */
491 case TIOCGETP:
492 case TIOCSETP:
493 case TIOCSETN:
494 case TIOCGETC:
495 case TIOCSETC:
496 case TIOCSLTC:
497 case TIOCGLTC:
498 case TIOCLBIS:
499 case TIOCLBIC:
500 case TIOCLSET:
501 case TIOCLGET:
502 return(ottioctl(tp, com, data, flag));
503
89dc6dfb 504 default:
fc6972ae 505 return (-1);
89dc6dfb 506 }
fc6972ae 507 return (0);
89dc6dfb 508}
e1d74936 509
2c6a4e11
MT
510/*
511 * DEBUG - to be removed
512 */
513ttytrace(ioc, tp)
514 struct tty *tp;
515{
516 register u_char *cc = tp->t_cc;
517 char comm[MAXCOMLEN+1];
518 static int seq = 0;
519
520 bcopy(u.u_comm, comm, MAXCOMLEN+1);
521 comm[MAXCOMLEN] = '\0';
522
523 /* trace changes to line disciplines */
524 if (ioc == TIOCSETD) {
525 log(LOG_LOCAL4|LOG_DEBUG, "%s:%x:%x:%x:%x\n",
526 comm, ioc, u.u_procp->p_pid, tp->t_dev, tp->t_line);
527 return;
528 }
529
530 /*
531 * format for the trace record is:
532 *
533 * u_comm:ioctl:pid:dev_t:ldisc:iflag:oflag:lflag:cflag:ispeed:
534 * ospeed:cc's...:seq
535 *
536 * u_comm is a string and all other values are hex. "cc's..."
537 * stands for control chars 0 through NCC-1. seq is a sequence #
538 * to force syslogd to log every entry (rather than hold them to
539 * print "last message repeated...".
540 */
541 log(LOG_LOCAL4|LOG_DEBUG, "%s:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x\n",
542 comm, ioc, u.u_procp->p_pid, tp->t_dev, tp->t_line,
543 tp->t_iflag, tp->t_oflag, tp->t_lflag, tp->t_cflag,
544 tp->t_ispeed, tp->t_ospeed, cc[0], cc[1], cc[2], cc[3],
545 cc[4], cc[5], cc[6], cc[7], cc[8], cc[9], cc[10], cc[11],
546 cc[12], cc[13], cc[14], cc[15], cc[16], cc[17], cc[18],
547 cc[19], seq++);
548}
549
e1d74936
BJ
550ttnread(tp)
551 struct tty *tp;
552{
553 int nread = 0;
554
2c6a4e11 555 if (tp->t_lflag & PENDIN)
e1d74936
BJ
556 ttypend(tp);
557 nread = tp->t_canq.c_cc;
2c6a4e11 558 if (tp->t_lflag & ICANON == 0)
e1d74936
BJ
559 nread += tp->t_rawq.c_cc;
560 return (nread);
561}
562
941944c9 563ttselect(dev, rw)
e1d74936 564 dev_t dev;
941944c9 565 int rw;
e1d74936
BJ
566{
567 register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
568 int nread;
4f3a716e 569 int s = spltty();
e1d74936 570
941944c9 571 switch (rw) {
e1d74936
BJ
572
573 case FREAD:
574 nread = ttnread(tp);
66ad69d6
MT
575 if (nread > 0 ||
576 (!(tp->t_cflag&CLOCAL) && !(tp->t_state&TS_CARR_ON)))
941944c9 577 goto win;
89b8a44c 578 if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
941944c9 579 tp->t_state |= TS_RCOLL;
e1d74936
BJ
580 else
581 tp->t_rsel = u.u_procp;
941944c9 582 break;
e1d74936 583
941944c9 584 case FWRITE:
e39f9ea6 585 if (tp->t_outq.c_cc <= tp->t_lowat)
941944c9 586 goto win;
941944c9
BJ
587 if (tp->t_wsel && tp->t_wsel->p_wchan == (caddr_t)&selwait)
588 tp->t_state |= TS_WCOLL;
589 else
590 tp->t_wsel = u.u_procp;
591 break;
e1d74936 592 }
941944c9
BJ
593 splx(s);
594 return (0);
595win:
596 splx(s);
597 return (1);
e1d74936 598}
8bba2b8f 599
4147b3f6 600/*
605d7712 601 * Initial open of tty, or (re)entry to line discipline.
4147b3f6
BJ
602 */
603ttyopen(dev, tp)
4b72e2f9
SL
604 dev_t dev;
605 register struct tty *tp;
4147b3f6 606{
4147b3f6 607
4147b3f6 608 tp->t_dev = dev;
e39f9ea6 609
4147b3f6 610 tp->t_state &= ~TS_WOPEN;
4f3a716e
MK
611 if ((tp->t_state & TS_ISOPEN) == 0) {
612 tp->t_state |= TS_ISOPEN;
f9eea644 613 bzero((caddr_t)&tp->t_winsize, sizeof(tp->t_winsize));
2c6a4e11
MT
614 /*
615 * CHANGE: used to do a ttywflush() if it was the
616 * old (old) line discipline.
617 */
4f3a716e 618 }
fc6972ae 619 return (0);
4147b3f6
BJ
620}
621
605d7712
MK
622/*
623 * "close" a line discipline
624 */
625ttylclose(tp)
626 register struct tty *tp;
627{
628
629 ttywflush(tp);
605d7712
MK
630}
631
4147b3f6
BJ
632/*
633 * clean tp on last close
634 */
635ttyclose(tp)
4b72e2f9 636 register struct tty *tp;
4147b3f6 637{
adf4bc89
MK
638 if (constty == tp)
639 constty = NULL;
605d7712 640 ttyflush(tp, FREAD|FWRITE);
e39f9ea6 641 tp->t_pgid = 0;
4147b3f6
BJ
642 tp->t_state = 0;
643}
644
605d7712
MK
645/*
646 * Handle modem control transition on a tty.
647 * Flag indicates new state of carrier.
648 * Returns 0 if the line should be turned off, otherwise 1.
649 */
650ttymodem(tp, flag)
651 register struct tty *tp;
652{
653
2c6a4e11 654 if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_lflag & MDMBUF)) {
605d7712
MK
655 /*
656 * MDMBUF: do flow control according to carrier flag
657 */
658 if (flag) {
659 tp->t_state &= ~TS_TTSTOP;
660 ttstart(tp);
661 } else if ((tp->t_state&TS_TTSTOP) == 0) {
662 tp->t_state |= TS_TTSTOP;
663 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
664 }
665 } else if (flag == 0) {
666 /*
667 * Lost carrier.
668 */
669 tp->t_state &= ~TS_CARR_ON;
670 if (tp->t_state & TS_ISOPEN) {
2c6a4e11 671 if ((tp->t_lflag & NOHANG) == 0) {
e39f9ea6
MT
672 gsignal(tp->t_pgid, SIGHUP);
673 gsignal(tp->t_pgid, SIGCONT);
605d7712
MK
674 ttyflush(tp, FREAD|FWRITE);
675 return (0);
676 }
677 }
678 } else {
679 /*
680 * Carrier now on.
681 */
682 tp->t_state |= TS_CARR_ON;
66ad69d6 683 ttwakeup(tp);
605d7712
MK
684 }
685 return (1);
686}
687
e3f2038d
MK
688/*
689 * Default modem control routine (for other line disciplines).
690 * Return argument flag, to turn off device on carrier drop.
691 */
2f54b5e8
MK
692nullmodem(tp, flag)
693 register struct tty *tp;
e3f2038d
MK
694 int flag;
695{
696
697 if (flag)
698 tp->t_state |= TS_CARR_ON;
699 else
700 tp->t_state &= ~TS_CARR_ON;
701 return (flag);
702}
703
4147b3f6
BJ
704/*
705 * reinput pending characters after state switch
4f3a716e 706 * call at spltty().
4147b3f6
BJ
707 */
708ttypend(tp)
4b72e2f9 709 register struct tty *tp;
4147b3f6
BJ
710{
711 struct clist tq;
712 register c;
713
2c6a4e11 714 tp->t_lflag &= ~PENDIN;
becb115c 715 tp->t_state |= TS_TYPEN;
4147b3f6
BJ
716 tq = tp->t_rawq;
717 tp->t_rawq.c_cc = 0;
718 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
719 while ((c = getc(&tq)) >= 0)
720 ttyinput(c, tp);
becb115c 721 tp->t_state &= ~TS_TYPEN;
4147b3f6
BJ
722}
723
724/*
e39f9ea6 725 *
2c6a4e11 726 *
becb115c
SL
727 * Place a character on raw TTY input queue,
728 * putting in delimiters and waking up top
729 * half as needed. Also echo if required.
730 * The arguments are the character and the
731 * appropriate tty structure.
4147b3f6
BJ
732 */
733ttyinput(c, tp)
4b72e2f9
SL
734 register c;
735 register struct tty *tp;
4147b3f6 736{
2c6a4e11
MT
737 register int iflag = tp->t_iflag;
738 register int lflag = tp->t_lflag;
739 register u_char *cc = tp->t_cc;
740 int i, err;
4147b3f6 741
becb115c
SL
742 /*
743 * If input is pending take it first.
744 */
2c6a4e11 745 if (lflag&PENDIN)
4147b3f6 746 ttypend(tp);
e39f9ea6
MT
747 /*
748 * Gather stats.
749 */
2c6a4e11 750
4147b3f6 751 tk_nin++;
e39f9ea6
MT
752 if (lflag&ICANON) {
753 tk_cancc++;
754 tp->t_cancc++;
755 } else {
756 tk_rawcc++;
757 tp->t_rawcc++;
758 }
becb115c 759 /*
2c6a4e11 760 * Handle exceptional conditions (break, parity, framing).
becb115c 761 */
2c6a4e11
MT
762 if (err = (c&TTY_ERRORMASK)) {
763 c &= TTY_CHARMASK;
764 if (err&TTY_FE && !c) { /* break */
765 if (iflag&IGNBRK)
766 goto endcase;
767 else if (iflag&BRKINT && lflag&ISIG &&
768 (cc[VINTR] != POSIX_V_DISABLE))
769 c = cc[VINTR];
770 else
771 c = 0;
772 } else if ((err&TTY_PE && iflag&INPCK) || err&TTY_FE) {
773 if (iflag&IGNPAR)
774 goto endcase;
775 else if (iflag&PARMRK) {
776 ttyinput(0377, tp);
777 ttyinput(0, tp);
778 } else
779 c = 0;
4147b3f6 780 }
becb115c 781 }
2c6a4e11
MT
782 dprintf("<%o>\n", c);
783
784 /*
785 * In tandem mode, check high water mark.
786 */
787 if (iflag&IXOFF)
788 ttyblock(tp);
789
becb115c 790 /*
e39f9ea6 791 * In tandem mode, check high water mark.
becb115c 792 */
2c6a4e11 793 if ((tp->t_state&TS_TYPEN) == 0 && (iflag&ISTRIP))
becb115c
SL
794 c &= 0177;
795 /*
796 * Check for literal nexting very first
797 */
798 if (tp->t_state&TS_LNCH) {
e39f9ea6 799 c |= TTY_QUOTE;
becb115c
SL
800 tp->t_state &= ~TS_LNCH;
801 }
becb115c
SL
802 /*
803 * Scan for special characters. This code
804 * is really just a big case statement with
805 * non-constant cases. The bottom of the
806 * case statement is labeled ``endcase'', so goto
807 * it after a case match, or similar.
808 */
2c6a4e11
MT
809
810 /*
811 * Extensions to POSIX input modes which aren't controlled
812 * by ICANON, ISIG, or IXON.
813 */
814 if (iflag&IEXTEN) {
815 if (CCEQ(cc[VLNEXT],c) && (iflag&ISTRIP)) {
816 if (lflag&ECHO)
817 ttyout("^\b", tp); /*XXX - presumes too much */
becb115c
SL
818 tp->t_state |= TS_LNCH;
819 goto endcase;
820 }
2c6a4e11
MT
821 if (CCEQ(cc[VFLUSHO],c)) {
822 if (lflag&FLUSHO)
823 tp->t_lflag &= ~FLUSHO;
4147b3f6 824 else {
88a7a62a 825 ttyflush(tp, FWRITE);
4147b3f6 826 ttyecho(c, tp);
becb115c 827 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
4147b3f6 828 ttyretype(tp);
2c6a4e11 829 tp->t_lflag |= FLUSHO;
4147b3f6 830 }
becb115c
SL
831 goto startoutput;
832 }
2c6a4e11
MT
833 }
834
835 /*
836 * Signals.
837 */
838 if (lflag&ISIG) {
839 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
840 if ((lflag&NOFLSH) == 0)
841 ttyflush(tp, FREAD|FWRITE);
842 ttyecho(c, tp);
843 gsignal(tp->t_pgrp, CCEQ(cc[VINTR],c) ?
844 SIGINT : SIGQUIT);
845 goto endcase;
846 }
847 if (CCEQ(cc[VSUSP],c)) {
848 if ((lflag&NOFLSH) == 0)
88a7a62a 849 ttyflush(tp, FREAD);
4147b3f6 850 ttyecho(c, tp);
e39f9ea6 851 gsignal(tp->t_pgid, SIGTSTP);
becb115c
SL
852 goto endcase;
853 }
854 }
becb115c
SL
855 /*
856 * Handle start/stop characters.
857 */
2c6a4e11
MT
858 if (iflag&IXON) {
859 if (CCEQ(cc[VSTOP],c)) {
860 if ((tp->t_state&TS_TTSTOP) == 0) {
861 tp->t_state |= TS_TTSTOP;
862 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
863 return;
864 }
865 if (!CCEQ(cc[VSTART], c))
866 return;
867 /*
868 * if VSTART == VSTOP we toggle
869 */
870 goto endcase;
becb115c 871 }
2c6a4e11
MT
872 if (CCEQ(cc[VSTART], c))
873 goto restartoutput;
becb115c 874 }
becb115c 875 /*
2c6a4e11 876 * IGNCR, ICRNL, & INLCR
becb115c 877 */
2c6a4e11
MT
878 if (c == '\r') {
879 if (iflag&IGNCR)
880 goto endcase;
881 else if (iflag&ICRNL)
882 c = '\n';
becb115c 883 }
2c6a4e11
MT
884 else if (c == '\n' && iflag&INLCR)
885 c = '\r';
e39f9ea6
MT
886 else if (c == '\n' && iflag&INLCR)
887 c = '\r';
becb115c 888 /*
2c6a4e11 889 * Non canonical mode, don't process line editing
becb115c 890 * characters; check high water mark for wakeup.
2c6a4e11 891 *
e39f9ea6 892 *
becb115c 893 */
2c6a4e11 894 if (!(lflag&ICANON)) {
becb115c 895 if (tp->t_rawq.c_cc > TTYHOG) {
2c6a4e11 896 if (iflag&IMAXBEL) {
e39f9ea6 897 if (tp->t_outq.c_cc < tp->t_hiwat)
2c6a4e11
MT
898 (void) ttyoutput(CTRL('g'), tp);
899 } else
900 ttyflush(tp, FREAD | FWRITE);
e39f9ea6
MT
901 } else {
902 if (putc(c, &tp->t_rawq) >= 0) {
903 ttwakeup(tp);
904 ttyecho(c, tp);
905 }
4147b3f6 906 }
becb115c
SL
907 goto endcase;
908 }
becb115c 909 /*
2c6a4e11 910 * From here on down canonical mode character
becb115c
SL
911 * processing takes place.
912 */
2c6a4e11
MT
913
914 /*
915 * Oldstyle quoting of erase, kill, and eof chars.
916 *
917 * Historically is '\' , but can be changed (read: disabled)
918 * with the VQUOTE subscript.
919 */
2c6a4e11
MT
920
921 /*
922 * erase (^H / ^?)
923 */
924 if (CCEQ(cc[VERASE], c)) {
becb115c
SL
925 if (tp->t_rawq.c_cc)
926 ttyrub(unputc(&tp->t_rawq), tp);
927 goto endcase;
928 }
66ad69d6
MT
929 if (lflag&ECHOKE && tp->t_rawq.c_cc == tp->t_rocount &&
930 !(lflag&ECHOPRT)) {
becb115c
SL
931 while (tp->t_rawq.c_cc)
932 ttyrub(unputc(&tp->t_rawq), tp);
933 } else {
934 ttyecho(c, tp);
2c6a4e11
MT
935 if (lflag&ECHOK || lflag&ECHOKE)
936 ttyecho('\n', tp);
becb115c
SL
937 while (getc(&tp->t_rawq) > 0)
938 ;
939 tp->t_rocount = 0;
940 }
941 tp->t_state &= ~TS_LOCAL;
942 goto endcase;
943 }
becb115c 944 /*
2c6a4e11 945 * word erase (^W)
becb115c 946 */
2c6a4e11
MT
947 c = unputc(&tp->t_rawq);
948 } while (c != ' ' && c != '\t');
949 (void) putc(c, &tp->t_rawq);
950 goto endcase;
951 }
952 /*
953 * reprint line (^R)
954 */
955 if (CCEQ(cc[VREPRINT], c)) {
956 ttyretype(tp);
957 goto endcase;
becb115c 958 }
e39f9ea6
MT
959 /*
960 * reprint line (^R)
961 */
962 if (CCEQ(cc[VREPRINT], c)) {
963 ttyretype(tp);
964 goto endcase;
965 }
becb115c
SL
966 /*
967 * Check for input buffer overflow
968 */
7c9f96c0 969 if (tp->t_rawq.c_cc+tp->t_canq.c_cc >= TTYHOG) {
2c6a4e11
MT
970 if (iflag&IMAXBEL) {
971 if (tp->t_outq.c_cc < TTHIWAT(tp))
972 (void) ttyoutput(CTRL('g'), tp);
973 } else
974 ttyflush(tp, FREAD | FWRITE);
becb115c 975 goto endcase;
7c9f96c0 976 }
becb115c
SL
977 /*
978 * Put data char in q for user and
979 * wakeup on seeing a line delimiter.
980 */
981 if (putc(c, &tp->t_rawq) >= 0) {
2c6a4e11 982 if (ttbreakc(c)) {
becb115c
SL
983 tp->t_rocount = 0;
984 catq(&tp->t_rawq, &tp->t_canq);
4147b3f6 985 ttwakeup(tp);
becb115c
SL
986 } else if (tp->t_rocount++ == 0)
987 tp->t_rocol = tp->t_col;
2c6a4e11
MT
988 if (CCEQ(cc[VQUOTE], c) && (iflag&ISTRIP))
989 tp->t_state |= TS_QUOT; /* '\' escape */
becb115c 990 if (tp->t_state&TS_ERASE) {
e39f9ea6
MT
991 /*
992 * end of prterase \.../
993 */
2c6a4e11
MT
994 /*
995 * end of prterase \.../
996 */
becb115c
SL
997 tp->t_state &= ~TS_ERASE;
998 (void) ttyoutput('/', tp);
999 }
1000 i = tp->t_col;
4147b3f6 1001 ttyecho(c, tp);
2c6a4e11
MT
1002 if (CCEQ(cc[VEOF], c) && lflag&ECHO) {
1003 /*
1004 * Place the cursor over the '^' of the ^D.
1005 */
becb115c
SL
1006 i = MIN(2, tp->t_col - i);
1007 while (i > 0) {
1008 (void) ttyoutput('\b', tp);
1009 i--;
1010 }
1011 }
4147b3f6 1012 }
becb115c
SL
1013endcase:
1014 /*
2c6a4e11 1015 * IXANY means allow any character to restart output.
becb115c 1016 */
2c6a4e11
MT
1017 if (tp->t_state&TS_TTSTOP && (iflag&IXANY == 0)
1018 && cc[VSTART] != cc[VSTOP])
4147b3f6 1019 return;
2c6a4e11 1020
becb115c 1021restartoutput:
4147b3f6 1022 tp->t_state &= ~TS_TTSTOP;
2c6a4e11 1023 tp->t_lflag &= ~FLUSHO;
becb115c 1024startoutput:
4147b3f6
BJ
1025 ttstart(tp);
1026}
1027
1028/*
becb115c 1029 * Put character on TTY output queue, adding delays,
4147b3f6 1030 * expanding tabs, and handling the CR/NL bit.
becb115c
SL
1031 * This is called both from the top half for output,
1032 * and from interrupt level for echoing.
4147b3f6
BJ
1033 * The arguments are the character and the tty structure.
1034 * Returns < 0 if putc succeeds, otherwise returns char to resend
1035 * Must be recursive.
1036 */
1037ttyoutput(c, tp)
1038 register c;
1039 register struct tty *tp;
1040{
1041 register char *colp;
1042 register ctype;
2c6a4e11
MT
1043 if (!(tp->t_oflag&OPOST)) {
1044 if (tp->t_lflag&FLUSHO)
4147b3f6
BJ
1045 return (-1);
1046 if (putc(c, &tp->t_outq))
4b72e2f9 1047 return (c);
4147b3f6 1048 tk_nout++;
e39f9ea6 1049 tp->t_outcc++;
4147b3f6
BJ
1050 return (-1);
1051 }
2c6a4e11 1052 c &= 0377;
4147b3f6
BJ
1053 /*
1054 * Turn tabs to spaces as required
1055 */
2c6a4e11 1056 if (c == '\t' && tp->t_oflag&OXTABS ) {
4147b3f6
BJ
1057 register int s;
1058
1059 c = 8 - (tp->t_col&7);
2c6a4e11 1060 if ((tp->t_lflag&FLUSHO) == 0) {
4f3a716e 1061 s = spltty(); /* don't interrupt tabs */
4147b3f6
BJ
1062 c -= b_to_q(" ", c, &tp->t_outq);
1063 tk_nout += c;
e39f9ea6 1064 tp->t_outcc += c;
4147b3f6
BJ
1065 splx(s);
1066 }
1067 tp->t_col += c;
1068 return (c ? -1 : '\t');
1069 }
e39f9ea6
MT
1070 if (c == CEOT && oflag&ONOEOT)
1071 return(-1);
4147b3f6 1072 tk_nout++;
e39f9ea6 1073 tp->t_outcc++;
2c6a4e11 1074#ifdef notdef
4147b3f6
BJ
1075 /*
1076 * turn <nl> to <cr><lf> if desired.
1077 */
2c6a4e11 1078#endif
e39f9ea6
MT
1079 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
1080 return (c);
2c6a4e11 1081 if ((tp->t_lflag&FLUSHO) == 0 && putc(c, &tp->t_outq))
4147b3f6
BJ
1082 return (c);
1083 /*
1084 * Calculate delays.
1085 * The numbers here represent clock ticks
1086 * and are not necessarily optimal for all terminals.
becb115c
SL
1087 *
1088 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
e39f9ea6
MT
1089 *
1090 * (actually, should THROW AWAY terminals which need delays)
4147b3f6
BJ
1091 */
1092 colp = &tp->t_col;
1093 ctype = partab[c];
1094 c = 0;
1095 switch (ctype&077) {
1096
1097 case ORDINARY:
1098 (*colp)++;
1099
1100 case CONTROL:
1101 break;
1102
1103 case BACKSPACE:
1104 if (*colp)
1105 (*colp)--;
1106 break;
1107
3686c829
SL
1108 /*
1109 * This macro is close enough to the correct thing;
1110 * it should be replaced by real user settable delays
1111 * in any event...
1112 */
1113#define mstohz(ms) (((ms) * hz) >> 10)
4147b3f6
BJ
1114 case NEWLINE:
1115 ctype = (tp->t_flags >> 8) & 03;
4b72e2f9 1116 if (ctype == 1) { /* tty 37 */
8011f5df
MK
1117 if (*colp > 0) {
1118 c = (((unsigned)*colp) >> 4) + 3;
1119 if ((unsigned)c > 6)
1120 c = 6;
1121 }
becb115c 1122 } else if (ctype == 2) /* vt05 */
3686c829 1123 c = mstohz(100);
4147b3f6
BJ
1124 *colp = 0;
1125 break;
1126
1127 case TAB:
1128 ctype = (tp->t_flags >> 10) & 03;
4b72e2f9 1129 if (ctype == 1) { /* tty 37 */
4147b3f6 1130 c = 1 - (*colp | ~07);
4b72e2f9 1131 if (c < 5)
4147b3f6
BJ
1132 c = 0;
1133 }
1134 *colp |= 07;
1135 (*colp)++;
1136 break;
1137
1138 case VTAB:
becb115c 1139 if (tp->t_flags&VTDELAY) /* tty 37 */
4147b3f6
BJ
1140 c = 0177;
1141 break;
1142
1143 case RETURN:
1144 ctype = (tp->t_flags >> 12) & 03;
becb115c 1145 if (ctype == 1) /* tn 300 */
3686c829 1146 c = mstohz(83);
becb115c 1147 else if (ctype == 2) /* ti 700 */
3686c829 1148 c = mstohz(166);
becb115c 1149 else if (ctype == 3) { /* concept 100 */
4147b3f6 1150 int i;
becb115c 1151
4147b3f6 1152 if ((i = *colp) >= 0)
becb115c 1153 for (; i < 9; i++)
4147b3f6
BJ
1154 (void) putc(0177, &tp->t_outq);
1155 }
1156 *colp = 0;
1157 }
2c6a4e11 1158 if (c && (tp->t_lflag&FLUSHO) == 0)
e39f9ea6 1159 (void) putc(c|TTY_QUOTE, &tp->t_outq);
4147b3f6
BJ
1160 return (-1);
1161}
3686c829 1162#undef mstohz
4147b3f6
BJ
1163
1164/*
1165 * Called from device's read routine after it has
1166 * calculated the tty-structure given as argument.
1167 */
66ad69d6 1168ttread(tp, uio, flag)
4b72e2f9 1169 register struct tty *tp;
d6d7360b 1170 struct uio *uio;
4147b3f6
BJ
1171{
1172 register struct clist *qp;
2c6a4e11
MT
1173 register int c, t_flags;
1174 register long lflag = tp->t_lflag;
1175 register long iflag = tp->t_iflag;
1176 register u_char *cc = tp->t_cc;
875a1e2c 1177 int s, first, error = 0;
4147b3f6 1178
2c6a4e11 1179
4147b3f6 1180loop:
66ad69d6 1181 s = spltty();
becb115c 1182 /*
66ad69d6 1183 * take pending input first
becb115c 1184 */
2c6a4e11 1185 if (tp->t_lflag&PENDIN)
4147b3f6 1186 ttypend(tp);
66ad69d6
MT
1187 /*
1188 * Handle carrier.
1189 */
1190 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) {
1191 if (tp->t_state&TS_ISOPEN) {
1192 splx(s);
1193 return (0); /* EOF */
c4ec2128 1194 } else if (flag & IO_NDELAY) {
66ad69d6
MT
1195 splx(s);
1196 return (EWOULDBLOCK);
1197 } else {
1198 /*
1199 * sleep awaiting carrier
1200 */
1201 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1202 splx(s);
1203 goto loop;
1204 }
1205 }
875a1e2c 1206 splx(s);
becb115c
SL
1207 /*
1208 * Hang process if it's in the background.
1209 */
e39f9ea6 1210 if (u.u_ttyp == tp && u.u_procp->p_pgid != tp->t_pgid) {
52c041cd
MK
1211 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
1212 (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
e39f9ea6 1213 u.u_procp->p_flag&SVFORK || u.u_procp->p_pgrp->pg_jobc == 0)
840510a3 1214 return (EIO);
e39f9ea6 1215 pgsignal(u.u_procp->p_pgrp, SIGTTIN);
4147b3f6 1216 sleep((caddr_t)&lbolt, TTIPRI);
58786a81 1217 goto loop;
4147b3f6 1218 }
becb115c 1219 /*
2c6a4e11
MT
1220 * If canonical, use the canonical queue,
1221 * else use the raw queue.
becb115c 1222 */
2c6a4e11 1223 qp = lflag&ICANON ? &tp->t_canq : &tp->t_rawq;
becb115c
SL
1224 /*
1225 * No input, sleep on rawq awaiting hardware
1226 * receipt and notification.
1227 */
4f3a716e 1228 s = spltty();
becb115c 1229 if (qp->c_cc <= 0) {
66ad69d6 1230 /** XXX ??? ask mike why TS_CARR_ON was (once) necessary here
becb115c
SL
1231 if ((tp->t_state&TS_CARR_ON) == 0 ||
1232 (tp->t_state&TS_NBIO)) {
875a1e2c 1233 splx(s);
becb115c 1234 return (EWOULDBLOCK);
4147b3f6 1235 }
66ad69d6 1236 **/
c4ec2128 1237 if (flag & IO_NDELAY) {
66ad69d6
MT
1238 splx(s);
1239 return (EWOULDBLOCK);
1240 }
becb115c 1241 sleep((caddr_t)&tp->t_rawq, TTIPRI);
875a1e2c 1242 splx(s);
becb115c
SL
1243 goto loop;
1244 }
875a1e2c 1245 splx(s);
becb115c 1246 /*
2c6a4e11 1247 * Input present, check for input mapping and processing.
becb115c
SL
1248 */
1249 first = 1;
1250 while ((c = getc(qp)) >= 0) {
becb115c 1251 /*
2c6a4e11 1252 * delayed suspend (^Y)
becb115c 1253 */
2c6a4e11 1254 if (CCEQ(cc[VDSUSP], c) && lflag&ISIG) {
e39f9ea6 1255 gsignal(tp->t_pgid, SIGTSTP);
becb115c
SL
1256 if (first) {
1257 sleep((caddr_t)&lbolt, TTIPRI);
1258 goto loop;
1259 }
1260 break;
4147b3f6 1261 }
becb115c 1262 /*
2c6a4e11 1263 * Interpret EOF only in canonical mode.
becb115c 1264 */
2c6a4e11 1265 if (CCEQ(cc[VEOF], c) && lflag&ICANON)
becb115c
SL
1266 break;
1267 /*
1268 * Give user character.
1269 */
2c6a4e11 1270 error = ureadc(iflag&ISTRIP ? c & 0177 : c , uio);
becb115c
SL
1271 if (error)
1272 break;
9ec65acb 1273 if (uio->uio_resid == 0)
becb115c
SL
1274 break;
1275 /*
2c6a4e11 1276 * In canonical mode check for a "break character"
becb115c
SL
1277 * marking the end of a "line of input".
1278 */
2c6a4e11 1279 if (lflag&ICANON && ttbreakc(c)) {
becb115c 1280 break;
2c6a4e11 1281 }
e39f9ea6 1282 }
becb115c 1283 first = 0;
4147b3f6 1284 }
becb115c
SL
1285 /*
1286 * Look to unblock output now that (presumably)
1287 * the input queue has gone down.
1288 */
2c6a4e11
MT
1289 if (tp->t_state&TS_TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
1290 if (cc[VSTART] != POSIX_V_DISABLE
1291 && putc(cc[VSTART], &tp->t_outq) == 0) {
4147b3f6
BJ
1292 tp->t_state &= ~TS_TBLOCK;
1293 ttstart(tp);
1294 }
2c6a4e11 1295 }
e39f9ea6 1296 }
840510a3 1297 return (error);
4147b3f6
BJ
1298}
1299
605d7712
MK
1300/*
1301 * Check the output queue on tp for space for a kernel message
1302 * (from uprintf/tprintf). Allow some space over the normal
1303 * hiwater mark so we don't lose messages due to normal flow
1304 * control, but don't let the tty run amok.
ca9b16e5
MK
1305 * Sleeps here are not interruptible, but we return prematurely
1306 * if new signals come in.
605d7712
MK
1307 */
1308ttycheckoutq(tp, wait)
1309 register struct tty *tp;
1310 int wait;
1311{
ca9b16e5 1312 int hiwat, s, oldsig;
605d7712 1313
e39f9ea6 1314 hiwat = tp->t_hiwat;
605d7712 1315 s = spltty();
ca9b16e5 1316 oldsig = u.u_procp->p_sig;
605d7712 1317 if (tp->t_outq.c_cc > hiwat + 200)
fb1db32c
MK
1318 while (tp->t_outq.c_cc > hiwat) {
1319 ttstart(tp);
ca9b16e5 1320 if (wait == 0 || u.u_procp->p_sig != oldsig) {
fb1db32c
MK
1321 splx(s);
1322 return (0);
1323 }
ca9b16e5 1324 timeout(wakeup, (caddr_t)&tp->t_outq, hz);
fb1db32c 1325 tp->t_state |= TS_ASLEEP;
ca9b16e5 1326 sleep((caddr_t)&tp->t_outq, PZERO - 1);
605d7712 1327 }
605d7712
MK
1328 splx(s);
1329 return (1);
1330}
1331
4147b3f6
BJ
1332/*
1333 * Called from the device's write routine after it has
1334 * calculated the tty-structure given as argument.
1335 */
66ad69d6 1336ttwrite(tp, uio, flag)
4b72e2f9 1337 register struct tty *tp;
becb115c 1338 register struct uio *uio;
4147b3f6 1339{
4147b3f6 1340 register char *cp;
c4ec2128 1341 register int cc, ce;
becb115c 1342 int i, hiwat, cnt, error, s;
4147b3f6 1343 char obuf[OBUFSIZ];
4147b3f6 1344
e39f9ea6 1345 hiwat = tp->t_hiwat;
becb115c
SL
1346 cnt = uio->uio_resid;
1347 error = 0;
4147b3f6 1348loop:
66ad69d6
MT
1349 s = spltty();
1350 if (!(tp->t_state&TS_CARR_ON) && !(tp->t_cflag&CLOCAL)) {
1351 if (tp->t_state&TS_ISOPEN) {
1352 splx(s);
1353 return (EIO);
c4ec2128 1354 } else if (flag & IO_NDELAY) {
66ad69d6
MT
1355 splx(s);
1356 return (EWOULDBLOCK);
1357 } else {
1358 /*
1359 * sleep awaiting carrier
1360 */
1361 sleep((caddr_t)&tp->t_rawq, TTIPRI);
1362 splx(s);
1363 goto loop;
1364 }
1365 }
1366 splx(s);
becb115c
SL
1367 /*
1368 * Hang the process if it's in the background.
1369 */
2c6a4e11 1370 (tp->t_lflag&TOSTOP) && (u.u_procp->p_flag&SVFORK)==0 &&
52c041cd 1371 !(u.u_procp->p_sigignore & sigmask(SIGTTOU)) &&
e39f9ea6
MT
1372 !(u.u_procp->p_sigmask & sigmask(SIGTTOU)) &&
1373 u.u_procp->p_pgrp->pg_jobc) {
1374 pgsignal(u.u_procp->p_pgrp, SIGTTOU);
4147b3f6 1375 sleep((caddr_t)&lbolt, TTIPRI);
93d2ecff 1376 goto loop;
4147b3f6 1377 }
becb115c
SL
1378 /*
1379 * Process the user's data in at most OBUFSIZ
1380 * chunks. Perform lower case simulation and
1381 * similar hacks. Keep track of high water
1382 * mark, sleep on overflow awaiting device aid
1383 * in acquiring new space.
1384 */
913ea2d1 1385 while (uio->uio_resid > 0) {
b482b2c8
MK
1386 if (tp->t_outq.c_cc > hiwat) {
1387 cc = 0;
1388 goto ovhiwat;
1389 }
becb115c
SL
1390 /*
1391 * Grab a hunk of data from the user.
1392 */
913ea2d1
BJ
1393 cc = uio->uio_iov->iov_len;
1394 if (cc == 0) {
1395 uio->uio_iovcnt--;
1396 uio->uio_iov++;
93d2ecff 1397 if (uio->uio_iovcnt <= 0)
913ea2d1
BJ
1398 panic("ttwrite");
1399 continue;
1400 }
1401 if (cc > OBUFSIZ)
1402 cc = OBUFSIZ;
4147b3f6 1403 cp = obuf;
c4ec2128 1404 error = uiomove(cp, cc, uio);
840510a3 1405 if (error)
4147b3f6 1406 break;
2c6a4e11 1407 if (tp->t_lflag&FLUSHO)
4147b3f6 1408 continue;
2c6a4e11 1409#ifdef notdef
becb115c
SL
1410 /*
1411 * If nothing fancy need be done, grab those characters we
1412 * can handle without any of ttyoutput's processing and
1413 * just transfer them to the output q. For those chars
1414 * which require special processing (as indicated by the
1415 * bits in partab), call ttyoutput. After processing
1416 * a hunk of data, look for FLUSHO so ^O's will take effect
1417 * immediately.
1418 */
1419 while (cc > 0) {
2c6a4e11 1420 if (!(tp->t_oflag&OPOST))
4147b3f6
BJ
1421 ce = cc;
1422 else {
3f36033f
MK
1423 ce = cc - scanc((unsigned)cc, (u_char *)cp,
1424 (u_char *)partab, 077);
becb115c
SL
1425 /*
1426 * If ce is zero, then we're processing
1427 * a special character through ttyoutput.
1428 */
1429 if (ce == 0) {
4147b3f6
BJ
1430 tp->t_rocount = 0;
1431 if (ttyoutput(*cp, tp) >= 0) {
93d2ecff
JB
1432 /* no c-lists, wait a bit */
1433 ttstart(tp);
1434 sleep((caddr_t)&lbolt, TTOPRI);
1435 if (cc != 0) {
1436 uio->uio_iov->iov_base -= cc;
1437 uio->uio_iov->iov_len += cc;
1438 uio->uio_resid += cc;
1439 uio->uio_offset -= cc;
1440 }
1441 goto loop;
4147b3f6 1442 }
becb115c 1443 cp++, cc--;
2c6a4e11 1444 if (tp->t_lflag&FLUSHO ||
becb115c 1445 tp->t_outq.c_cc > hiwat)
4147b3f6 1446 goto ovhiwat;
becb115c 1447 continue;
4147b3f6
BJ
1448 }
1449 }
becb115c
SL
1450 /*
1451 * A bunch of normal characters have been found,
1452 * transfer them en masse to the output queue and
1453 * continue processing at the top of the loop.
1454 * If there are any further characters in this
1455 * <= OBUFSIZ chunk, the first should be a character
1456 * requiring special handling by ttyoutput.
1457 */
4147b3f6 1458 tp->t_rocount = 0;
becb115c
SL
1459 i = b_to_q(cp, ce, &tp->t_outq);
1460 ce -= i;
1461 tp->t_col += ce;
1462 cp += ce, cc -= ce, tk_nout += ce;
e39f9ea6 1463 tp->t_outcc += ce;
becb115c
SL
1464 if (i > 0) {
1465 /* out of c-lists, wait a bit */
4147b3f6
BJ
1466 ttstart(tp);
1467 sleep((caddr_t)&lbolt, TTOPRI);
93d2ecff
JB
1468 uio->uio_iov->iov_base -= cc;
1469 uio->uio_iov->iov_len += cc;
1470 uio->uio_resid += cc;
1471 uio->uio_offset -= cc;
1472 goto loop;
4147b3f6 1473 }
2c6a4e11 1474 if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat)
4147b3f6
BJ
1475 goto ovhiwat;
1476 }
2c6a4e11 1477 ttstart(tp);
e39f9ea6 1478 ttstart(tp);
4147b3f6 1479 }
840510a3 1480 return (error);
4147b3f6 1481ovhiwat:
becb115c
SL
1482 if (cc != 0) {
1483 uio->uio_iov->iov_base -= cc;
1484 uio->uio_iov->iov_len += cc;
1485 uio->uio_resid += cc;
1486 uio->uio_offset -= cc;
1487 }
b482b2c8
MK
1488 ttstart(tp);
1489 s = spltty();
becb115c 1490 /*
2c6a4e11 1491 * This can only occur if FLUSHO is set in t_lflag,
b482b2c8 1492 * or if ttstart/oproc is synchronous (or very fast).
becb115c 1493 */
4147b3f6 1494 if (tp->t_outq.c_cc <= hiwat) {
becb115c 1495 splx(s);
4147b3f6
BJ
1496 goto loop;
1497 }
c4ec2128 1498 if (flag & IO_NDELAY) {
4f3a716e 1499 splx(s);
913ea2d1 1500 if (uio->uio_resid == cnt)
840510a3
BJ
1501 return (EWOULDBLOCK);
1502 return (0);
4147b3f6
BJ
1503 }
1504 tp->t_state |= TS_ASLEEP;
1505 sleep((caddr_t)&tp->t_outq, TTOPRI);
becb115c 1506 splx(s);
4147b3f6
BJ
1507 goto loop;
1508}
1509
1510/*
1511 * Rubout one character from the rawq of tp
1512 * as cleanly as possible.
1513 */
1514ttyrub(c, tp)
4b72e2f9
SL
1515 register c;
1516 register struct tty *tp;
4147b3f6
BJ
1517{
1518 register char *cp;
1519 register int savecol;
1520 int s;
1521 char *nextc();
1522
2c6a4e11 1523 if ((tp->t_lflag&ECHO) == 0)
4147b3f6 1524 return;
2c6a4e11 1525 if (tp->t_lflag&ECHOE) {
4147b3f6
BJ
1526 if (tp->t_rocount == 0) {
1527 /*
1528 * Screwed by ttwrite; retype
1529 */
1530 ttyretype(tp);
1531 return;
1532 }
2c6a4e11 1533 /* if tab or newline was escaped - XXX - not 8bit */
e39f9ea6 1534 if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE))
4147b3f6 1535 ttyrubo(tp, 2);
e39f9ea6 1536 else switch (partab[c&=0377]&077) {
4147b3f6
BJ
1537
1538 case ORDINARY:
2c6a4e11 1539#ifdef notdef
e39f9ea6 1540 ttyrubo(tp, 1);
4147b3f6
BJ
1541 break;
1542
1543 case VTAB:
1544 case BACKSPACE:
1545 case CONTROL:
1546 case RETURN:
2c6a4e11 1547 if (tp->t_lflag&ECHOCTL)
4147b3f6
BJ
1548 ttyrubo(tp, 2);
1549 break;
1550
e39f9ea6
MT
1551 case TAB: {
1552 int c;
1553
4147b3f6
BJ
1554 if (tp->t_rocount < tp->t_rawq.c_cc) {
1555 ttyretype(tp);
1556 return;
1557 }
4f3a716e 1558 s = spltty();
4147b3f6 1559 savecol = tp->t_col;
becb115c 1560 tp->t_state |= TS_CNTTB;
2c6a4e11 1561 tp->t_lflag |= FLUSHO;
4147b3f6 1562 tp->t_col = tp->t_rocol;
becb115c 1563 cp = tp->t_rawq.c_cf;
2c6a4e11 1564 tp->t_lflag &= ~FLUSHO;
becb115c 1565 tp->t_state &= ~TS_CNTTB;
4147b3f6
BJ
1566 splx(s);
1567 /*
1568 * savecol will now be length of the tab
1569 */
1570 savecol -= tp->t_col;
1571 tp->t_col += savecol;
1572 if (savecol > 8)
1573 savecol = 8; /* overflow screw */
1574 while (--savecol >= 0)
1575 (void) ttyoutput('\b', tp);
1576 break;
e39f9ea6 1577 }
4147b3f6
BJ
1578
1579 default:
66ad69d6 1580 /* XXX */
e39f9ea6
MT
1581 printf("ttyrub: would panic c = %d, val = %d\n",
1582 c, partab[c&=0377]&077);
1583 /*panic("ttyrub");*/
4147b3f6 1584 }
2c6a4e11 1585 } else if (tp->t_lflag&ECHOPRT) {
becb115c 1586 if ((tp->t_state&TS_ERASE) == 0) {
4147b3f6 1587 (void) ttyoutput('\\', tp);
becb115c 1588 tp->t_state |= TS_ERASE;
4147b3f6
BJ
1589 }
1590 ttyecho(c, tp);
1591 } else
2c6a4e11 1592 ttyecho(tp->t_cc[VERASE], tp);
4147b3f6
BJ
1593 tp->t_rocount--;
1594}
1595
1596/*
1597 * Crt back over cnt chars perhaps
1598 * erasing them.
1599 */
1600ttyrubo(tp, cnt)
4b72e2f9
SL
1601 register struct tty *tp;
1602 int cnt;
4147b3f6 1603{
2c6a4e11 1604 register char *rubostring = tp->t_lflag&ECHOE ? "\b \b" : "\b";
4147b3f6
BJ
1605
1606 while (--cnt >= 0)
e39f9ea6 1607 ttyout("\b \b", tp);
4147b3f6
BJ
1608}
1609
1610/*
1611 * Reprint the rawq line.
1612 * We assume c_cc has already been checked.
1613 */
1614ttyretype(tp)
4b72e2f9 1615 register struct tty *tp;
4147b3f6
BJ
1616{
1617 register char *cp;
1618 char *nextc();
e39f9ea6 1619 int s, c;
4147b3f6 1620
2c6a4e11
MT
1621 if (tp->t_cc[VREPRINT] != POSIX_V_DISABLE)
1622 ttyecho(tp->t_cc[VREPRINT], tp);
4147b3f6 1623 (void) ttyoutput('\n', tp);
4f3a716e 1624 s = spltty();
e39f9ea6
MT
1625 /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1626 BIT OF FIRST CHAR ****/
1627 for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) {
1628 ttyecho(c, tp);
1629 }
1630 for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
1631 ttyecho(c, tp);
1632 }
becb115c 1633 tp->t_state &= ~TS_ERASE;
4147b3f6
BJ
1634 splx(s);
1635 tp->t_rocount = tp->t_rawq.c_cc;
1636 tp->t_rocol = 0;
1637}
1638
1639/*
2c6a4e11 1640 * Echo a typed character to the terminal.
4147b3f6
BJ
1641 */
1642ttyecho(c, tp)
4b72e2f9
SL
1643 register c;
1644 register struct tty *tp;
4147b3f6 1645{
4147b3f6 1646 c &= 0377;
2c6a4e11
MT
1647 if ((tp->t_state&TS_CNTTB) == 0)
1648 tp->t_lflag &= ~FLUSHO;
1649 if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n'))
4147b3f6 1650 return;
2c6a4e11 1651 if (tp->t_lflag&ECHOCTL) {
e39f9ea6 1652 if ((c&TTY_CHARMASK)<=037 && c!='\t' && c!='\n' || c==0177) {
4147b3f6 1653 (void) ttyoutput('^', tp);
e39f9ea6 1654 c &= TTY_CHARMASK;
4147b3f6
BJ
1655 if (c == 0177)
1656 c = '?';
2c6a4e11 1657#ifdef notdef
2c6a4e11 1658#endif
4147b3f6
BJ
1659 else
1660 c += 'A' - 1;
1661 }
1662 }
e39f9ea6 1663 (void) ttyoutput(c, tp);
4147b3f6
BJ
1664 * send string cp to tp
1665 */
1666ttyout(cp, tp)
4b72e2f9
SL
1667 register char *cp;
1668 register struct tty *tp;
4147b3f6
BJ
1669{
1670 register char c;
1671
1672 while (c = *cp++)
1673 (void) ttyoutput(c, tp);
1674}
1675
1676ttwakeup(tp)
1677 struct tty *tp;
1678{
1679
1680 if (tp->t_rsel) {
1681 selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
1682 tp->t_state &= ~TS_RCOLL;
1683 tp->t_rsel = 0;
1684 }
88a7a62a 1685 if (tp->t_state & TS_ASYNC)
e39f9ea6 1686 gsignal(tp->t_pgid, SIGIO);
4147b3f6
BJ
1687 wakeup((caddr_t)&tp->t_rawq);
1688}
e39f9ea6
MT
1689
1690/*
1691 * set tty hi and low water marks
1692 *
1693 * Try to arrange the dynamics so there's about one second
1694 * from hi to low water.
1695 *
1696 */
1697ttsetwater(tp)
1698 struct tty *tp;
1699{
1700 register cps = tp->t_ospeed / 10;
1701 register x;
1702
1703#define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x))
1704 tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT);
1705 x += cps;
1706 x = clamp(x, TTMAXHIWAT, TTMINHIWAT);
1707 tp->t_hiwat = roundup(x, CBSIZE);
1708#undef clamp
1709}
1710
1711ttspeedtab(speed, table)
1712 struct speedtab table[];
1713{
1714 register int i;
1715
1716 for (i = 0; table[i].sp_speed != -1; i++)
1717 if (table[i].sp_speed == speed)
1718 return(table[i].sp_code);
1719 return(-1);
1720}