This source file includes following definitions.
- ttyopen
- ttyclose
- ttyinput
- ttyoutput
- ttioctl
- ttpoll
- ttkqfilter
- filt_ttyrdetach
- filt_ttyread
- filt_ttywdetach
- filt_ttywrite
- ttnread
- ttywait
- ttywflush
- ttyflush
- ttychars
- ttyblock
- ttrstrt
- ttstart
- ttylclose
- ttymodem
- nullmodem
- ttypend
- ttvtimeout
- ttread
- ttyunblock
- ttycheckoutq
- ttwrite
- ttyrub
- ttyrubo
- ttyretype
- ttyecho
- ttwakeup
- ttspeedtab
- ttsetwater
- ttyinfo
- proc_compare
- tputchar
- ttysleep
- tty_init
- ttymalloc
- ttyfree
- ttystats_init
- sysctl_tty
- ttytstamp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/ioctl.h>
43 #include <sys/proc.h>
44 #define TTYDEFCHARS
45 #include <sys/tty.h>
46 #undef TTYDEFCHARS
47 #include <sys/file.h>
48 #include <sys/conf.h>
49 #include <sys/dkstat.h>
50 #include <sys/uio.h>
51 #include <sys/kernel.h>
52 #include <sys/vnode.h>
53 #include <sys/syslog.h>
54 #include <sys/malloc.h>
55 #include <sys/signalvar.h>
56 #include <sys/resourcevar.h>
57 #include <sys/sysctl.h>
58 #include <sys/pool.h>
59 #include <sys/poll.h>
60
61 #include <sys/namei.h>
62
63 #include <uvm/uvm_extern.h>
64 #include <dev/rndvar.h>
65
66 #include "pty.h"
67
68 static int ttnread(struct tty *);
69 static void ttyblock(struct tty *);
70 void ttyunblock(struct tty *);
71 static void ttyecho(int, struct tty *);
72 static void ttyrubo(struct tty *, int);
73 static int proc_compare(struct proc *, struct proc *);
74 int filt_ttyread(struct knote *kn, long hint);
75 void filt_ttyrdetach(struct knote *kn);
76 int filt_ttywrite(struct knote *kn, long hint);
77 void filt_ttywdetach(struct knote *kn);
78 int ttystats_init(void);
79
80
81 char ttclos[] = "ttycls";
82 char ttopen[] = "ttyopn";
83 char ttybg[] = "ttybg";
84 char ttyin[] = "ttyin";
85 char ttyout[] = "ttyout";
86
87
88
89
90
91
92
93
94 #define E 0x00
95 #define O 0x80
96 #define PARITY(c) (char_type[c] & O)
97
98 #define ALPHA 0x40
99 #define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
100
101 #define CCLASSMASK 0x3f
102 #define CCLASS(c) (char_type[c] & CCLASSMASK)
103
104 #define BS BACKSPACE
105 #define CC CONTROL
106 #define CR RETURN
107 #define NA ORDINARY | ALPHA
108 #define NL NEWLINE
109 #define NO ORDINARY
110 #define TB TAB
111 #define VT VTAB
112
113 u_char const char_type[] = {
114 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,
115 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC,
116 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC,
117 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,
118 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,
119 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO,
120 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
121 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,
122 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
123 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
124 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
125 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA,
126 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
127 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
128 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
129 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC,
130
131
132
133
134 NA, NA, NA, NA, NA, NA, NA, NA,
135 NA, NA, NA, NA, NA, NA, NA, NA,
136 NA, NA, NA, NA, NA, NA, NA, NA,
137 NA, NA, NA, NA, NA, NA, NA, NA,
138 NA, NA, NA, NA, NA, NA, NA, NA,
139 NA, NA, NA, NA, NA, NA, NA, NA,
140 NA, NA, NA, NA, NA, NA, NA, NA,
141 NA, NA, NA, NA, NA, NA, NA, NA,
142 NA, NA, NA, NA, NA, NA, NA, NA,
143 NA, NA, NA, NA, NA, NA, NA, NA,
144 NA, NA, NA, NA, NA, NA, NA, NA,
145 NA, NA, NA, NA, NA, NA, NA, NA,
146 NA, NA, NA, NA, NA, NA, NA, NA,
147 NA, NA, NA, NA, NA, NA, NA, NA,
148 NA, NA, NA, NA, NA, NA, NA, NA,
149 NA, NA, NA, NA, NA, NA, NA, NA,
150 };
151 #undef BS
152 #undef CC
153 #undef CR
154 #undef NA
155 #undef NL
156 #undef NO
157 #undef TB
158 #undef VT
159
160 #define islower(c) ((c) >= 'a' && (c) <= 'z')
161 #define isupper(c) ((c) >= 'A' && (c) <= 'Z')
162
163 #define tolower(c) ((c) - 'A' + 'a')
164 #define toupper(c) ((c) - 'a' + 'A')
165
166 struct ttylist_head ttylist;
167 int tty_count;
168
169 int64_t tk_cancc, tk_nin, tk_nout, tk_rawcc;
170
171
172
173
174 int
175 ttyopen(dev_t device, struct tty *tp)
176 {
177 int s;
178
179 s = spltty();
180 tp->t_dev = device;
181 if (!ISSET(tp->t_state, TS_ISOPEN)) {
182 SET(tp->t_state, TS_ISOPEN);
183 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
184 #ifdef COMPAT_OLDTTY
185 tp->t_flags = 0;
186 #endif
187 }
188 CLR(tp->t_state, TS_WOPEN);
189 splx(s);
190 return (0);
191 }
192
193
194
195
196
197
198 int
199 ttyclose(struct tty *tp)
200 {
201 extern struct tty *constty;
202
203 if (constty == tp)
204 constty = NULL;
205
206 ttyflush(tp, FREAD | FWRITE);
207
208 tp->t_gen++;
209 tp->t_pgrp = NULL;
210 if (tp->t_session)
211 SESSRELE(tp->t_session);
212 tp->t_session = NULL;
213 tp->t_state = 0;
214 return (0);
215 }
216
217 #define FLUSHQ(q) { \
218 if ((q)->c_cc) \
219 ndflush(q, (q)->c_cc); \
220 }
221
222
223 #define TTBREAKC(c, lflag) \
224 ((c) == '\n' || (((c) == cc[VEOF] || (c) == cc[VEOL] || \
225 ((c) == cc[VEOL2] && (lflag & IEXTEN))) && (c) != _POSIX_VDISABLE))
226
227
228
229
230
231 int
232 ttyinput(int c, struct tty *tp)
233 {
234 int iflag, lflag;
235 u_char *cc;
236 int i, error;
237 int s;
238
239 add_tty_randomness(tp->t_dev << 8 | c);
240
241
242
243 if (!ISSET(tp->t_cflag, CREAD))
244 return (0);
245
246
247
248
249 lflag = tp->t_lflag;
250 s = spltty();
251 if (ISSET(lflag, PENDIN))
252 ttypend(tp);
253 splx(s);
254
255
256
257 if (ISSET(lflag, ICANON)) {
258 ++tk_cancc;
259 ++tp->t_cancc;
260 } else {
261 ++tk_rawcc;
262 ++tp->t_rawcc;
263 }
264 ++tk_nin;
265
266
267 cc = tp->t_cc;
268 iflag = tp->t_iflag;
269 if ((error = (ISSET(c, TTY_ERRORMASK))) != 0) {
270 CLR(c, TTY_ERRORMASK);
271 if (ISSET(error, TTY_FE) && !c) {
272 if (ISSET(iflag, IGNBRK))
273 return (0);
274 ttyflush(tp, FREAD | FWRITE);
275 if (ISSET(iflag, BRKINT)) {
276 pgsignal(tp->t_pgrp, SIGINT, 1);
277 goto endcase;
278 }
279 else if (ISSET(iflag, PARMRK))
280 goto parmrk;
281 } else if ((ISSET(error, TTY_PE) && ISSET(iflag, INPCK)) ||
282 ISSET(error, TTY_FE)) {
283 if (ISSET(iflag, IGNPAR))
284 goto endcase;
285 else if (ISSET(iflag, PARMRK)) {
286 parmrk: (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
287 if (ISSET(iflag, ISTRIP) || c != 0377)
288 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
289 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
290 goto endcase;
291 } else
292 c = 0;
293 }
294 }
295 if (c == 0377 && !ISSET(iflag, ISTRIP) && ISSET(iflag, PARMRK))
296 goto parmrk;
297
298
299
300
301 if (ISSET(iflag, IXOFF) || ISSET(tp->t_cflag, CHWFLOW))
302 ttyblock(tp);
303 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
304 CLR(c, 0x80);
305 if (!ISSET(lflag, EXTPROC)) {
306
307
308
309 if (ISSET(tp->t_state, TS_LNCH)) {
310 SET(c, TTY_QUOTE);
311 CLR(tp->t_state, TS_LNCH);
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325 if (ISSET(lflag, IEXTEN)) {
326 if (CCEQ(cc[VLNEXT], c)) {
327 if (ISSET(lflag, ECHO)) {
328 if (ISSET(lflag, ECHOE)) {
329 (void)ttyoutput('^', tp);
330 (void)ttyoutput('\b', tp);
331 } else
332 ttyecho(c, tp);
333 }
334 SET(tp->t_state, TS_LNCH);
335 goto endcase;
336 }
337 if (CCEQ(cc[VDISCARD], c)) {
338 if (ISSET(lflag, FLUSHO))
339 CLR(tp->t_lflag, FLUSHO);
340 else {
341 ttyflush(tp, FWRITE);
342 ttyecho(c, tp);
343 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
344 ttyretype(tp);
345 SET(tp->t_lflag, FLUSHO);
346 }
347 goto startoutput;
348 }
349 }
350
351
352
353 if (ISSET(lflag, ISIG)) {
354 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
355 if (!ISSET(lflag, NOFLSH))
356 ttyflush(tp, FREAD | FWRITE);
357 ttyecho(c, tp);
358 pgsignal(tp->t_pgrp,
359 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
360 goto endcase;
361 }
362 if (CCEQ(cc[VSUSP], c)) {
363 if (!ISSET(lflag, NOFLSH))
364 ttyflush(tp, FREAD);
365 ttyecho(c, tp);
366 pgsignal(tp->t_pgrp, SIGTSTP, 1);
367 goto endcase;
368 }
369 }
370
371
372
373 if (ISSET(iflag, IXON)) {
374 if (CCEQ(cc[VSTOP], c)) {
375 if (!ISSET(tp->t_state, TS_TTSTOP)) {
376 SET(tp->t_state, TS_TTSTOP);
377 (*cdevsw[major(tp->t_dev)].d_stop)(tp,
378 0);
379 return (0);
380 }
381 if (!CCEQ(cc[VSTART], c))
382 return (0);
383
384
385
386 goto endcase;
387 }
388 if (CCEQ(cc[VSTART], c))
389 goto restartoutput;
390 }
391
392
393
394 if (c == '\r') {
395 if (ISSET(iflag, IGNCR))
396 goto endcase;
397 else if (ISSET(iflag, ICRNL))
398 c = '\n';
399 } else if (c == '\n' && ISSET(iflag, INLCR))
400 c = '\r';
401 }
402 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
403
404
405
406
407
408
409
410 if (ISSET(lflag, XCASE) && ISSET(iflag, IUCLC)) {
411 if (ISSET(tp->t_state, TS_BKSL)) {
412 CLR(tp->t_state, TS_BKSL);
413 switch (c) {
414 case '\'':
415 c = '`';
416 break;
417 case '!':
418 c = '|';
419 break;
420 case '^':
421 c = '~';
422 break;
423 case '(':
424 c = '{';
425 break;
426 case ')':
427 c = '}';
428 break;
429 }
430 }
431 else if (c == '\\') {
432 SET(tp->t_state, TS_BKSL);
433 goto endcase;
434 }
435 else if (isupper(c))
436 c = tolower(c);
437 }
438 else if (ISSET(iflag, IUCLC) && isupper(c))
439 c = tolower(c);
440
441
442
443 if (CCEQ(cc[VERASE], c)) {
444 if (tp->t_rawq.c_cc)
445 ttyrub(unputc(&tp->t_rawq), tp);
446 goto endcase;
447 }
448
449
450
451 if (CCEQ(cc[VKILL], c)) {
452 if (ISSET(lflag, ECHOKE) &&
453 tp->t_rawq.c_cc == tp->t_rocount &&
454 !ISSET(lflag, ECHOPRT))
455 while (tp->t_rawq.c_cc)
456 ttyrub(unputc(&tp->t_rawq), tp);
457 else {
458 ttyecho(c, tp);
459 if (ISSET(lflag, ECHOK) ||
460 ISSET(lflag, ECHOKE))
461 ttyecho('\n', tp);
462 FLUSHQ(&tp->t_rawq);
463 tp->t_rocount = 0;
464 }
465 CLR(tp->t_state, TS_LOCAL);
466 goto endcase;
467 }
468
469
470
471 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
472 int alt = ISSET(lflag, ALTWERASE);
473 int ctype;
474
475
476
477
478 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
479 ttyrub(c, tp);
480 if (c == -1)
481 goto endcase;
482
483
484
485
486 ttyrub(c, tp);
487 c = unputc(&tp->t_rawq);
488 if (c == -1)
489 goto endcase;
490 if (c == ' ' || c == '\t') {
491 (void)putc(c, &tp->t_rawq);
492 goto endcase;
493 }
494 ctype = ISALPHA(c);
495
496
497
498 do {
499 ttyrub(c, tp);
500 c = unputc(&tp->t_rawq);
501 if (c == -1)
502 goto endcase;
503 } while (c != ' ' && c != '\t' &&
504 (alt == 0 || ISALPHA(c) == ctype));
505 (void)putc(c, &tp->t_rawq);
506 goto endcase;
507 }
508
509
510
511 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
512 ttyretype(tp);
513 goto endcase;
514 }
515
516
517
518 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
519 if (ISSET(lflag, ISIG))
520 pgsignal(tp->t_pgrp, SIGINFO, 1);
521 if (!ISSET(lflag, NOKERNINFO))
522 ttyinfo(tp);
523 goto endcase;
524 }
525 }
526
527
528
529 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) {
530 if (ISSET(iflag, IMAXBEL)) {
531 if (tp->t_outq.c_cc < tp->t_hiwat)
532 (void)ttyoutput(CTRL('g'), tp);
533 } else
534 ttyflush(tp, FREAD | FWRITE);
535 goto endcase;
536 }
537
538
539
540
541 if (putc(c, &tp->t_rawq) >= 0) {
542 if (!ISSET(lflag, ICANON)) {
543 ttwakeup(tp);
544 ttyecho(c, tp);
545 goto endcase;
546 }
547 if (TTBREAKC(c, lflag)) {
548 tp->t_rocount = 0;
549 catq(&tp->t_rawq, &tp->t_canq);
550 ttwakeup(tp);
551 } else if (tp->t_rocount++ == 0)
552 tp->t_rocol = tp->t_column;
553 if (ISSET(tp->t_state, TS_ERASE)) {
554
555
556
557 CLR(tp->t_state, TS_ERASE);
558 (void)ttyoutput('/', tp);
559 }
560 i = tp->t_column;
561 ttyecho(c, tp);
562 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
563
564
565
566 i = min(2, tp->t_column - i);
567 while (i > 0) {
568 (void)ttyoutput('\b', tp);
569 i--;
570 }
571 }
572 }
573 endcase:
574
575
576
577 if (ISSET(tp->t_state, TS_TTSTOP) &&
578 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP])
579 return (0);
580 restartoutput:
581 CLR(tp->t_lflag, FLUSHO);
582 CLR(tp->t_state, TS_TTSTOP);
583 startoutput:
584 return (ttstart(tp));
585 }
586
587
588
589
590
591
592
593 int
594 ttyoutput(int c, struct tty *tp)
595 {
596 long oflag;
597 int col, notout, s, c2;
598
599 oflag = tp->t_oflag;
600 if (!ISSET(oflag, OPOST)) {
601 tk_nout++;
602 tp->t_outcc++;
603 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
604 return (c);
605 return (-1);
606 }
607
608
609
610
611
612
613 CLR(c, ~TTY_CHARMASK);
614 if (c == '\t' &&
615 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
616 c = 8 - (tp->t_column & 7);
617 if (ISSET(tp->t_lflag, FLUSHO)) {
618 notout = 0;
619 } else {
620 s = spltty();
621 notout = b_to_q(" ", c, &tp->t_outq);
622 c -= notout;
623 tk_nout += c;
624 tp->t_outcc += c;
625 splx(s);
626 }
627 tp->t_column += c;
628 return (notout ? '\t' : -1);
629 }
630 if (c == CEOT && ISSET(oflag, ONOEOT))
631 return (-1);
632
633
634
635
636
637
638 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
639 tk_nout++;
640 tp->t_outcc++;
641 if (!ISSET(tp->t_lflag, FLUSHO) && putc('\r', &tp->t_outq))
642 return (c);
643 tp->t_column = 0;
644 }
645 else if (c == '\r' && ISSET(tp->t_oflag, OCRNL))
646 c = '\n';
647
648 if (ISSET(tp->t_oflag, OLCUC) && islower(c))
649 c = toupper(c);
650 else if (ISSET(tp->t_oflag, OLCUC) && ISSET(tp->t_lflag, XCASE)) {
651 c2 = c;
652 switch (c) {
653 case '`':
654 c2 = '\'';
655 break;
656 case '|':
657 c2 = '!';
658 break;
659 case '~':
660 c2 = '^';
661 break;
662 case '{':
663 c2 = '(';
664 break;
665 case '}':
666 c2 = ')';
667 break;
668 }
669 if (c == '\\' || isupper(c) || c != c2) {
670 tk_nout++;
671 tp->t_outcc++;
672 if (putc('\\', &tp->t_outq))
673 return (c);
674 c = c2;
675 }
676 }
677 if (ISSET(tp->t_oflag, ONOCR) && c == '\r' && tp->t_column == 0)
678 return (-1);
679
680 tk_nout++;
681 tp->t_outcc++;
682 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
683 return (c);
684
685 col = tp->t_column;
686 switch (CCLASS(c)) {
687 case BACKSPACE:
688 if (col > 0)
689 --col;
690 break;
691 case CONTROL:
692 break;
693 case NEWLINE:
694 if (ISSET(tp->t_oflag, ONLRET) || ISSET(tp->t_oflag, OCRNL))
695 col = 0;
696 break;
697 case RETURN:
698 col = 0;
699 break;
700 case ORDINARY:
701 ++col;
702 break;
703 case TAB:
704 col = (col + 8) & ~7;
705 break;
706 }
707 tp->t_column = col;
708 return (-1);
709 }
710
711
712
713
714
715
716
717 int
718 ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
719 {
720 extern struct tty *constty;
721 extern int nlinesw;
722 int s, error;
723
724
725 switch (cmd) {
726 case TIOCFLUSH:
727 case TIOCDRAIN:
728 case TIOCSBRK:
729 case TIOCCBRK:
730 case TIOCSETA:
731 case TIOCSETD:
732 case TIOCSETAF:
733 case TIOCSETAW:
734 #ifdef notdef
735 case TIOCSPGRP:
736 #endif
737 case TIOCSTAT:
738 case TIOCSTI:
739 case TIOCSWINSZ:
740 #ifdef COMPAT_OLDTTY
741 case TIOCLBIC:
742 case TIOCLBIS:
743 case TIOCLSET:
744 case TIOCSETC:
745 case OTIOCSETD:
746 case TIOCSETN:
747 case TIOCSETP:
748 case TIOCSLTC:
749 #endif
750 while (isbackground(p, tp) &&
751 (p->p_flag & P_PPWAIT) == 0 &&
752 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
753 (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
754 if (p->p_pgrp->pg_jobc == 0)
755 return (EIO);
756 pgsignal(p->p_pgrp, SIGTTOU, 1);
757 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH,
758 ttybg, 0);
759 if (error)
760 return (error);
761 }
762 break;
763 }
764
765 switch (cmd) {
766 case FIOASYNC:
767 s = spltty();
768 if (*(int *)data)
769 SET(tp->t_state, TS_ASYNC);
770 else
771 CLR(tp->t_state, TS_ASYNC);
772 splx(s);
773 break;
774 case FIONBIO:
775 break;
776 case FIONREAD:
777 s = spltty();
778 *(int *)data = ttnread(tp);
779 splx(s);
780 break;
781 case TIOCEXCL:
782 s = spltty();
783 SET(tp->t_state, TS_XCLUDE);
784 splx(s);
785 break;
786 case TIOCFLUSH: {
787 int flags = *(int *)data;
788
789 if (flags == 0)
790 flags = FREAD | FWRITE;
791 else
792 flags &= FREAD | FWRITE;
793 ttyflush(tp, flags);
794 break;
795 }
796 case TIOCCONS: {
797 if (*(int *)data) {
798 struct nameidata nid;
799
800 if (constty != NULL && constty != tp &&
801 ISSET(constty->t_state, TS_CARR_ON | TS_ISOPEN) ==
802 (TS_CARR_ON | TS_ISOPEN))
803 return (EBUSY);
804
805
806 NDINIT(&nid, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
807 error = namei(&nid);
808 if (error)
809 return (error);
810 vn_lock(nid.ni_vp, LK_EXCLUSIVE | LK_RETRY, p);
811 error = VOP_ACCESS(nid.ni_vp, VREAD, p->p_ucred, p);
812 VOP_UNLOCK(nid.ni_vp, 0, p);
813 vrele(nid.ni_vp);
814 if (error)
815 return (error);
816
817 constty = tp;
818 } else if (tp == constty)
819 constty = NULL;
820 break;
821 }
822 case TIOCDRAIN:
823 if ((error = ttywait(tp)) != 0)
824 return (error);
825 break;
826 case TIOCGETA: {
827 struct termios *t = (struct termios *)data;
828
829 bcopy(&tp->t_termios, t, sizeof(struct termios));
830 break;
831 }
832 case TIOCGETD:
833 *(int *)data = tp->t_line;
834 break;
835 case TIOCGWINSZ:
836 *(struct winsize *)data = tp->t_winsize;
837 break;
838 case TIOCGTSTAMP:
839 s = spltty();
840 *(struct timeval *)data = tp->t_tv;
841 splx(s);
842 break;
843 case TIOCGPGRP:
844 if (!isctty(p, tp) && suser(p, 0))
845 return (ENOTTY);
846 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
847 break;
848 #ifdef TIOCHPCL
849 case TIOCHPCL:
850 s = spltty();
851 SET(tp->t_cflag, HUPCL);
852 splx(s);
853 break;
854 #endif
855 case TIOCNXCL:
856 s = spltty();
857 CLR(tp->t_state, TS_XCLUDE);
858 splx(s);
859 break;
860 case TIOCOUTQ:
861 *(int *)data = tp->t_outq.c_cc;
862 break;
863 case TIOCSETA:
864 case TIOCSETAW:
865 case TIOCSETAF: {
866 struct termios *t = (struct termios *)data;
867
868 s = spltty();
869 if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
870 if ((error = ttywait(tp)) != 0) {
871 splx(s);
872 return (error);
873 }
874 if (cmd == TIOCSETAF)
875 ttyflush(tp, FREAD);
876 }
877 if (!ISSET(t->c_cflag, CIGNORE)) {
878
879
880
881 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
882 splx(s);
883 return (error);
884 } else {
885 if (!ISSET(tp->t_state, TS_CARR_ON) &&
886 ISSET(tp->t_cflag, CLOCAL) &&
887 !ISSET(t->c_cflag, CLOCAL)) {
888 CLR(tp->t_state, TS_ISOPEN);
889 SET(tp->t_state, TS_WOPEN);
890 ttwakeup(tp);
891 }
892 tp->t_cflag = t->c_cflag;
893 tp->t_ispeed = t->c_ispeed;
894 tp->t_ospeed = t->c_ospeed;
895 if (t->c_ospeed == 0 && tp->t_session &&
896 tp->t_session->s_leader)
897 psignal(tp->t_session->s_leader,
898 SIGHUP);
899 }
900 ttsetwater(tp);
901 }
902 if (cmd != TIOCSETAF) {
903 if (ISSET(t->c_lflag, ICANON) !=
904 ISSET(tp->t_lflag, ICANON)) {
905 if (ISSET(t->c_lflag, ICANON)) {
906 SET(tp->t_lflag, PENDIN);
907 ttwakeup(tp);
908 } else {
909 struct clist tq;
910
911 catq(&tp->t_rawq, &tp->t_canq);
912 tq = tp->t_rawq;
913 tp->t_rawq = tp->t_canq;
914 tp->t_canq = tq;
915 CLR(tp->t_lflag, PENDIN);
916 }
917 }
918 }
919 tp->t_iflag = t->c_iflag;
920 tp->t_oflag = t->c_oflag;
921
922
923
924 if (ISSET(tp->t_lflag, EXTPROC))
925 SET(t->c_lflag, EXTPROC);
926 else
927 CLR(t->c_lflag, EXTPROC);
928 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
929 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
930 splx(s);
931 break;
932 }
933 case TIOCSETD: {
934 int t = *(int *)data;
935 dev_t device = tp->t_dev;
936
937 if ((u_int)t >= nlinesw)
938 return (ENXIO);
939 if (t != tp->t_line) {
940 s = spltty();
941 (*linesw[tp->t_line].l_close)(tp, flag);
942 error = (*linesw[t].l_open)(device, tp);
943 if (error) {
944 (void)(*linesw[tp->t_line].l_open)(device, tp);
945 splx(s);
946 return (error);
947 }
948 tp->t_line = t;
949 splx(s);
950 }
951 break;
952 }
953 case TIOCSTART:
954 s = spltty();
955 if (ISSET(tp->t_state, TS_TTSTOP) ||
956 ISSET(tp->t_lflag, FLUSHO)) {
957 CLR(tp->t_lflag, FLUSHO);
958 CLR(tp->t_state, TS_TTSTOP);
959 ttstart(tp);
960 }
961 splx(s);
962 break;
963 case TIOCSTI:
964 if (p->p_ucred->cr_uid && (flag & FREAD) == 0)
965 return (EPERM);
966 if (p->p_ucred->cr_uid && !isctty(p, tp))
967 return (EACCES);
968 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
969 break;
970 case TIOCSTOP:
971 s = spltty();
972 if (!ISSET(tp->t_state, TS_TTSTOP)) {
973 SET(tp->t_state, TS_TTSTOP);
974 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
975 }
976 splx(s);
977 break;
978 case TIOCSCTTY:
979
980 if (!SESS_LEADER(p) ||
981 ((p->p_session->s_ttyvp || tp->t_session) &&
982 (tp->t_session != p->p_session)))
983 return (EPERM);
984 if (tp->t_session)
985 SESSRELE(tp->t_session);
986 SESSHOLD(p->p_session);
987 tp->t_session = p->p_session;
988 tp->t_pgrp = p->p_pgrp;
989 p->p_session->s_ttyp = tp;
990 atomic_setbits_int(&p->p_flag, P_CONTROLT);
991 break;
992 case TIOCSPGRP: {
993 struct pgrp *pgrp = pgfind(*(int *)data);
994
995 if (!isctty(p, tp))
996 return (ENOTTY);
997 else if (pgrp == NULL)
998 return (EINVAL);
999 else if (pgrp->pg_session != p->p_session)
1000 return (EPERM);
1001 tp->t_pgrp = pgrp;
1002 break;
1003 }
1004 case TIOCSTAT:
1005 ttyinfo(tp);
1006 break;
1007 case TIOCSWINSZ:
1008 if (bcmp((caddr_t)&tp->t_winsize, data,
1009 sizeof (struct winsize))) {
1010 tp->t_winsize = *(struct winsize *)data;
1011 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1012 }
1013 break;
1014 case TIOCSTSTAMP: {
1015 struct tstamps *ts = (struct tstamps *)data;
1016
1017 s = spltty();
1018 CLR(tp->t_flags, TS_TSTAMPDCDSET);
1019 CLR(tp->t_flags, TS_TSTAMPCTSSET);
1020 CLR(tp->t_flags, TS_TSTAMPDCDCLR);
1021 CLR(tp->t_flags, TS_TSTAMPCTSCLR);
1022 if (ISSET(ts->ts_set, TIOCM_CAR))
1023 SET(tp->t_flags, TS_TSTAMPDCDSET);
1024 if (ISSET(ts->ts_set, TIOCM_CTS))
1025 SET(tp->t_flags, TS_TSTAMPCTSSET);
1026 if (ISSET(ts->ts_clr, TIOCM_CAR))
1027 SET(tp->t_flags, TS_TSTAMPDCDCLR);
1028 if (ISSET(ts->ts_clr, TIOCM_CTS))
1029 SET(tp->t_flags, TS_TSTAMPCTSCLR);
1030 splx(s);
1031 break;
1032 }
1033 default:
1034 #ifdef COMPAT_OLDTTY
1035 return (ttcompat(tp, cmd, data, flag, p));
1036 #else
1037 return (-1);
1038 #endif
1039 }
1040 return (0);
1041 }
1042
1043 int
1044 ttpoll(dev_t device, int events, struct proc *p)
1045 {
1046 struct tty *tp;
1047 int revents, s;
1048
1049 tp = (*cdevsw[major(device)].d_tty)(device);
1050
1051 revents = 0;
1052 s = spltty();
1053 if (events & (POLLIN | POLLRDNORM)) {
1054 if (ttnread(tp) > 0 || (!ISSET(tp->t_cflag, CLOCAL) &&
1055 !ISSET(tp->t_state, TS_CARR_ON)))
1056 revents |= events & (POLLIN | POLLRDNORM);
1057 }
1058 if (events & (POLLOUT | POLLWRNORM)) {
1059 if (tp->t_outq.c_cc <= tp->t_lowat)
1060 revents |= events & (POLLOUT | POLLWRNORM);
1061 }
1062 if (revents == 0) {
1063 if (events & (POLLIN | POLLRDNORM))
1064 selrecord(p, &tp->t_rsel);
1065 if (events & (POLLOUT | POLLWRNORM))
1066 selrecord(p, &tp->t_wsel);
1067 }
1068 splx(s);
1069 return (revents);
1070 }
1071
1072 struct filterops ttyread_filtops =
1073 { 1, NULL, filt_ttyrdetach, filt_ttyread };
1074 struct filterops ttywrite_filtops =
1075 { 1, NULL, filt_ttywdetach, filt_ttywrite };
1076
1077 int
1078 ttkqfilter(dev_t dev, struct knote *kn)
1079 {
1080 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1081 struct klist *klist;
1082 int s;
1083
1084 switch (kn->kn_filter) {
1085 case EVFILT_READ:
1086 klist = &tp->t_rsel.si_note;
1087 kn->kn_fop = &ttyread_filtops;
1088 break;
1089 case EVFILT_WRITE:
1090 klist = &tp->t_wsel.si_note;
1091 kn->kn_fop = &ttywrite_filtops;
1092 break;
1093 default:
1094 return (1);
1095 }
1096
1097 kn->kn_hook = (caddr_t)((u_long)dev);
1098
1099 s = spltty();
1100 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1101 splx(s);
1102
1103 return (0);
1104 }
1105
1106 void
1107 filt_ttyrdetach(struct knote *kn)
1108 {
1109 dev_t dev = (dev_t)((u_long)kn->kn_hook);
1110 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1111 int s = spltty();
1112
1113 SLIST_REMOVE(&tp->t_rsel.si_note, kn, knote, kn_selnext);
1114 splx(s);
1115 }
1116
1117 int
1118 filt_ttyread(struct knote *kn, long hint)
1119 {
1120 dev_t dev = (dev_t)((u_long)kn->kn_hook);
1121 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1122 int s;
1123
1124 s = spltty();
1125 kn->kn_data = ttnread(tp);
1126 splx(s);
1127 if (!ISSET(tp->t_cflag, CLOCAL) && !ISSET(tp->t_state, TS_CARR_ON)) {
1128 kn->kn_flags |= EV_EOF;
1129 return (1);
1130 }
1131 return (kn->kn_data > 0);
1132 }
1133
1134 void
1135 filt_ttywdetach(struct knote *kn)
1136 {
1137 dev_t dev = (dev_t)((u_long)kn->kn_hook);
1138 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1139 int s = spltty();
1140
1141 SLIST_REMOVE(&tp->t_wsel.si_note, kn, knote, kn_selnext);
1142 splx(s);
1143 }
1144
1145 int
1146 filt_ttywrite(struct knote *kn, long hint)
1147 {
1148 dev_t dev = (dev_t)((u_long)kn->kn_hook);
1149 struct tty *tp = (*cdevsw[major(dev)].d_tty)(dev);
1150
1151 kn->kn_data = tp->t_outq.c_cc;
1152 return (kn->kn_data <= tp->t_lowat);
1153 }
1154
1155 static int
1156 ttnread(struct tty *tp)
1157 {
1158 int nread;
1159
1160 splassert(IPL_TTY);
1161
1162 if (ISSET(tp->t_lflag, PENDIN))
1163 ttypend(tp);
1164 nread = tp->t_canq.c_cc;
1165 if (!ISSET(tp->t_lflag, ICANON)) {
1166 nread += tp->t_rawq.c_cc;
1167 if (nread < tp->t_cc[VMIN] && !tp->t_cc[VTIME])
1168 nread = 0;
1169 }
1170 return (nread);
1171 }
1172
1173
1174
1175
1176 int
1177 ttywait(struct tty *tp)
1178 {
1179 int error, s;
1180
1181 error = 0;
1182 s = spltty();
1183 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1184 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL)) &&
1185 tp->t_oproc) {
1186 (*tp->t_oproc)(tp);
1187 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1188 (ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
1189 && tp->t_oproc) {
1190 SET(tp->t_state, TS_ASLEEP);
1191 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1192 if (error)
1193 break;
1194 } else
1195 break;
1196 }
1197 splx(s);
1198 return (error);
1199 }
1200
1201
1202
1203
1204 int
1205 ttywflush(struct tty *tp)
1206 {
1207 int error;
1208
1209 if ((error = ttywait(tp)) == 0)
1210 ttyflush(tp, FREAD);
1211 return (error);
1212 }
1213
1214
1215
1216
1217 void
1218 ttyflush(struct tty *tp, int rw)
1219 {
1220 int s;
1221
1222 s = spltty();
1223 if (rw & FREAD) {
1224 FLUSHQ(&tp->t_canq);
1225 FLUSHQ(&tp->t_rawq);
1226 tp->t_rocount = 0;
1227 tp->t_rocol = 0;
1228 CLR(tp->t_state, TS_LOCAL);
1229 ttyunblock(tp);
1230 ttwakeup(tp);
1231 }
1232 if (rw & FWRITE) {
1233 CLR(tp->t_state, TS_TTSTOP);
1234 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1235 FLUSHQ(&tp->t_outq);
1236 wakeup((caddr_t)&tp->t_outq);
1237 selwakeup(&tp->t_wsel);
1238 }
1239 splx(s);
1240 }
1241
1242
1243
1244
1245 void
1246 ttychars(struct tty *tp)
1247 {
1248
1249 bcopy(ttydefchars, tp->t_cc, sizeof(ttydefchars));
1250 }
1251
1252
1253
1254
1255 static void
1256 ttyblock(struct tty *tp)
1257 {
1258 int total;
1259
1260 total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
1261 if (tp->t_rawq.c_cc > TTYHOG) {
1262 ttyflush(tp, FREAD | FWRITE);
1263 CLR(tp->t_state, TS_TBLOCK);
1264 }
1265
1266
1267
1268
1269 if ((total >= TTYHOG / 2 &&
1270 !ISSET(tp->t_state, TS_TBLOCK) &&
1271 !ISSET(tp->t_lflag, ICANON)) || tp->t_canq.c_cc > 0) {
1272 if (ISSET(tp->t_iflag, IXOFF) &&
1273 tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1274 putc(tp->t_cc[VSTOP], &tp->t_outq) == 0) {
1275 SET(tp->t_state, TS_TBLOCK);
1276 ttstart(tp);
1277 }
1278
1279 if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1280 (*tp->t_hwiflow)(tp, 1) != 0)
1281 SET(tp->t_state, TS_TBLOCK);
1282 }
1283 }
1284
1285 void
1286 ttrstrt(void *tp_arg)
1287 {
1288 struct tty *tp;
1289 int s;
1290
1291 #ifdef DIAGNOSTIC
1292 if (tp_arg == NULL)
1293 panic("ttrstrt");
1294 #endif
1295 tp = tp_arg;
1296 s = spltty();
1297
1298 CLR(tp->t_state, TS_TIMEOUT);
1299 ttstart(tp);
1300
1301 splx(s);
1302 }
1303
1304 int
1305 ttstart(struct tty *tp)
1306 {
1307
1308 if (tp->t_oproc != NULL)
1309 (*tp->t_oproc)(tp);
1310 return (0);
1311 }
1312
1313
1314
1315
1316 int
1317 ttylclose(struct tty *tp, int flag)
1318 {
1319
1320 if (flag & FNONBLOCK)
1321 ttyflush(tp, FREAD | FWRITE);
1322 else
1323 ttywflush(tp);
1324 return (0);
1325 }
1326
1327
1328
1329
1330
1331
1332 int
1333 ttymodem(struct tty *tp, int flag)
1334 {
1335
1336 if (!ISSET(tp->t_state, TS_WOPEN) && ISSET(tp->t_cflag, MDMBUF)) {
1337
1338
1339
1340 if (flag) {
1341 CLR(tp->t_state, TS_TTSTOP);
1342 ttstart(tp);
1343 } else if (!ISSET(tp->t_state, TS_TTSTOP)) {
1344 SET(tp->t_state, TS_TTSTOP);
1345 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
1346 }
1347 } else if (flag == 0) {
1348
1349
1350
1351 CLR(tp->t_state, TS_CARR_ON);
1352 if (ISSET(tp->t_state, TS_ISOPEN) &&
1353 !ISSET(tp->t_cflag, CLOCAL)) {
1354 if (tp->t_session && tp->t_session->s_leader)
1355 psignal(tp->t_session->s_leader, SIGHUP);
1356 ttyflush(tp, FREAD | FWRITE);
1357 return (0);
1358 }
1359 } else {
1360
1361
1362
1363 SET(tp->t_state, TS_CARR_ON);
1364 ttwakeup(tp);
1365 }
1366 return (1);
1367 }
1368
1369
1370
1371
1372
1373 int
1374 nullmodem(struct tty *tp, int flag)
1375 {
1376
1377 if (flag)
1378 SET(tp->t_state, TS_CARR_ON);
1379 else {
1380 CLR(tp->t_state, TS_CARR_ON);
1381 if (ISSET(tp->t_state, TS_ISOPEN) &&
1382 !ISSET(tp->t_cflag, CLOCAL)) {
1383 if (tp->t_session && tp->t_session->s_leader)
1384 psignal(tp->t_session->s_leader, SIGHUP);
1385 ttyflush(tp, FREAD | FWRITE);
1386 return (0);
1387 }
1388 }
1389 return (1);
1390 }
1391
1392
1393
1394
1395
1396 void
1397 ttypend(struct tty *tp)
1398 {
1399 struct clist tq;
1400 int c;
1401
1402 splassert(IPL_TTY);
1403
1404 CLR(tp->t_lflag, PENDIN);
1405 SET(tp->t_state, TS_TYPEN);
1406 tq = tp->t_rawq;
1407 tp->t_rawq.c_cc = 0;
1408 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1409 while ((c = getc(&tq)) >= 0)
1410 ttyinput(c, tp);
1411 CLR(tp->t_state, TS_TYPEN);
1412 }
1413
1414 void ttvtimeout(void *);
1415
1416 void
1417 ttvtimeout(void *arg)
1418 {
1419 struct tty *tp = (struct tty *)arg;
1420
1421 wakeup(&tp->t_rawq);
1422 }
1423
1424
1425
1426
1427 int
1428 ttread(struct tty *tp, struct uio *uio, int flag)
1429 {
1430 struct timeout *stime = NULL;
1431 struct proc *p = curproc;
1432 int s, first, error = 0;
1433 u_char *cc = tp->t_cc;
1434 struct clist *qp;
1435 int last_cc = 0;
1436 long lflag;
1437 int c;
1438
1439 loop: lflag = tp->t_lflag;
1440 s = spltty();
1441
1442
1443
1444 if (ISSET(lflag, PENDIN))
1445 ttypend(tp);
1446 splx(s);
1447
1448
1449
1450
1451 if (isbackground(p, tp)) {
1452 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1453 (p->p_sigmask & sigmask(SIGTTIN)) ||
1454 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1455 error = EIO;
1456 goto out;
1457 }
1458 pgsignal(p->p_pgrp, SIGTTIN, 1);
1459 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1460 if (error)
1461 goto out;
1462 goto loop;
1463 }
1464
1465 s = spltty();
1466 if (!ISSET(lflag, ICANON)) {
1467 int m = cc[VMIN];
1468 long t;
1469
1470
1471
1472
1473
1474
1475 t = cc[VTIME] * hz / 10;
1476
1477 qp = &tp->t_rawq;
1478
1479
1480
1481
1482
1483
1484 if (t == 0) {
1485 if (qp->c_cc < m)
1486 goto sleep;
1487 goto read;
1488 }
1489 if (m > 0) {
1490 if (qp->c_cc <= 0)
1491 goto sleep;
1492 if (qp->c_cc >= m)
1493 goto read;
1494 if (stime == NULL) {
1495 alloc_timer:
1496 stime = malloc(sizeof(*stime), M_TEMP, M_WAITOK);
1497 timeout_set(stime, ttvtimeout, tp);
1498 timeout_add(stime, t);
1499 } else if (qp->c_cc > last_cc) {
1500
1501 timeout_add(stime, t);
1502 }
1503 } else {
1504 if (qp->c_cc > 0)
1505 goto read;
1506 if (stime == NULL) {
1507 goto alloc_timer;
1508 }
1509 }
1510 last_cc = qp->c_cc;
1511 if (stime && !timeout_triggered(stime)) {
1512 goto sleep;
1513 }
1514 } else if ((qp = &tp->t_canq)->c_cc <= 0) {
1515 int carrier;
1516
1517 sleep:
1518
1519
1520
1521
1522
1523 carrier = ISSET(tp->t_state, TS_CARR_ON) ||
1524 ISSET(tp->t_cflag, CLOCAL);
1525 if (!carrier && ISSET(tp->t_state, TS_ISOPEN)) {
1526 splx(s);
1527 error = 0;
1528 goto out;
1529 }
1530 if (flag & IO_NDELAY) {
1531 splx(s);
1532 error = EWOULDBLOCK;
1533 goto out;
1534 }
1535 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
1536 carrier ? ttyin : ttopen, 0);
1537 splx(s);
1538 if (stime && timeout_triggered(stime))
1539 error = EWOULDBLOCK;
1540 if (cc[VMIN] == 0 && error == EWOULDBLOCK) {
1541 error = 0;
1542 goto out;
1543 }
1544 if (error && error != EWOULDBLOCK)
1545 goto out;
1546 error = 0;
1547 goto loop;
1548 }
1549 read:
1550 splx(s);
1551
1552
1553
1554
1555 first = 1;
1556 while ((c = getc(qp)) >= 0) {
1557
1558
1559
1560 if (CCEQ(cc[VDSUSP], c) &&
1561 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1562 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1563 if (first) {
1564 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
1565 ttybg, 0);
1566 if (error)
1567 break;
1568 goto loop;
1569 }
1570 break;
1571 }
1572
1573
1574
1575 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1576 break;
1577
1578
1579
1580 error = ureadc(c, uio);
1581 if (error)
1582 break;
1583 if (uio->uio_resid == 0)
1584 break;
1585
1586
1587
1588
1589 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1590 break;
1591 first = 0;
1592 }
1593
1594
1595
1596
1597 s = spltty();
1598 if (tp->t_rawq.c_cc < TTYHOG/5)
1599 ttyunblock(tp);
1600 splx(s);
1601
1602 out:
1603 if (stime) {
1604 timeout_del(stime);
1605 free(stime, M_TEMP);
1606 }
1607 return (error);
1608 }
1609
1610
1611 void
1612 ttyunblock(struct tty *tp)
1613 {
1614 u_char *cc = tp->t_cc;
1615
1616 splassert(IPL_TTY);
1617
1618 if (ISSET(tp->t_state, TS_TBLOCK)) {
1619 if (ISSET(tp->t_iflag, IXOFF) &&
1620 cc[VSTART] != _POSIX_VDISABLE &&
1621 putc(cc[VSTART], &tp->t_outq) == 0) {
1622 CLR(tp->t_state, TS_TBLOCK);
1623 ttstart(tp);
1624 }
1625
1626 if (ISSET(tp->t_cflag, CHWFLOW) && tp->t_hwiflow &&
1627 (*tp->t_hwiflow)(tp, 0) != 0)
1628 CLR(tp->t_state, TS_TBLOCK);
1629 }
1630 }
1631
1632
1633
1634
1635
1636
1637
1638
1639 int
1640 ttycheckoutq(struct tty *tp, int wait)
1641 {
1642 int hiwat, s, oldsig;
1643
1644 hiwat = tp->t_hiwat;
1645 s = spltty();
1646 oldsig = wait ? curproc->p_siglist : 0;
1647 if (tp->t_outq.c_cc > hiwat + 200)
1648 while (tp->t_outq.c_cc > hiwat) {
1649 ttstart(tp);
1650 if (wait == 0 || curproc->p_siglist != oldsig) {
1651 splx(s);
1652 return (0);
1653 }
1654 SET(tp->t_state, TS_ASLEEP);
1655 tsleep(&tp->t_outq, PZERO - 1, "ttckoutq", hz);
1656 }
1657 splx(s);
1658 return (1);
1659 }
1660
1661
1662
1663
1664 int
1665 ttwrite(struct tty *tp, struct uio *uio, int flag)
1666 {
1667 u_char *cp = NULL;
1668 int cc, ce;
1669 struct proc *p;
1670 int i, hiwat, cnt, error, s;
1671 u_char obuf[OBUFSIZ];
1672
1673 hiwat = tp->t_hiwat;
1674 cnt = uio->uio_resid;
1675 error = 0;
1676 cc = 0;
1677 loop:
1678 s = spltty();
1679 if (!ISSET(tp->t_state, TS_CARR_ON) &&
1680 !ISSET(tp->t_cflag, CLOCAL)) {
1681 if (ISSET(tp->t_state, TS_ISOPEN)) {
1682 splx(s);
1683 return (EIO);
1684 } else if (flag & IO_NDELAY) {
1685 splx(s);
1686 error = EWOULDBLOCK;
1687 goto out;
1688 } else {
1689
1690 error = ttysleep(tp,
1691 &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
1692 splx(s);
1693 if (error)
1694 goto out;
1695 goto loop;
1696 }
1697 }
1698 splx(s);
1699
1700
1701
1702 p = curproc;
1703 if (isbackground(p, tp) &&
1704 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
1705 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
1706 (p->p_sigmask & sigmask(SIGTTOU)) == 0) {
1707 if (p->p_pgrp->pg_jobc == 0) {
1708 error = EIO;
1709 goto out;
1710 }
1711 pgsignal(p->p_pgrp, SIGTTOU, 1);
1712 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, ttybg, 0);
1713 if (error)
1714 goto out;
1715 goto loop;
1716 }
1717
1718
1719
1720
1721
1722 while (uio->uio_resid > 0 || cc > 0) {
1723 if (ISSET(tp->t_lflag, FLUSHO)) {
1724 uio->uio_resid = 0;
1725 return (0);
1726 }
1727 if (tp->t_outq.c_cc > hiwat)
1728 goto ovhiwat;
1729
1730
1731
1732
1733 if (cc == 0) {
1734 cc = min(uio->uio_resid, OBUFSIZ);
1735 cp = obuf;
1736 error = uiomove(cp, cc, uio);
1737 if (error) {
1738 cc = 0;
1739 break;
1740 }
1741 }
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751 while (cc > 0) {
1752 if (!ISSET(tp->t_oflag, OPOST))
1753 ce = cc;
1754 else {
1755 ce = cc - scanc((u_int)cc, cp, char_type,
1756 CCLASSMASK);
1757
1758
1759
1760
1761 if (ce == 0) {
1762 tp->t_rocount = 0;
1763 if (ttyoutput(*cp, tp) >= 0) {
1764
1765 goto overfull;
1766 }
1767 cp++;
1768 cc--;
1769 if (ISSET(tp->t_lflag, FLUSHO) ||
1770 tp->t_outq.c_cc > hiwat)
1771 goto ovhiwat;
1772 continue;
1773 }
1774 }
1775
1776
1777
1778
1779
1780
1781
1782
1783 tp->t_rocount = 0;
1784 i = b_to_q(cp, ce, &tp->t_outq);
1785 ce -= i;
1786 tp->t_column += ce;
1787 cp += ce, cc -= ce, tk_nout += ce;
1788 tp->t_outcc += ce;
1789 if (i > 0) {
1790
1791 goto overfull;
1792 }
1793 if (ISSET(tp->t_lflag, FLUSHO) ||
1794 tp->t_outq.c_cc > hiwat)
1795 break;
1796 }
1797 ttstart(tp);
1798 }
1799 out:
1800
1801
1802
1803
1804
1805 uio->uio_resid += cc;
1806 return (error);
1807
1808 overfull:
1809
1810
1811
1812
1813
1814
1815 hiwat = tp->t_outq.c_cc - 1;
1816
1817 ovhiwat:
1818 ttstart(tp);
1819 s = spltty();
1820
1821
1822
1823
1824 if (tp->t_outq.c_cc <= hiwat) {
1825 splx(s);
1826 goto loop;
1827 }
1828 if (flag & IO_NDELAY) {
1829 splx(s);
1830 uio->uio_resid += cc;
1831 return (uio->uio_resid == cnt ? EWOULDBLOCK : 0);
1832 }
1833 SET(tp->t_state, TS_ASLEEP);
1834 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
1835 splx(s);
1836 if (error)
1837 goto out;
1838 goto loop;
1839 }
1840
1841
1842
1843
1844
1845 void
1846 ttyrub(int c, struct tty *tp)
1847 {
1848 u_char *cp;
1849 int savecol;
1850 int tabc, s;
1851
1852 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
1853 return;
1854 CLR(tp->t_lflag, FLUSHO);
1855 if (ISSET(tp->t_lflag, ECHOE)) {
1856 if (tp->t_rocount == 0) {
1857
1858
1859
1860 ttyretype(tp);
1861 return;
1862 }
1863 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
1864 ttyrubo(tp, 2);
1865 else {
1866 CLR(c, ~TTY_CHARMASK);
1867 switch (CCLASS(c)) {
1868 case ORDINARY:
1869 ttyrubo(tp, 1);
1870 break;
1871 case BACKSPACE:
1872 case CONTROL:
1873 case NEWLINE:
1874 case RETURN:
1875 case VTAB:
1876 if (ISSET(tp->t_lflag, ECHOCTL))
1877 ttyrubo(tp, 2);
1878 break;
1879 case TAB:
1880 if (tp->t_rocount < tp->t_rawq.c_cc) {
1881 ttyretype(tp);
1882 return;
1883 }
1884 s = spltty();
1885 savecol = tp->t_column;
1886 SET(tp->t_state, TS_CNTTB);
1887 SET(tp->t_lflag, FLUSHO);
1888 tp->t_column = tp->t_rocol;
1889 for (cp = firstc(&tp->t_rawq, &tabc); cp;
1890 cp = nextc(&tp->t_rawq, cp, &tabc))
1891 ttyecho(tabc, tp);
1892 CLR(tp->t_lflag, FLUSHO);
1893 CLR(tp->t_state, TS_CNTTB);
1894 splx(s);
1895
1896
1897 savecol -= tp->t_column;
1898 tp->t_column += savecol;
1899 if (savecol > 8)
1900 savecol = 8;
1901 while (--savecol >= 0)
1902 (void)ttyoutput('\b', tp);
1903 break;
1904 default:
1905 #define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
1906 (void)printf(PANICSTR, c, CCLASS(c));
1907 #ifdef notdef
1908 panic(PANICSTR, c, CCLASS(c));
1909 #endif
1910 }
1911 }
1912 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
1913 if (!ISSET(tp->t_state, TS_ERASE)) {
1914 SET(tp->t_state, TS_ERASE);
1915 (void)ttyoutput('\\', tp);
1916 }
1917 ttyecho(c, tp);
1918 } else
1919 ttyecho(tp->t_cc[VERASE], tp);
1920 --tp->t_rocount;
1921 }
1922
1923
1924
1925
1926 static void
1927 ttyrubo(struct tty *tp, int cnt)
1928 {
1929
1930 while (cnt-- > 0) {
1931 (void)ttyoutput('\b', tp);
1932 (void)ttyoutput(' ', tp);
1933 (void)ttyoutput('\b', tp);
1934 }
1935 }
1936
1937
1938
1939
1940
1941
1942 void
1943 ttyretype(struct tty *tp)
1944 {
1945 u_char *cp;
1946 int s, c;
1947
1948
1949 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
1950 ttyecho(tp->t_cc[VREPRINT], tp);
1951
1952 (void)ttyoutput('\n', tp);
1953
1954 s = spltty();
1955 for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
1956 ttyecho(c, tp);
1957 for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
1958 ttyecho(c, tp);
1959 CLR(tp->t_state, TS_ERASE);
1960 splx(s);
1961
1962 tp->t_rocount = tp->t_rawq.c_cc;
1963 tp->t_rocol = 0;
1964 }
1965
1966
1967
1968
1969 static void
1970 ttyecho(int c, struct tty *tp)
1971 {
1972
1973 if (!ISSET(tp->t_state, TS_CNTTB))
1974 CLR(tp->t_lflag, FLUSHO);
1975 if ((!ISSET(tp->t_lflag, ECHO) &&
1976 (!ISSET(tp->t_lflag, ECHONL) || c != '\n')) ||
1977 ISSET(tp->t_lflag, EXTPROC))
1978 return;
1979 if (((ISSET(tp->t_lflag, ECHOCTL) &&
1980 (ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n')) ||
1981 ISSET(c, TTY_CHARMASK) == 0177)) {
1982 (void)ttyoutput('^', tp);
1983 CLR(c, ~TTY_CHARMASK);
1984 if (c == 0177)
1985 c = '?';
1986 else
1987 c += 'A' - 1;
1988 }
1989 (void)ttyoutput(c, tp);
1990 }
1991
1992
1993
1994
1995 void
1996 ttwakeup(struct tty *tp)
1997 {
1998
1999 selwakeup(&tp->t_rsel);
2000 if (ISSET(tp->t_state, TS_ASYNC))
2001 pgsignal(tp->t_pgrp, SIGIO, 1);
2002 wakeup((caddr_t)&tp->t_rawq);
2003 KNOTE(&tp->t_rsel.si_note, 0);
2004 }
2005
2006
2007
2008
2009
2010 int
2011 ttspeedtab(int speed, const struct speedtab *table)
2012 {
2013
2014 for ( ; table->sp_speed != -1; table++)
2015 if (table->sp_speed == speed)
2016 return (table->sp_code);
2017 return (-1);
2018 }
2019
2020
2021
2022
2023
2024
2025
2026 void
2027 ttsetwater(struct tty *tp)
2028 {
2029 int cps, x;
2030
2031 #define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2032
2033 cps = tp->t_ospeed / 10;
2034 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2035 x += cps;
2036 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2037 tp->t_hiwat = roundup(x, CBSIZE);
2038 #undef CLAMP
2039 }
2040
2041
2042
2043
2044 void
2045 ttyinfo(struct tty *tp)
2046 {
2047 struct proc *p, *pick;
2048 struct timeval utime, stime;
2049 int tmp;
2050
2051 if (ttycheckoutq(tp,0) == 0)
2052 return;
2053
2054
2055 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2056 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100);
2057
2058 if (tp->t_session == NULL)
2059 ttyprintf(tp, "not a controlling terminal\n");
2060 else if (tp->t_pgrp == NULL)
2061 ttyprintf(tp, "no foreground process group\n");
2062 else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == NULL)
2063 ttyprintf(tp, "empty foreground process group\n");
2064 else {
2065
2066 for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
2067 if (proc_compare(pick, p))
2068 pick = p;
2069
2070 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
2071 pick->p_stat == SONPROC ? "running" :
2072 pick->p_stat == SRUN ? "runnable" :
2073 pick->p_wmesg ? pick->p_wmesg : "iowait");
2074
2075 calcru(pick, &utime, &stime, NULL);
2076
2077
2078 utime.tv_usec += 5000;
2079 if (utime.tv_usec >= 1000000) {
2080 utime.tv_sec += 1;
2081 utime.tv_usec -= 1000000;
2082 }
2083 ttyprintf(tp, "%ld.%02ldu ", utime.tv_sec,
2084 utime.tv_usec / 10000);
2085
2086
2087 stime.tv_usec += 5000;
2088 if (stime.tv_usec >= 1000000) {
2089 stime.tv_sec += 1;
2090 stime.tv_usec -= 1000000;
2091 }
2092 ttyprintf(tp, "%ld.%02lds ", stime.tv_sec,
2093 stime.tv_usec / 10000);
2094
2095 #define pgtok(a) (((u_long) ((a) * PAGE_SIZE) / 1024))
2096
2097 tmp = (pick->p_pctcpu * 10000 + FSCALE / 2) >> FSHIFT;
2098 ttyprintf(tp, "%d%% %ldk\n",
2099 tmp / 100,
2100 pick->p_stat == SIDL || P_ZOMBIE(pick) ? 0 :
2101 vm_resident_count(pick->p_vmspace));
2102 }
2103 tp->t_rocount = 0;
2104 }
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119 #define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL) || \
2120 ((p)->p_stat == SONPROC))
2121 #define TESTAB(a, b) ((a)<<1 | (b))
2122 #define ONLYA 2
2123 #define ONLYB 1
2124 #define BOTH 3
2125
2126 static int
2127 proc_compare(struct proc *p1, struct proc *p2)
2128 {
2129
2130 if (p1 == NULL)
2131 return (1);
2132
2133
2134
2135 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2136 case ONLYA:
2137 return (0);
2138 case ONLYB:
2139 return (1);
2140 case BOTH:
2141
2142
2143
2144 if (p2->p_estcpu > p1->p_estcpu)
2145 return (1);
2146 if (p1->p_estcpu > p2->p_estcpu)
2147 return (0);
2148 return (p2->p_pid > p1->p_pid);
2149 }
2150
2151
2152
2153 switch (TESTAB(P_ZOMBIE(p1), P_ZOMBIE(p2))) {
2154 case ONLYA:
2155 return (1);
2156 case ONLYB:
2157 return (0);
2158 case BOTH:
2159 return (p2->p_pid > p1->p_pid);
2160 }
2161
2162
2163
2164 if (p2->p_slptime > p1->p_slptime)
2165 return (0);
2166 if (p1->p_slptime > p2->p_slptime)
2167 return (1);
2168
2169
2170
2171 if (p1->p_flag & P_SINTR && (p2->p_flag & P_SINTR) == 0)
2172 return (1);
2173 if (p2->p_flag & P_SINTR && (p1->p_flag & P_SINTR) == 0)
2174 return (0);
2175 return (p2->p_pid > p1->p_pid);
2176 }
2177
2178
2179
2180
2181 int
2182 tputchar(int c, struct tty *tp)
2183 {
2184 int s;
2185
2186 s = spltty();
2187 if (ISSET(tp->t_state,
2188 TS_CARR_ON | TS_ISOPEN) != (TS_CARR_ON | TS_ISOPEN)) {
2189 splx(s);
2190 return (-1);
2191 }
2192 if (c == '\n')
2193 (void)ttyoutput('\r', tp);
2194 (void)ttyoutput(c, tp);
2195 ttstart(tp);
2196 splx(s);
2197 return (0);
2198 }
2199
2200
2201
2202
2203
2204
2205
2206 int
2207 ttysleep(struct tty *tp, void *chan, int pri, char *wmesg, int timo)
2208 {
2209 int error;
2210 short gen;
2211
2212 gen = tp->t_gen;
2213 if ((error = tsleep(chan, pri, wmesg, timo)) != 0)
2214 return (error);
2215 return (tp->t_gen == gen ? 0 : ERESTART);
2216 }
2217
2218
2219
2220
2221 void
2222 tty_init(void)
2223 {
2224
2225 TAILQ_INIT(&ttylist);
2226 tty_count = 0;
2227 }
2228
2229
2230
2231
2232
2233 struct tty *
2234 ttymalloc(void)
2235 {
2236 struct tty *tp;
2237
2238 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK);
2239 bzero(tp, sizeof *tp);
2240
2241 clalloc(&tp->t_rawq, 1024, 1);
2242 clalloc(&tp->t_canq, 1024, 1);
2243
2244 clalloc(&tp->t_outq, 1024, 0);
2245
2246 TAILQ_INSERT_TAIL(&ttylist, tp, tty_link);
2247 ++tty_count;
2248 timeout_set(&tp->t_rstrt_to, ttrstrt, tp);
2249
2250 return(tp);
2251 }
2252
2253
2254
2255
2256
2257 void
2258 ttyfree(struct tty *tp)
2259 {
2260
2261 --tty_count;
2262 #ifdef DIAGNOSTIC
2263 if (tty_count < 0)
2264 panic("ttyfree: tty_count < 0");
2265 #endif
2266 TAILQ_REMOVE(&ttylist, tp, tty_link);
2267
2268 clfree(&tp->t_rawq);
2269 clfree(&tp->t_canq);
2270 clfree(&tp->t_outq);
2271 FREE(tp, M_TTYS);
2272 }
2273
2274 struct itty *ttystats;
2275
2276 int
2277 ttystats_init(void)
2278 {
2279 struct itty *itp;
2280 struct tty *tp;
2281
2282 ttystats = malloc(tty_count * sizeof(struct itty),
2283 M_SYSCTL, M_WAITOK);
2284 for (tp = TAILQ_FIRST(&ttylist), itp = ttystats; tp;
2285 tp = TAILQ_NEXT(tp, tty_link), itp++) {
2286 itp->t_dev = tp->t_dev;
2287 itp->t_rawq_c_cc = tp->t_rawq.c_cc;
2288 itp->t_canq_c_cc = tp->t_canq.c_cc;
2289 itp->t_outq_c_cc = tp->t_outq.c_cc;
2290 itp->t_hiwat = tp->t_hiwat;
2291 itp->t_lowat = tp->t_lowat;
2292 itp->t_column = tp->t_column;
2293 itp->t_state = tp->t_state;
2294 itp->t_session = tp->t_session;
2295 if (tp->t_pgrp)
2296 itp->t_pgrp_pg_id = tp->t_pgrp->pg_id;
2297 else
2298 itp->t_pgrp_pg_id = 0;
2299 itp->t_line = tp->t_line;
2300 }
2301 return (0);
2302 }
2303
2304
2305
2306
2307 int
2308 sysctl_tty(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
2309 size_t newlen)
2310 {
2311 int err;
2312
2313 if (namelen != 1)
2314 return (ENOTDIR);
2315
2316 switch (name[0]) {
2317 case KERN_TTY_TKNIN:
2318 return (sysctl_rdquad(oldp, oldlenp, newp, tk_nin));
2319 case KERN_TTY_TKNOUT:
2320 return (sysctl_rdquad(oldp, oldlenp, newp, tk_nout));
2321 case KERN_TTY_TKRAWCC:
2322 return (sysctl_rdquad(oldp, oldlenp, newp, tk_rawcc));
2323 case KERN_TTY_TKCANCC:
2324 return (sysctl_rdquad(oldp, oldlenp, newp, tk_cancc));
2325 case KERN_TTY_INFO:
2326 err = ttystats_init();
2327 if (err)
2328 return (err);
2329 err = sysctl_rdstruct(oldp, oldlenp, newp, ttystats,
2330 tty_count * sizeof(struct itty));
2331 free(ttystats, M_SYSCTL);
2332 return (err);
2333 default:
2334 #if NPTY > 0
2335 return (sysctl_pty(name, namelen, oldp, oldlenp, newp, newlen));
2336 #else
2337 return (EOPNOTSUPP);
2338 #endif
2339 }
2340
2341 }
2342
2343 void
2344 ttytstamp(struct tty *tp, int octs, int ncts, int odcd, int ndcd)
2345 {
2346 int doit = 0;
2347
2348 if (ncts ^ octs)
2349 doit |= ncts ? ISSET(tp->t_flags, TS_TSTAMPCTSSET) :
2350 ISSET(tp->t_flags, TS_TSTAMPCTSCLR);
2351 if (ndcd ^ odcd)
2352 doit |= ndcd ? ISSET(tp->t_flags, TS_TSTAMPDCDSET) :
2353 ISSET(tp->t_flags, TS_TSTAMPDCDCLR);
2354
2355 if (doit)
2356 microtime(&tp->t_tv);
2357 }