1 /*-
2 * Copyright (c) 1982, 1986, 1990, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * %sccs.include.redist.c%
11 *
12 * @(#)tty.c 8.13 (Berkeley) 01/09/95
13 */
14
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/ioctl.h>
18 #include <sys/proc.h>
19 #define TTYDEFCHARS
20 #include <sys/tty.h>
21 #undef TTYDEFCHARS
22 #include <sys/file.h>
23 #include <sys/conf.h>
24 #include <sys/dkstat.h>
25 #include <sys/uio.h>
26 #include <sys/kernel.h>
27 #include <sys/vnode.h>
28 #include <sys/syslog.h>
29
30 #include <vm/vm.h>
31
32 static int proc_compare __P((struct proc *p1, struct proc *p2));
33 static int ttnread __P((struct tty *));
34 static void ttyblock __P((struct tty *tp));
35 static void ttyecho __P((int, struct tty *tp));
36 static void ttyrubo __P((struct tty *, int));
37
38 /* Symbolic sleep message strings. */
39 char ttclos[] = "ttycls";
40 char ttopen[] = "ttyopn";
41 char ttybg[] = "ttybg";
42 char ttybuf[] = "ttybuf";
43 char ttyin[] = "ttyin";
44 char ttyout[] = "ttyout";
45
46 /*
47 * Table with character classes and parity. The 8th bit indicates parity,
48 * the 7th bit indicates the character is an alphameric or underscore (for
49 * ALTWERASE), and the low 6 bits indicate delay type. If the low 6 bits
50 * are 0 then the character needs no special processing on output; classes
51 * other than 0 might be translated or (not currently) require delays.
52 */
53 #define E 0x00 /* Even parity. */
54 #define O 0x80 /* Odd parity. */
55 #define PARITY(c) (char_type[c] & O)
56
57 #define ALPHA 0x40 /* Alpha or underscore. */
58 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
59
60 #define CCLASSMASK 0x3f
61 #define CCLASS(c) (char_type[c] & CCLASSMASK)
62
63 #define BS BACKSPACE
64 #define CC CONTROL
65 #define CR RETURN
66 #define NA ORDINARY | ALPHA
67 #define NL NEWLINE
68 #define NO ORDINARY
69 #define TB TAB
70 #define VT VTAB
71
72 char const char_type[] = {
73 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* nul - bel */
74 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC, /* bs - si */
75 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC, /* dle - etb */
76 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC, /* can - us */
77 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* sp - ' */
78 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO, /* ( - / */
79 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* 0 - 7 */
80 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO, /* 8 - ? */
81 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* @ - G */
82 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* H - O */
83 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* P - W */
84 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA, /* X - _ */
85 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA, /* ` - g */
86 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* h - o */
87 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA, /* p - w */
88 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC, /* x - del */
89 /*
90 * Meta chars; should be settable per character set;
91 * for now, treat them all as normal characters.
92 */
93 NA, NA, NA, NA, NA, NA, NA, NA,
94 NA, NA, NA, NA, NA, NA, NA, NA,
95 NA, NA, NA, NA, NA, NA, NA, NA,
96 NA, NA, NA, NA, NA, NA, NA, NA,
97 NA, NA, NA, NA, NA, NA, NA, NA,
98 NA, NA, NA, NA, NA, NA, NA, NA,
99 NA, NA, NA, NA, NA, NA, NA, NA,
100 NA, NA, NA, NA, NA, NA, NA, NA,
101 NA, NA, NA, NA, NA, NA, NA, NA,
102 NA, NA, NA, NA, NA, NA, NA, NA,
103 NA, NA, NA, NA, NA, NA, NA, NA,
104 NA, NA, NA, NA, NA, NA, NA, NA,
105 NA, NA, NA, NA, NA, NA, NA, NA,
106 NA, NA, NA, NA, NA, NA, NA, NA,
107 NA, NA, NA, NA, NA, NA, NA, NA,
108 NA, NA, NA, NA, NA, NA, NA, NA,
109 };
110 #undef BS
111 #undef CC
112 #undef CR
113 #undef NA
114 #undef NL
115 #undef NO
116 #undef TB
117 #undef VT
118
119 /* Macros to clear/set/test flags. */
120 #define SET(t, f) (t) |= (f)
121 #define CLR(t, f) (t) &= ~(f)
122 #define ISSET(t, f) ((t) & (f))
123
124 /*
125 * Initial open of tty, or (re)entry to standard tty line discipline.
126 */
127 int
ttyopen(device,tp)128 ttyopen(device, tp)
129 dev_t device;
130 register struct tty *tp;
131 {
132 int s;
133
134 s = spltty();
135 tp->t_dev = device;
136 if (!ISSET(tp->t_state, TS_ISOPEN)) {
137 SET(tp->t_state, TS_ISOPEN);
138 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
139 }
140 CLR(tp->t_state, TS_WOPEN);
141 splx(s);
142 return (0);
143 }
144
145 /*
146 * Handle close() on a tty line: flush and set to initial state,
147 * bumping generation number so that pending read/write calls
148 * can detect recycling of the tty.
149 */
150 int
ttyclose(tp)151 ttyclose(tp)
152 register struct tty *tp;
153 {
154 extern struct tty *constty; /* Temporary virtual console. */
155
156 if (constty == tp)
157 constty = NULL;
158
159 ttyflush(tp, FREAD | FWRITE);
160
161 tp->t_gen++;
162 tp->t_pgrp = NULL;
163 tp->t_session = NULL;
164 tp->t_state = 0;
165 return (0);
166 }
167
168 #define FLUSHQ(q) { \
169 if ((q)->c_cc) \
170 ndflush(q, (q)->c_cc); \
171 }
172
173 /* Is 'c' a line delimiter ("break" character)? */
174 #define TTBREAKC(c) \
175 ((c) == '\n' || ((c) == cc[VEOF] || \
176 (c) == cc[VEOL] || (c) == cc[VEOL2]) && (c) != _POSIX_VDISABLE)
177
178
179 /*
180 * Process input of a single character received on a tty.
181 */
182 int
ttyinput(c,tp)183 ttyinput(c, tp)
184 register int c;
185 register struct tty *tp;
186 {
187 register int iflag, lflag;
188 register u_char *cc;
189 int i, err;
190
191 /*
192 * If input is pending take it first.
193 */
194 lflag = tp->t_lflag;
195 if (ISSET(lflag, PENDIN))
196 ttypend(tp);
197 /*
198 * Gather stats.
199 */
200 if (ISSET(lflag, ICANON)) {
201 ++tk_cancc;
202 ++tp->t_cancc;
203 } else {
204 ++tk_rawcc;
205 ++tp->t_rawcc;
206 }
207 ++tk_nin;
208
209 /* Handle exceptional conditions (break, parity, framing). */
210 cc = tp->t_cc;
211 iflag = tp->t_iflag;
212 if (err = (ISSET(c, TTY_ERRORMASK))) {
213 CLR(c, TTY_ERRORMASK);
214 if (ISSET(err, TTY_FE) && !c) { /* Break. */
215 if (ISSET(iflag, IGNBRK))
216 goto endcase;
217 else if (ISSET(iflag, BRKINT) &&
218 ISSET(lflag, ISIG) &&
219 (cc[VINTR] != _POSIX_VDISABLE))
220 c = cc[VINTR];
221 else if (ISSET(iflag, PARMRK))
222 goto parmrk;
223 } else if (ISSET(err, TTY_PE) &&
224 ISSET(iflag, INPCK) || ISSET(err, TTY_FE)) {
225 if (ISSET(iflag, IGNPAR))
226 goto endcase;
227 else if (ISSET(iflag, PARMRK)) {
228 parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
229 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
230 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
231 goto endcase;
232 } else
233 c = 0;
234 }
235 }
236 /*
237 * In tandem mode, check high water mark.
238 */
239 if (ISSET(iflag, IXOFF))
240 ttyblock(tp);
241 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
242 CLR(c, 0x80);
243 if (!ISSET(lflag, EXTPROC)) {
244 /*
245 * Check for literal nexting very first
246 */
247 if (ISSET(tp->t_state, TS_LNCH)) {
248 SET(c, TTY_QUOTE);
249 CLR(tp->t_state, TS_LNCH);
250 }
251 /*
252 * Scan for special characters. This code
253 * is really just a big case statement with
254 * non-constant cases. The bottom of the
255 * case statement is labeled ``endcase'', so goto
256 * it after a case match, or similar.
257 */
258
259 /*
260 * Control chars which aren't controlled
261 * by ICANON, ISIG, or IXON.
262 */
263 if (ISSET(lflag, IEXTEN)) {
264 if (CCEQ(cc[VLNEXT], c)) {
265 if (ISSET(lflag, ECHO)) {
266 if (ISSET(lflag, ECHOE)) {
267 (void)ttyoutput('^', tp);
268 (void)ttyoutput('\b', tp);
269 } else
270 ttyecho(c, tp);
271 }
272 SET(tp->t_state, TS_LNCH);
273 goto endcase;
274 }
275 if (CCEQ(cc[VDISCARD], c)) {
276 if (ISSET(lflag, FLUSHO))
277 CLR(tp->t_lflag, FLUSHO);
278 else {
279 ttyflush(tp, FWRITE);
280 ttyecho(c, tp);
281 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
282 ttyretype(tp);
283 SET(tp->t_lflag, FLUSHO);
284 }
285 goto startoutput;
286 }
287 }
288 /*
289 * Signals.
290 */
291 if (ISSET(lflag, ISIG)) {
292 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
293 if (!ISSET(lflag, NOFLSH))
294 ttyflush(tp, FREAD | FWRITE);
295 ttyecho(c, tp);
296 pgsignal(tp->t_pgrp,
297 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
298 goto endcase;
299 }
300 if (CCEQ(cc[VSUSP], c)) {
301 if (!ISSET(lflag, NOFLSH))
302 ttyflush(tp, FREAD);
303 ttyecho(c, tp);
304 pgsignal(tp->t_pgrp, SIGTSTP, 1);
305 goto endcase;
306 }
307 }
308 /*
309 * Handle start/stop characters.
310 */
311 if (ISSET(iflag, IXON)) {
312 if (CCEQ(cc[VSTOP], c)) {
313 if (!ISSET(tp->t_state, TS_TTSTOP)) {
314 SET(tp->t_state, TS_TTSTOP);
315 #ifdef sun4c /* XXX */
316 (*tp->t_stop)(tp, 0);
317 #else
318 (*cdevsw[major(tp->t_dev)].d_stop)(tp,
319 0);
320 #endif
321 return (0);
322 }
323 if (!CCEQ(cc[VSTART], c))
324 return (0);
325 /*
326 * if VSTART == VSTOP then toggle
327 */
328 goto endcase;
329 }
330 if (CCEQ(cc[VSTART], c))
331 goto restartoutput;
332 }
333 /*
334 * IGNCR, ICRNL, & INLCR
335 */
336 if (c == '\r') {
337 if (ISSET(iflag, IGNCR))
338 goto endcase;
339 else if (ISSET(iflag, ICRNL))
340 c = '\n';
341 } else if (c == '\n' && ISSET(iflag, INLCR))
342 c = '\r';
343 }
344 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
345 /*
346 * From here on down canonical mode character
347 * processing takes place.
348 */
349 /*
350 * erase (^H / ^?)
351 */
352 if (CCEQ(cc[VERASE], c)) {
353 if (tp->t_rawq.c_cc)
354 ttyrub(unputc(&tp->t_rawq), tp);
355 goto endcase;
356 }
357 /*
358 * kill (^U)
359 */
360 if (CCEQ(cc[VKILL], c)) {
361 if (ISSET(lflag, ECHOKE) &&
362 tp->t_rawq.c_cc == tp->t_rocount &&
363 !ISSET(lflag, ECHOPRT))
364 while (tp->t_rawq.c_cc)
365 ttyrub(unputc(&tp->t_rawq), tp);
366 else {
367 ttyecho(c, tp);
368 if (ISSET(lflag, ECHOK) ||
369 ISSET(lflag, ECHOKE))
370 ttyecho('\n', tp);
371 FLUSHQ(&tp->t_rawq);
372 tp->t_rocount = 0;
373 }
374 CLR(tp->t_state, TS_LOCAL);
375 goto endcase;
376 }
377 /*
378 * word erase (^W)
379 */
380 if (CCEQ(cc[VWERASE], c)) {
381 int alt = ISSET(lflag, ALTWERASE);
382 int ctype;
383
384 /*
385 * erase whitespace
386 */
387 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
388 ttyrub(c, tp);
389 if (c == -1)
390 goto endcase;
391 /*
392 * erase last char of word and remember the
393 * next chars type (for ALTWERASE)
394 */
395 ttyrub(c, tp);
396 c = unputc(&tp->t_rawq);
397 if (c == -1)
398 goto endcase;
399 if (c == ' ' || c == '\t') {
400 (void)putc(c, &tp->t_rawq);
401 goto endcase;
402 }
403 ctype = ISALPHA(c);
404 /*
405 * erase rest of word
406 */
407 do {
408 ttyrub(c, tp);
409 c = unputc(&tp->t_rawq);
410 if (c == -1)
411 goto endcase;
412 } while (c != ' ' && c != '\t' &&
413 (alt == 0 || ISALPHA(c) == ctype));
414 (void)putc(c, &tp->t_rawq);
415 goto endcase;
416 }
417 /*
418 * reprint line (^R)
419 */
420 if (CCEQ(cc[VREPRINT], c)) {
421 ttyretype(tp);
422 goto endcase;
423 }
424 /*
425 * ^T - kernel info and generate SIGINFO
426 */
427 if (CCEQ(cc[VSTATUS], c)) {
428 if (ISSET(lflag, ISIG))
429 pgsignal(tp->t_pgrp, SIGINFO, 1);
430 if (!ISSET(lflag, NOKERNINFO))
431 ttyinfo(tp);
432 goto endcase;
433 }
434 }
435 /*
436 * Check for input buffer overflow
437 */
438 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
439 if (ISSET(iflag, IMAXBEL)) {
440 if (tp->t_outq.c_cc < tp->t_hiwat)
441 (void)ttyoutput(CTRL('g'), tp);
442 } else
443 ttyflush(tp, FREAD | FWRITE);
444 goto endcase;
445 }
446 /*
447 * Put data char in q for user and
448 * wakeup on seeing a line delimiter.
449 */
450 if (putc(c, &tp->t_rawq) >= 0) {
451 if (!ISSET(lflag, ICANON)) {
452 ttwakeup(tp);
453 ttyecho(c, tp);
454 goto endcase;
455 }
456 if (TTBREAKC(c)) {
457 tp->t_rocount = 0;
458 catq(&tp->t_rawq, &tp->t_canq);
459 ttwakeup(tp);
460 } else if (tp->t_rocount++ == 0)
461 tp->t_rocol = tp->t_column;
462 if (ISSET(tp->t_state, TS_ERASE)) {
463 /*
464 * end of prterase \.../
465 */
466 CLR(tp->t_state, TS_ERASE);
467 (void)ttyoutput('/', tp);
468 }
469 i = tp->t_column;
470 ttyecho(c, tp);
471 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
472 /*
473 * Place the cursor over the '^' of the ^D.
474 */
475 i = min(2, tp->t_column - i);
476 while (i > 0) {
477 (void)ttyoutput('\b', tp);
478 i--;
479 }
480 }
481 }
482 endcase:
483 /*
484 * IXANY means allow any character to restart output.
485 */
486 if (ISSET(tp->t_state, TS_TTSTOP) &&
487 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
488 return (0);
489 restartoutput:
490 CLR(tp->t_lflag, FLUSHO);
491 CLR(tp->t_state, TS_TTSTOP);
492 startoutput:
493 return (ttstart(tp));
494 }
495
496 /*
497 * Output a single character on a tty, doing output processing
498 * as needed (expanding tabs, newline processing, etc.).
499 * Returns < 0 if succeeds, otherwise returns char to resend.
500 * Must be recursive.
501 */
502 int
ttyoutput(c,tp)503 ttyoutput(c, tp)
504 register int c;
505 register struct tty *tp;
506 {
507 register long oflag;
508 register int notout, col, s;
509
510 oflag = tp->t_oflag;
511 if (!ISSET(oflag, OPOST)) {
512 if (ISSET(tp->t_lflag, FLUSHO))
513 return (-1);
514 if (putc(c, &tp->t_outq))
515 return (c);
516 tk_nout++;
517 tp->t_outcc++;
518 return (-1);
519 }
520 /*
521 * Do tab expansion if OXTABS is set. Special case if we external
522 * processing, we don't do the tab expansion because we'll probably
523 * get it wrong. If tab expansion needs to be done, let it happen
524 * externally.
525 */
526 CLR(c, ~TTY_CHARMASK);
527 if (c == '\t' &&
528 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
529 c = 8 - (tp->t_column & 7);
530 if (ISSET(tp->t_lflag, FLUSHO)) {
531 notout = 0;
532 } else {
533 s = spltty(); /* Don't interrupt tabs. */
534 notout = b_to_q(" ", c, &tp->t_outq);
535 c -= notout;
536 tk_nout += c;
537 tp->t_outcc += c;
538 splx(s);
539 }
540 tp->t_column += c;
541 return (notout ? '\t' : -1);
542 }
543 if (c == CEOT && ISSET(oflag, ONOEOT))
544 return (-1);
545
546 /*
547 * Newline translation: if ONLCR is set,
548 * translate newline into "\r\n".
549 */
550 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
551 tk_nout++;
552 tp->t_outcc++;
553 if (putc('\r', &tp->t_outq))
554 return (c);
555 }
556 tk_nout++;
557 tp->t_outcc++;
558 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
559 return (c);
560
561 col = tp->t_column;
562 switch (CCLASS(c)) {
563 case BACKSPACE:
564 if (col > 0)
565 --col;
566 break;
567 case CONTROL:
568 break;
569 case NEWLINE:
570 case RETURN:
571 col = 0;
572 break;
573 case ORDINARY:
574 ++col;
575 break;
576 case TAB:
577 col = (col + 8) & ~7;
578 break;
579 }
580 tp->t_column = col;
581 return (-1);
582 }
583
584 /*
585 * Ioctls for all tty devices. Called after line-discipline specific ioctl
586 * has been called to do discipline-specific functions and/or reject any
587 * of these ioctl commands.
588 */
589 /* ARGSUSED */
590 int
ttioctl(tp,cmd,data,flag)591 ttioctl(tp, cmd, data, flag)
592 register struct tty *tp;
593 u_long cmd;
594 void *data;
595 int flag;
596 {
597 extern struct tty *constty; /* Temporary virtual console. */
598 extern int nlinesw;
599 register struct proc *p;
600 int s, error;
601
602 p = curproc; /* XXX */
603
604 /* If the ioctl involves modification, hang if in the background. */
605 switch (cmd) {
606 case TIOCFLUSH:
607 case TIOCSETA:
608 case TIOCSETD:
609 case TIOCSETAF:
610 case TIOCSETAW:
611 #ifdef notdef
612 case TIOCSPGRP:
613 #endif
614 case TIOCSTI:
615 case TIOCSWINSZ:
616 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
617 case TIOCLBIC:
618 case TIOCLBIS:
619 case TIOCLSET:
620 case TIOCSETC:
621 case OTIOCSETD:
622 case TIOCSETN:
623 case TIOCSETP:
624 case TIOCSLTC:
625 #endif
626 while (isbackground(curproc, tp) &&
627 p->p_pgrp->pg_jobc && (p->p_flag & P_PPWAIT) == 0 &&
628 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
629 (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
630 pgsignal(p->p_pgrp, SIGTTOU, 1);
631 if (error = ttysleep(tp,
632 &lbolt, TTOPRI | PCATCH, ttybg, 0))
633 return (error);
634 }
635 break;
636 }
637
638 switch (cmd) { /* Process the ioctl. */
639 case FIOASYNC: /* set/clear async i/o */
640 s = spltty();
641 if (*(int *)data)
642 SET(tp->t_state, TS_ASYNC);
643 else
644 CLR(tp->t_state, TS_ASYNC);
645 splx(s);
646 break;
647 case FIONBIO: /* set/clear non-blocking i/o */
648 break; /* XXX: delete. */
649 case FIONREAD: /* get # bytes to read */
650 *(int *)data = ttnread(tp);
651 break;
652 case TIOCEXCL: /* set exclusive use of tty */
653 s = spltty();
654 SET(tp->t_state, TS_XCLUDE);
655 splx(s);
656 break;
657 case TIOCFLUSH: { /* flush buffers */
658 register int flags = *(int *)data;
659
660 if (flags == 0)
661 flags = FREAD | FWRITE;
662 else
663 flags &= FREAD | FWRITE;
664 ttyflush(tp, flags);
665 break;
666 }
667 case TIOCCONS: /* become virtual console */
668 if (*(int *)data) {
669 if (constty && constty != tp &&
670 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
671 (TS_CARR_ON | TS_ISOPEN))
672 return (EBUSY);
673 #ifndef UCONSOLE
674 if (error = suser(p->p_ucred, &p->p_acflag))
675 return (error);
676 #endif
677 constty = tp;
678 } else if (tp == constty)
679 constty = NULL;
680 break;
681 case TIOCDRAIN: /* wait till output drained */
682 if (error = ttywait(tp))
683 return (error);
684 break;
685 case TIOCGETA: { /* get termios struct */
686 struct termios *t = (struct termios *)data;
687
688 bcopy(&tp->t_termios, t, sizeof(struct termios));
689 break;
690 }
691 case TIOCGETD: /* get line discipline */
692 *(int *)data = tp->t_line;
693 break;
694 case TIOCGWINSZ: /* get window size */
695 *(struct winsize *)data = tp->t_winsize;
696 break;
697 case TIOCGPGRP: /* get pgrp of tty */
698 if (!isctty(p, tp))
699 return (ENOTTY);
700 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
701 break;
702 #ifdef TIOCHPCL
703 case TIOCHPCL: /* hang up on last close */
704 s = spltty();
705 SET(tp->t_cflag, HUPCL);
706 splx(s);
707 break;
708 #endif
709 case TIOCNXCL: /* reset exclusive use of tty */
710 s = spltty();
711 CLR(tp->t_state, TS_XCLUDE);
712 splx(s);
713 break;
714 case TIOCOUTQ: /* output queue size */
715 *(int *)data = tp->t_outq.c_cc;
716 break;
717 case TIOCSETA: /* set termios struct */
718 case TIOCSETAW: /* drain output, set */
719 case TIOCSETAF: { /* drn out, fls in, set */
720 register struct termios *t = (struct termios *)data;
721
722 s = spltty();
723 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
724 if (error = ttywait(tp)) {
725 splx(s);
726 return (error);
727 }
728 if (cmd == TIOCSETAF)
729 ttyflush(tp, FREAD);
730 }
731 if (!ISSET(t->c_cflag, CIGNORE)) {
732 /*
733 * Set device hardware.
734 */
735 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
736 splx(s);
737 return (error);
738 } else {
739 if (!ISSET(tp->t_state, TS_CARR_ON) &&
740 ISSET(tp->t_cflag, CLOCAL) &&
741 !ISSET(t->c_cflag, CLOCAL)) {
742 CLR(tp->t_state, TS_ISOPEN);
743 SET(tp->t_state, TS_WOPEN);
744 ttwakeup(tp);
745 }
746 tp->t_cflag = t->c_cflag;
747 tp->t_ispeed = t->c_ispeed;
748 tp->t_ospeed = t->c_ospeed;
749 }
750 ttsetwater(tp);
751 }
752 if (cmd != TIOCSETAF) {
753 if (ISSET(t->c_lflag, ICANON) !=
754 ISSET(tp->t_lflag, ICANON))
755 if (ISSET(t->c_lflag, ICANON)) {
756 SET(tp->t_lflag, PENDIN);
757 ttwakeup(tp);
758 } else {
759 struct clist tq;
760
761 catq(&tp->t_rawq, &tp->t_canq);
762 tq = tp->t_rawq;
763 tp->t_rawq = tp->t_canq;
764 tp->t_canq = tq;
765 CLR(tp->t_lflag, PENDIN);
766 }
767 }
768 tp->t_iflag = t->c_iflag;
769 tp->t_oflag = t->c_oflag;
770 /*
771 * Make the EXTPROC bit read only.
772 */
773 if (ISSET(tp->t_lflag, EXTPROC))
774 SET(t->c_lflag, EXTPROC);
775 else
776 CLR(t->c_lflag, EXTPROC);
777 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
778 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
779 splx(s);
780 break;
781 }
782 case TIOCSETD: { /* set line discipline */
783 register int t = *(int *)data;
784 dev_t device = tp->t_dev;
785
786 if ((u_int)t >= nlinesw)
787 return (ENXIO);
788 if (t != tp->t_line) {
789 s = spltty();
790 (*linesw[tp->t_line].l_close)(tp, flag);
791 error = (*linesw[t].l_open)(device, tp);
792 if (error) {
793 (void)(*linesw[tp->t_line].l_open)(device, tp);
794 splx(s);
795 return (error);
796 }
797 tp->t_line = t;
798 splx(s);
799 }
800 break;
801 }
802 case TIOCSTART: /* start output, like ^Q */
803 s = spltty();
804 if (ISSET(tp->t_state, TS_TTSTOP) ||
805 ISSET(tp->t_lflag, FLUSHO)) {
806 CLR(tp->t_lflag, FLUSHO);
807 CLR(tp->t_state, TS_TTSTOP);
808 ttstart(tp);
809 }
810 splx(s);
811 break;
812 case TIOCSTI: /* simulate terminal input */
813 if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
814 return (EPERM);
815 if (p->p_ucred->cr_uid && !isctty(p, tp))
816 return (EACCES);
817 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
818 break;
819 case TIOCSTOP: /* stop output, like ^S */
820 s = spltty();
821 if (!ISSET(tp->t_state, TS_TTSTOP)) {
822 SET(tp->t_state, TS_TTSTOP);
823 #ifdef sun4c /* XXX */
824 (*tp->t_stop)(tp, 0);
825 #else
826 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
827 #endif
828 }
829 splx(s);
830 break;
831 case TIOCSCTTY: /* become controlling tty */
832 /* Session ctty vnode pointer set in vnode layer. */
833 if (!SESS_LEADER(p) ||
834 (p->p_session->s_ttyvp || tp->t_session) &&
835 (tp->t_session != p->p_session))
836 return (EPERM);
837 tp->t_session = p->p_session;
838 tp->t_pgrp = p->p_pgrp;
839 p->p_session->s_ttyp = tp;
840 p->p_flag |= P_CONTROLT;
841 break;
842 case TIOCSPGRP: { /* set pgrp of tty */
843 register struct pgrp *pgrp = pgfind(*(int *)data);
844
845 if (!isctty(p, tp))
846 return (ENOTTY);
847 else if (pgrp == NULL || pgrp->pg_session != p->p_session)
848 return (EPERM);
849 tp->t_pgrp = pgrp;
850 break;
851 }
852 case TIOCSWINSZ: /* set window size */
853 if (bcmp((caddr_t)&tp->t_winsize, data,
854 sizeof (struct winsize))) {
855 tp->t_winsize = *(struct winsize *)data;
856 pgsignal(tp->t_pgrp, SIGWINCH, 1);
857 }
858 break;
859 default:
860 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
861 return (ttcompat(tp, cmd, data, flag));
862 #else
863 return (-1);
864 #endif
865 }
866 return (0);
867 }
868
869 int
ttselect(device,rw,p)870 ttselect(device, rw, p)
871 dev_t device;
872 int rw;
873 struct proc *p;
874 {
875 register struct tty *tp;
876 int nread, s;
877
878 tp = &cdevsw[major(device)].d_ttys[minor(device)];
879
880 s = spltty();
881 switch (rw) {
882 case FREAD:
883 nread = ttnread(tp);
884 if (nread > 0 || !ISSET(tp->t_cflag, CLOCAL) &&
885 !ISSET(tp->t_state, TS_CARR_ON))
886 goto win;
887 selrecord(p, &tp->t_rsel);
888 break;
889 case FWRITE:
890 if (tp->t_outq.c_cc <= tp->t_lowat) {
891 win: splx(s);
892 return (1);
893 }
894 selrecord(p, &tp->t_wsel);
895 break;
896 }
897 splx(s);
898 return (0);
899 }
900
901 static int
ttnread(tp)902 ttnread(tp)
903 struct tty *tp;
904 {
905 int nread;
906
907 if (ISSET(tp->t_lflag, PENDIN))
908 ttypend(tp);
909 nread = tp->t_canq.c_cc;
910 if (!ISSET(tp->t_lflag, ICANON))
911 nread += tp->t_rawq.c_cc;
912 return (nread);
913 }
914
915 /*
916 * Wait for output to drain.
917 */
918 int
ttywait(tp)919 ttywait(tp)
920 register struct tty *tp;
921 {
922 int error, s;
923
924 error = 0;
925 s = spltty();
926 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
927 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
928 && tp->t_oproc) {
929 (*tp->t_oproc)(tp);
930 SET(tp->t_state, TS_ASLEEP);
931 if (error = ttysleep(tp,
932 &tp->t_outq, TTOPRI | PCATCH, ttyout, 0))
933 break;
934 }
935 splx(s);
936 return (error);
937 }
938
939 /*
940 * Flush if successfully wait.
941 */
942 int
ttywflush(tp)943 ttywflush(tp)
944 struct tty *tp;
945 {
946 int error;
947
948 if ((error = ttywait(tp)) == 0)
949 ttyflush(tp, FREAD);
950 return (error);
951 }
952
953 /*
954 * Flush tty read and/or write queues, notifying anyone waiting.
955 */
956 void
ttyflush(tp,rw)957 ttyflush(tp, rw)
958 register struct tty *tp;
959 int rw;
960 {
961 register int s;
962
963 s = spltty();
964 if (rw & FREAD) {
965 FLUSHQ(&tp->t_canq);
966 FLUSHQ(&tp->t_rawq);
967 tp->t_rocount = 0;
968 tp->t_rocol = 0;
969 CLR(tp->t_state, TS_LOCAL);
970 ttwakeup(tp);
971 }
972 if (rw & FWRITE) {
973 CLR(tp->t_state, TS_TTSTOP);
974 #ifdef sun4c /* XXX */
975 (*tp->t_stop)(tp, rw);
976 #else
977 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
978 #endif
979 FLUSHQ(&tp->t_outq);
980 wakeup((caddr_t)&tp->t_outq);
981 selwakeup(&tp->t_wsel);
982 }
983 splx(s);
984 }
985
986 /*
987 * Copy in the default termios characters.
988 */
989 void
ttychars(tp)990 ttychars(tp)
991 struct tty *tp;
992 {
993
994 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
995 }
996
997 /*
998 * Send stop character on input overflow.
999 */
1000 static void
ttyblock(tp)1001 ttyblock(tp)
1002 register struct tty *tp;
1003 {
1004 register int total;
1005
1006 total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1007 if (tp->t_rawq.c_cc > TTYHOG) {
1008 ttyflush(tp, FREAD | FWRITE);
1009 CLR(tp->t_state, TS_TBLOCK);
1010 }
1011 /*
1012 * Block further input iff: current input > threshold
1013 * AND input is available to user program.
1014 */
1015 if (total >= TTYHOG / 2 &&
1016 !ISSET(tp->t_state, TS_TBLOCK) &&
1017 !ISSET(tp->t_lflag, ICANON) || tp->t_canq.c_cc > 0 &&
1018 tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
1019 if (putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1020 SET(tp->t_state, TS_TBLOCK);
1021 ttstart(tp);
1022 }
1023 }
1024 }
1025
1026 void
ttrstrt(tp_arg)1027 ttrstrt(tp_arg)
1028 void *tp_arg;
1029 {
1030 struct tty *tp;
1031 int s;
1032
1033 #ifdef DIAGNOSTIC
1034 if (tp_arg == NULL)
1035 panic("ttrstrt");
1036 #endif
1037 tp = tp_arg;
1038 s = spltty();
1039
1040 CLR(tp->t_state, TS_TIMEOUT);
1041 ttstart(tp);
1042
1043 splx(s);
1044 }
1045
1046 int
ttstart(tp)1047 ttstart(tp)
1048 struct tty *tp;
1049 {
1050
1051 if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */
1052 (*tp->t_oproc)(tp);
1053 return (0);
1054 }
1055
1056 /*
1057 * "close" a line discipline
1058 */
1059 int
ttylclose(tp,flag)1060 ttylclose(tp, flag)
1061 struct tty *tp;
1062 int flag;
1063 {
1064
1065 if (flag & IO_NDELAY)
1066 ttyflush(tp, FREAD | FWRITE);
1067 else
1068 ttywflush(tp);
1069 return (0);
1070 }
1071
1072 /*
1073 * Handle modem control transition on a tty.
1074 * Flag indicates new state of carrier.
1075 * Returns 0 if the line should be turned off, otherwise 1.
1076 */
1077 int
ttymodem(tp,flag)1078 ttymodem(tp, flag)
1079 register struct tty *tp;
1080 int flag;
1081 {
1082
1083 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1084 /*
1085 * MDMBUF: do flow control according to carrier flag
1086 */
1087 if (flag) {
1088 CLR(tp->t_state, TS_TTSTOP);
1089 ttstart(tp);
1090 } else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1091 SET(tp->t_state, TS_TTSTOP);
1092 #ifdef sun4c /* XXX */
1093 (*tp->t_stop)(tp, 0);
1094 #else
1095 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1096 #endif
1097 }
1098 } else if (flag == 0) {
1099 /*
1100 * Lost carrier.
1101 */
1102 CLR(tp->t_state, TS_CARR_ON);
1103 if (ISSET(tp->t_state, TS_ISOPEN) &&
1104 !ISSET(tp->t_cflag, CLOCAL)) {
1105 if (tp->t_session && tp->t_session->s_leader)
1106 psignal(tp->t_session->s_leader, SIGHUP);
1107 ttyflush(tp, FREAD | FWRITE);
1108 return (0);
1109 }
1110 } else {
1111 /*
1112 * Carrier now on.
1113 */
1114 SET(tp->t_state, TS_CARR_ON);
1115 ttwakeup(tp);
1116 }
1117 return (1);
1118 }
1119
1120 /*
1121 * Default modem control routine (for other line disciplines).
1122 * Return argument flag, to turn off device on carrier drop.
1123 */
1124 int
nullmodem(tp,flag)1125 nullmodem(tp, flag)
1126 register struct tty *tp;
1127 int flag;
1128 {
1129
1130 if (flag)
1131 SET(tp->t_state, TS_CARR_ON);
1132 else {
1133 CLR(tp->t_state, TS_CARR_ON);
1134 if (!ISSET(tp->t_cflag, CLOCAL)) {
1135 if (tp->t_session && tp->t_session->s_leader)
1136 psignal(tp->t_session->s_leader, SIGHUP);
1137 return (0);
1138 }
1139 }
1140 return (1);
1141 }
1142
1143 /*
1144 * Reinput pending characters after state switch
1145 * call at spltty().
1146 */
1147 void
ttypend(tp)1148 ttypend(tp)
1149 register struct tty *tp;
1150 {
1151 struct clist tq;
1152 register c;
1153
1154 CLR(tp->t_lflag, PENDIN);
1155 SET(tp->t_state, TS_TYPEN);
1156 tq = tp->t_rawq;
1157 tp->t_rawq.c_cc = 0;
1158 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1159 while ((c = getc(&tq)) >= 0)
1160 ttyinput(c, tp);
1161 CLR(tp->t_state, TS_TYPEN);
1162 }
1163
1164 /*
1165 * Process a read call on a tty device.
1166 */
1167 int
ttread(tp,uio,flag)1168 ttread(tp, uio, flag)
1169 register struct tty *tp;
1170 struct uio *uio;
1171 int flag;
1172 {
1173 register struct clist *qp;
1174 register int c;
1175 register long lflag;
1176 register u_char *cc = tp->t_cc;
1177 register struct proc *p = curproc;
1178 int s, first, error = 0;
1179
1180 loop: lflag = tp->t_lflag;
1181 s = spltty();
1182 /*
1183 * take pending input first
1184 */
1185 if (ISSET(lflag, PENDIN))
1186 ttypend(tp);
1187 splx(s);
1188
1189 /*
1190 * Hang process if it's in the background.
1191 */
1192 if (isbackground(p, tp)) {
1193 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1194 (p->p_sigmask & sigmask(SIGTTIN)) ||
1195 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0)
1196 return (EIO);
1197 pgsignal(p->p_pgrp, SIGTTIN, 1);
1198 if (error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0))
1199 return (error);
1200 goto loop;
1201 }
1202
1203 /*
1204 * If canonical, use the canonical queue,
1205 * else use the raw queue.
1206 *
1207 * (should get rid of clists...)
1208 */
1209 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1210
1211 /*
1212 * If there is no input, sleep on rawq
1213 * awaiting hardware receipt and notification.
1214 * If we have data, we don't need to check for carrier.
1215 */
1216 s = spltty();
1217 if (qp->c_cc <= 0) {
1218 int carrier;
1219
1220 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1221 ISSET(tp->t_cflag, CLOCAL);
1222 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1223 splx(s);
1224 return (0); /* EOF */
1225 }
1226 if (flag & IO_NDELAY) {
1227 splx(s);
1228 return (EWOULDBLOCK);
1229 }
1230 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1231 carrier ? ttyin : ttopen, 0);
1232 splx(s);
1233 if (error)
1234 return (error);
1235 goto loop;
1236 }
1237 splx(s);
1238
1239 /*
1240 * Input present, check for input mapping and processing.
1241 */
1242 first = 1;
1243 while ((c = getc(qp)) >= 0) {
1244 /*
1245 * delayed suspend (^Y)
1246 */
1247 if (CCEQ(cc[VDSUSP], c) && ISSET(lflag, ISIG)) {
1248 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1249 if (first) {
1250 if (error = ttysleep(tp,
1251 &lbolt, TTIPRI | PCATCH, ttybg, 0))
1252 break;
1253 goto loop;
1254 }
1255 break;
1256 }
1257 /*
1258 * Interpret EOF only in canonical mode.
1259 */
1260 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1261 break;
1262 /*
1263 * Give user character.
1264 */
1265 error = ureadc(c, uio);
1266 if (error)
1267 break;
1268 if (uio->uio_resid == 0)
1269 break;
1270 /*
1271 * In canonical mode check for a "break character"
1272 * marking the end of a "line of input".
1273 */
1274 if (ISSET(lflag, ICANON) && TTBREAKC(c))
1275 break;
1276 first = 0;
1277 }
1278 /*
1279 * Look to unblock output now that (presumably)
1280 * the input queue has gone down.
1281 */
1282 s = spltty();
1283 if (ISSET(tp->t_state, TS_TBLOCK) && tp->t_rawq.c_cc < TTYHOG/5) {
1284 if (cc[VSTART] != _POSIX_VDISABLE &&
1285 putc(cc[VSTART], &tp->t_outq) == 0) {
1286 CLR(tp->t_state, TS_TBLOCK);
1287 ttstart(tp);
1288 }
1289 }
1290 splx(s);
1291 return (error);
1292 }
1293
1294 /*
1295 * Check the output queue on tp for space for a kernel message (from uprintf
1296 * or tprintf). Allow some space over the normal hiwater mark so we don't
1297 * lose messages due to normal flow control, but don't let the tty run amok.
1298 * Sleeps here are not interruptible, but we return prematurely if new signals
1299 * arrive.
1300 */
1301 int
ttycheckoutq(tp,wait)1302 ttycheckoutq(tp, wait)
1303 register struct tty *tp;
1304 int wait;
1305 {
1306 int hiwat, s, oldsig;
1307
1308 hiwat = tp->t_hiwat;
1309 s = spltty();
1310 oldsig = wait ? curproc->p_siglist : 0;
1311 if (tp->t_outq.c_cc > hiwat + 200)
1312 while (tp->t_outq.c_cc > hiwat) {
1313 ttstart(tp);
1314 if (wait == 0 || curproc->p_siglist != oldsig) {
1315 splx(s);
1316 return (0);
1317 }
1318 timeout((void (*)__P((void *)))wakeup,
1319 (void *)&tp->t_outq, hz);
1320 SET(tp->t_state, TS_ASLEEP);
1321 sleep((caddr_t)&tp->t_outq, PZERO - 1);
1322 }
1323 splx(s);
1324 return (1);
1325 }
1326
1327 /*
1328 * Process a write call on a tty device.
1329 */
1330 int
ttwrite(tp,uio,flag)1331 ttwrite(tp, uio, flag)
1332 register struct tty *tp;
1333 register struct uio *uio;
1334 int flag;
1335 {
1336 register char *cp;
1337 register int cc, ce;
1338 register struct proc *p;
1339 int i, hiwat, cnt, error, s;
1340 char obuf[OBUFSIZ];
1341
1342 hiwat = tp->t_hiwat;
1343 cnt = uio->uio_resid;
1344 error = 0;
1345 cc = 0;
1346 loop:
1347 s = spltty();
1348 if (!ISSET(tp->t_state, TS_CARR_ON) &&
1349 !ISSET(tp->t_cflag, CLOCAL)) {
1350 if (ISSET(tp->t_state, TS_ISOPEN)) {
1351 splx(s);
1352 return (EIO);
1353 } else if (flag & IO_NDELAY) {
1354 splx(s);
1355 error = EWOULDBLOCK;
1356 goto out;
1357 } else {
1358 /* Sleep awaiting carrier. */
1359 error = ttysleep(tp,
1360 &tp->t_rawq, TTIPRI | PCATCH,ttopen, 0);
1361 splx(s);
1362 if (error)
1363 goto out;
1364 goto loop;
1365 }
1366 }
1367 splx(s);
1368 /*
1369 * Hang the process if it's in the background.
1370 */
1371 p = curproc;
1372 if (isbackground(p, tp) &&
1373 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
1374 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
1375 (p->p_sigmask & sigmask(SIGTTOU)) == 0 &&
1376 p->p_pgrp->pg_jobc) {
1377 pgsignal(p->p_pgrp, SIGTTOU, 1);
1378 if (error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0))
1379 goto out;
1380 goto loop;
1381 }
1382 /*
1383 * Process the user's data in at most OBUFSIZ chunks. Perform any
1384 * output translation. Keep track of high water mark, sleep on
1385 * overflow awaiting device aid in acquiring new space.
1386 */
1387 while (uio->uio_resid > 0 || cc > 0) {
1388 if (ISSET(tp->t_lflag, FLUSHO)) {
1389 uio->uio_resid = 0;
1390 return (0);
1391 }
1392 if (tp->t_outq.c_cc > hiwat)
1393 goto ovhiwat;
1394 /*
1395 * Grab a hunk of data from the user, unless we have some
1396 * leftover from last time.
1397 */
1398 if (cc == 0) {
1399 cc = min(uio->uio_resid, OBUFSIZ);
1400 cp = obuf;
1401 error = uiomove(cp, cc, uio);
1402 if (error) {
1403 cc = 0;
1404 break;
1405 }
1406 }
1407 /*
1408 * If nothing fancy need be done, grab those characters we
1409 * can handle without any of ttyoutput's processing and
1410 * just transfer them to the output q. For those chars
1411 * which require special processing (as indicated by the
1412 * bits in char_type), call ttyoutput. After processing
1413 * a hunk of data, look for FLUSHO so ^O's will take effect
1414 * immediately.
1415 */
1416 while (cc > 0) {
1417 if (!ISSET(tp->t_oflag, OPOST))
1418 ce = cc;
1419 else {
1420 ce = cc - scanc((u_int)cc, (u_char *)cp,
1421 (u_char *)char_type, CCLASSMASK);
1422 /*
1423 * If ce is zero, then we're processing
1424 * a special character through ttyoutput.
1425 */
1426 if (ce == 0) {
1427 tp->t_rocount = 0;
1428 if (ttyoutput(*cp, tp) >= 0) {
1429 /* No Clists, wait a bit. */
1430 ttstart(tp);
1431 if (error = ttysleep(tp, &lbolt,
1432 TTOPRI | PCATCH, ttybuf, 0))
1433 break;
1434 goto loop;
1435 }
1436 cp++;
1437 cc--;
1438 if (ISSET(tp->t_lflag, FLUSHO) ||
1439 tp->t_outq.c_cc > hiwat)
1440 goto ovhiwat;
1441 continue;
1442 }
1443 }
1444 /*
1445 * A bunch of normal characters have been found.
1446 * Transfer them en masse to the output queue and
1447 * continue processing at the top of the loop.
1448 * If there are any further characters in this
1449 * <= OBUFSIZ chunk, the first should be a character
1450 * requiring special handling by ttyoutput.
1451 */
1452 tp->t_rocount = 0;
1453 i = b_to_q(cp, ce, &tp->t_outq);
1454 ce -= i;
1455 tp->t_column += ce;
1456 cp += ce, cc -= ce, tk_nout += ce;
1457 tp->t_outcc += ce;
1458 if (i > 0) {
1459 /* No Clists, wait a bit. */
1460 ttstart(tp);
1461 if (error = ttysleep(tp,
1462 &lbolt, TTOPRI | PCATCH, ttybuf, 0))
1463 break;
1464 goto loop;
1465 }
1466 if (ISSET(tp->t_lflag, FLUSHO) ||
1467 tp->t_outq.c_cc > hiwat)
1468 break;
1469 }
1470 ttstart(tp);
1471 }
1472 out:
1473 /*
1474 * If cc is nonzero, we leave the uio structure inconsistent, as the
1475 * offset and iov pointers have moved forward, but it doesn't matter
1476 * (the call will either return short or restart with a new uio).
1477 */
1478 uio->uio_resid += cc;
1479 return (error);
1480
1481 ovhiwat:
1482 ttstart(tp);
1483 s = spltty();
1484 /*
1485 * This can only occur if FLUSHO is set in t_lflag,
1486 * or if ttstart/oproc is synchronous (or very fast).
1487 */
1488 if (tp->t_outq.c_cc <= hiwat) {
1489 splx(s);
1490 goto loop;
1491 }
1492 if (flag & IO_NDELAY) {
1493 splx(s);
1494 uio->uio_resid += cc;
1495 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1496 }
1497 SET(tp->t_state, TS_ASLEEP);
1498 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1499 splx(s);
1500 if (error)
1501 goto out;
1502 goto loop;
1503 }
1504
1505 /*
1506 * Rubout one character from the rawq of tp
1507 * as cleanly as possible.
1508 */
1509 void
ttyrub(c,tp)1510 ttyrub(c, tp)
1511 register int c;
1512 register struct tty *tp;
1513 {
1514 register char *cp;
1515 register int savecol;
1516 int tabc, s;
1517
1518 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1519 return;
1520 CLR(tp->t_lflag, FLUSHO);
1521 if (ISSET(tp->t_lflag, ECHOE)) {
1522 if (tp->t_rocount == 0) {
1523 /*
1524 * Screwed by ttwrite; retype
1525 */
1526 ttyretype(tp);
1527 return;
1528 }
1529 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1530 ttyrubo(tp, 2);
1531 else {
1532 CLR(c, ~TTY_CHARMASK);
1533 switch (CCLASS(c)) {
1534 case ORDINARY:
1535 ttyrubo(tp, 1);
1536 break;
1537 case BACKSPACE:
1538 case CONTROL:
1539 case NEWLINE:
1540 case RETURN:
1541 case VTAB:
1542 if (ISSET(tp->t_lflag, ECHOCTL))
1543 ttyrubo(tp, 2);
1544 break;
1545 case TAB:
1546 if (tp->t_rocount < tp->t_rawq.c_cc) {
1547 ttyretype(tp);
1548 return;
1549 }
1550 s = spltty();
1551 savecol = tp->t_column;
1552 SET(tp->t_state, TS_CNTTB);
1553 SET(tp->t_lflag, FLUSHO);
1554 tp->t_column = tp->t_rocol;
1555 cp = tp->t_rawq.c_cf;
1556 if (cp)
1557 tabc = *cp; /* XXX FIX NEXTC */
1558 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
1559 ttyecho(tabc, tp);
1560 CLR(tp->t_lflag, FLUSHO);
1561 CLR(tp->t_state, TS_CNTTB);
1562 splx(s);
1563
1564 /* savecol will now be length of the tab. */
1565 savecol -= tp->t_column;
1566 tp->t_column += savecol;
1567 if (savecol > 8)
1568 savecol = 8; /* overflow screw */
1569 while (--savecol >= 0)
1570 (void)ttyoutput('\b', tp);
1571 break;
1572 default: /* XXX */
1573 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
1574 (void)printf(PANICSTR, c, CCLASS(c));
1575 #ifdef notdef
1576 panic(PANICSTR, c, CCLASS(c));
1577 #endif
1578 }
1579 }
1580 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
1581 if (!ISSET(tp->t_state, TS_ERASE)) {
1582 SET(tp->t_state, TS_ERASE);
1583 (void)ttyoutput('\\', tp);
1584 }
1585 ttyecho(c, tp);
1586 } else
1587 ttyecho(tp->t_cc[VERASE], tp);
1588 --tp->t_rocount;
1589 }
1590
1591 /*
1592 * Back over cnt characters, erasing them.
1593 */
1594 static void
ttyrubo(tp,cnt)1595 ttyrubo(tp, cnt)
1596 register struct tty *tp;
1597 int cnt;
1598 {
1599
1600 while (cnt-- > 0) {
1601 (void)ttyoutput('\b', tp);
1602 (void)ttyoutput(' ', tp);
1603 (void)ttyoutput('\b', tp);
1604 }
1605 }
1606
1607 /*
1608 * ttyretype --
1609 * Reprint the rawq line. Note, it is assumed that c_cc has already
1610 * been checked.
1611 */
1612 void
ttyretype(tp)1613 ttyretype(tp)
1614 register struct tty *tp;
1615 {
1616 register char *cp;
1617 int s, c;
1618
1619 /* Echo the reprint character. */
1620 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
1621 ttyecho(tp->t_cc[VREPRINT], tp);
1622
1623 (void)ttyoutput('\n', tp);
1624
1625 /*
1626 * XXX
1627 * FIX: NEXTC IS BROKEN - DOESN'T CHECK QUOTE
1628 * BIT OF FIRST CHAR.
1629 */
1630 s = spltty();
1631 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
1632 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
1633 ttyecho(c, tp);
1634 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
1635 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
1636 ttyecho(c, tp);
1637 CLR(tp->t_state, TS_ERASE);
1638 splx(s);
1639
1640 tp->t_rocount = tp->t_rawq.c_cc;
1641 tp->t_rocol = 0;
1642 }
1643
1644 /*
1645 * Echo a typed character to the terminal.
1646 */
1647 static void
ttyecho(c,tp)1648 ttyecho(c, tp)
1649 register int c;
1650 register struct tty *tp;
1651 {
1652
1653 if (!ISSET(tp->t_state, TS_CNTTB))
1654 CLR(tp->t_lflag, FLUSHO);
1655 if ((!ISSET(tp->t_lflag, ECHO) &&
1656 (!ISSET(tp->t_lflag, ECHONL) || c == '\n')) ||
1657 ISSET(tp->t_lflag, EXTPROC))
1658 return;
1659 if (ISSET(tp->t_lflag, ECHOCTL) &&
1660 (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' ||
1661 ISSET(c, TTY_CHARMASK) == 0177)) {
1662 (void)ttyoutput('^', tp);
1663 CLR(c, ~TTY_CHARMASK);
1664 if (c == 0177)
1665 c = '?';
1666 else
1667 c += 'A' - 1;
1668 }
1669 (void)ttyoutput(c, tp);
1670 }
1671
1672 /*
1673 * Wake up any readers on a tty.
1674 */
1675 void
ttwakeup(tp)1676 ttwakeup(tp)
1677 register struct tty *tp;
1678 {
1679
1680 selwakeup(&tp->t_rsel);
1681 if (ISSET(tp->t_state, TS_ASYNC))
1682 pgsignal(tp->t_pgrp, SIGIO, 1);
1683 wakeup((caddr_t)&tp->t_rawq);
1684 }
1685
1686 /*
1687 * Look up a code for a specified speed in a conversion table;
1688 * used by drivers to map software speed values to hardware parameters.
1689 */
1690 int
ttspeedtab(speed,table)1691 ttspeedtab(speed, table)
1692 int speed;
1693 register struct speedtab *table;
1694 {
1695
1696 for ( ; table->sp_speed != -1; table++)
1697 if (table->sp_speed == speed)
1698 return (table->sp_code);
1699 return (-1);
1700 }
1701
1702 /*
1703 * Set tty hi and low water marks.
1704 *
1705 * Try to arrange the dynamics so there's about one second
1706 * from hi to low water.
1707 *
1708 */
1709 void
ttsetwater(tp)1710 ttsetwater(tp)
1711 struct tty *tp;
1712 {
1713 register int cps, x;
1714
1715 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
1716
1717 cps = tp->t_ospeed / 10;
1718 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
1719 x += cps;
1720 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
1721 tp->t_hiwat = roundup(x, CBSIZE);
1722 #undef CLAMP
1723 }
1724
1725 /*
1726 * Report on state of foreground process group.
1727 */
1728 void
ttyinfo(tp)1729 ttyinfo(tp)
1730 register struct tty *tp;
1731 {
1732 register struct proc *p, *pick;
1733 struct timeval utime, stime;
1734 int tmp;
1735
1736 if (ttycheckoutq(tp,0) == 0)
1737 return;
1738
1739 /* Print load average. */
1740 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
1741 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
1742
1743 if (tp->t_session == NULL)
1744 ttyprintf(tp, "not a controlling terminal\n");
1745 else if (tp->t_pgrp == NULL)
1746 ttyprintf(tp, "no foreground process group\n");
1747 else if ((p = tp->t_pgrp->pg_members.lh_first) == 0)
1748 ttyprintf(tp, "empty foreground process group\n");
1749 else {
1750 /* Pick interesting process. */
1751 for (pick = NULL; p != 0; p = p->p_pglist.le_next)
1752 if (proc_compare(pick, p))
1753 pick = p;
1754
1755 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
1756 pick->p_stat == SRUN ? "running" :
1757 pick->p_wmesg ? pick->p_wmesg : "iowait");
1758
1759 calcru(pick, &utime, &stime, NULL);
1760
1761 /* Print user time. */
1762 ttyprintf(tp, "%d.%02du ",
1763 utime.tv_sec, (utime.tv_usec + 5000) / 10000);
1764
1765 /* Print system time. */
1766 ttyprintf(tp, "%d.%02ds ",
1767 stime.tv_sec, (stime.tv_usec + 5000) / 10000);
1768
1769 #define pgtok(a) (((a) * NBPG) / 1024)
1770 /* Print percentage cpu, resident set size. */
1771 tmp = pick->p_pctcpu * 10000 + FSCALE / 2 >> FSHIFT;
1772 ttyprintf(tp, "%d%% %dk\n",
1773 tmp / 100,
1774 pick->p_stat == SIDL || pick->p_stat == SZOMB ? 0 :
1775 #ifdef pmap_resident_count
1776 pgtok(pmap_resident_count(&pick->p_vmspace->vm_pmap))
1777 #else
1778 pgtok(pick->p_vmspace->vm_rssize)
1779 #endif
1780 );
1781 }
1782 tp->t_rocount = 0; /* so pending input will be retyped if BS */
1783 }
1784
1785 /*
1786 * Returns 1 if p2 is "better" than p1
1787 *
1788 * The algorithm for picking the "interesting" process is thus:
1789 *
1790 * 1) Only foreground processes are eligible - implied.
1791 * 2) Runnable processes are favored over anything else. The runner
1792 * with the highest cpu utilization is picked (p_estcpu). Ties are
1793 * broken by picking the highest pid.
1794 * 3) The sleeper with the shortest sleep time is next. With ties,
1795 * we pick out just "short-term" sleepers (P_SINTR == 0).
1796 * 4) Further ties are broken by picking the highest pid.
1797 */
1798 #define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
1799 #define TESTAB(a, b) ((a)<<1 | (b))
1800 #define ONLYA 2
1801 #define ONLYB 1
1802 #define BOTH 3
1803
1804 static int
proc_compare(p1,p2)1805 proc_compare(p1, p2)
1806 register struct proc *p1, *p2;
1807 {
1808
1809 if (p1 == NULL)
1810 return (1);
1811 /*
1812 * see if at least one of them is runnable
1813 */
1814 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
1815 case ONLYA:
1816 return (0);
1817 case ONLYB:
1818 return (1);
1819 case BOTH:
1820 /*
1821 * tie - favor one with highest recent cpu utilization
1822 */
1823 if (p2->p_estcpu > p1->p_estcpu)
1824 return (1);
1825 if (p1->p_estcpu > p2->p_estcpu)
1826 return (0);
1827 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1828 }
1829 /*
1830 * weed out zombies
1831 */
1832 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
1833 case ONLYA:
1834 return (1);
1835 case ONLYB:
1836 return (0);
1837 case BOTH:
1838 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1839 }
1840 /*
1841 * pick the one with the smallest sleep time
1842 */
1843 if (p2->p_slptime > p1->p_slptime)
1844 return (0);
1845 if (p1->p_slptime > p2->p_slptime)
1846 return (1);
1847 /*
1848 * favor one sleeping in a non-interruptible sleep
1849 */
1850 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
1851 return (1);
1852 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
1853 return (0);
1854 return (p2->p_pid > p1->p_pid); /* tie - return highest pid */
1855 }
1856
1857 /*
1858 * Output char to tty; console putchar style.
1859 */
1860 int
tputchar(c,tp)1861 tputchar(c, tp)
1862 int c;
1863 struct tty *tp;
1864 {
1865 register int s;
1866
1867 s = spltty();
1868 if (ISSET(tp->t_state,
1869 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) {
1870 splx(s);
1871 return (-1);
1872 }
1873 if (c == '\n')
1874 (void)ttyoutput('\r', tp);
1875 (void)ttyoutput(c, tp);
1876 ttstart(tp);
1877 splx(s);
1878 return (0);
1879 }
1880
1881 /*
1882 * Sleep on chan, returning ERESTART if tty changed while we napped and
1883 * returning any errors (e.g. EINTR/ETIMEDOUT) reported by tsleep. If
1884 * the tty is revoked, restarting a pending call will redo validation done
1885 * at the start of the call.
1886 */
1887 int
ttysleep(tp,chan,pri,wmesg,timo)1888 ttysleep(tp, chan, pri, wmesg, timo)
1889 struct tty *tp;
1890 void *chan;
1891 int pri, timo;
1892 char *wmesg;
1893 {
1894 int error;
1895 short gen;
1896
1897 gen = tp->t_gen;
1898 if (error = tsleep(chan, pri, wmesg, timo))
1899 return (error);
1900 return (tp->t_gen == gen ? 0 : ERESTART);
1901 }
1902