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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89#ifdef NeXT
90#define NSNP 0
91#else
92#include "snp.h"
93#include "opt_uconsole.h"
94#endif
95
96#include <sys/param.h>
97#define TTYDEFCHARS 1
98#include <sys/systm.h>
99#undef TTYDEFCHARS
100#include <sys/ioctl.h>
101#include <sys/proc_internal.h>
102#include <sys/kauth.h>
103#include <sys/file_internal.h>
104#include <sys/conf.h>
105#include <sys/dkstat.h>
106#include <sys/uio.h>
107#include <sys/kernel.h>
108#include <sys/vnode.h>
109#include <sys/syslog.h>
110#include <sys/user.h>
111#include <sys/signalvar.h>
112#include <sys/signalvar.h>
113#ifndef NeXT
114#include <sys/resourcevar.h>
115#endif
116#include <sys/malloc.h>
117#if NSNP > 0
118#include <sys/snoop.h>
119#endif
120
121#ifndef NeXT
122#include <vm/vm.h>
123#include <vm/vm_param.h>
124#include <vm/vm_prot.h>
125#include <vm/lock.h>
126#include <vm/pmap.h>
127#include <vm/vm_map.h>
128#else
129#include <dev/kmreg_com.h>
130#include <machine/cons.h>
131#include <machine/spl.h>
132#if 0
133#include <machdep/machine/pmap.h>
134#endif
135#endif
136#include <sys/resource.h>
137
138#ifndef NeXT
139static int proc_compare(struct proc *p1, struct proc *p2);
140#endif
141static int ttnread(struct tty *tp);
142static void ttyecho(int c, struct tty *tp);
143static int ttyoutput(int c, register struct tty *tp);
144static void ttypend(struct tty *tp);
145static void ttyretype(struct tty *tp);
146static void ttyrub(int c, struct tty *tp);
147static void ttyrubo(struct tty *tp, int count);
148static void ttystop(struct tty *tp, int rw);
149static void ttyunblock(struct tty *tp);
150static int ttywflush(struct tty *tp);
151static int proc_compare(struct proc *p1, struct proc *p2);
152
153
154
155
156
157
158
159
160#define E 0x00
161#define O 0x80
162#define PARITY(c) (char_type[c] & O)
163
164#define ALPHA 0x40
165#define ISALPHA(c) (char_type[(c) & TTY_CHARMASK] & ALPHA)
166
167#define CCLASSMASK 0x3f
168#define CCLASS(c) (char_type[c] & CCLASSMASK)
169
170#define BS BACKSPACE
171#define CC CONTROL
172#define CR RETURN
173#define NA ORDINARY | ALPHA
174#define NL NEWLINE
175#define NO ORDINARY
176#define TB TAB
177#define VT VTAB
178
179static u_char const char_type[] = {
180 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,
181 O|BS, E|TB, E|NL, O|CC, E|VT, O|CR, O|CC, E|CC,
182 O|CC, E|CC, E|CC, O|CC, E|CC, O|CC, O|CC, E|CC,
183 E|CC, O|CC, O|CC, E|CC, O|CC, E|CC, E|CC, O|CC,
184 O|NO, E|NO, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,
185 E|NO, O|NO, O|NO, E|NO, O|NO, E|NO, E|NO, O|NO,
186 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
187 O|NA, E|NA, E|NO, O|NO, E|NO, O|NO, O|NO, E|NO,
188 O|NO, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
189 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
190 E|NA, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
191 O|NA, E|NA, E|NA, O|NO, E|NO, O|NO, O|NO, O|NA,
192 E|NO, O|NA, O|NA, E|NA, O|NA, E|NA, E|NA, O|NA,
193 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
194 O|NA, E|NA, E|NA, O|NA, E|NA, O|NA, O|NA, E|NA,
195 E|NA, O|NA, O|NA, E|NO, O|NO, E|NO, E|NO, O|CC,
196
197
198
199
200 NA, NA, NA, NA, NA, NA, NA, NA,
201 NA, NA, NA, NA, NA, NA, NA, NA,
202 NA, NA, NA, NA, NA, NA, NA, NA,
203 NA, NA, NA, NA, NA, NA, NA, NA,
204 NA, NA, NA, NA, NA, NA, NA, NA,
205 NA, NA, NA, NA, NA, NA, NA, NA,
206 NA, NA, NA, NA, NA, NA, NA, NA,
207 NA, NA, NA, NA, NA, NA, NA, NA,
208 NA, NA, NA, NA, NA, NA, NA, NA,
209 NA, NA, NA, NA, NA, NA, NA, NA,
210 NA, NA, NA, NA, NA, NA, NA, NA,
211 NA, NA, NA, NA, NA, NA, NA, NA,
212 NA, NA, NA, NA, NA, NA, NA, NA,
213 NA, NA, NA, NA, NA, NA, NA, NA,
214 NA, NA, NA, NA, NA, NA, NA, NA,
215 NA, NA, NA, NA, NA, NA, NA, NA,
216};
217#undef BS
218#undef CC
219#undef CR
220#undef NA
221#undef NL
222#undef NO
223#undef TB
224#undef VT
225
226
227#define SET(t, f) (t) |= (f)
228#define CLR(t, f) (t) &= ~(f)
229#define ISSET(t, f) ((t) & (f))
230
231
232
233
234
235
236#define I_HIGH_WATER (TTYHOG - 2 * 256)
237#define I_LOW_WATER ((TTYHOG - 2 * 256) * 7 / 8)
238
239#undef MAX_INPUT
240#define MAX_INPUT TTYHOG
241
242static void
243termios32to64(struct termios *in, struct user_termios *out)
244{
245 out->c_iflag = (user_tcflag_t)in->c_iflag;
246 out->c_oflag = (user_tcflag_t)in->c_oflag;
247 out->c_cflag = (user_tcflag_t)in->c_cflag;
248 out->c_lflag = (user_tcflag_t)in->c_lflag;
249
250
251 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
252
253 out->c_ispeed = (user_speed_t)in->c_ispeed;
254 out->c_ospeed = (user_speed_t)in->c_ospeed;
255}
256
257static void
258termios64to32(struct user_termios *in, struct termios *out)
259{
260 out->c_iflag = (tcflag_t)in->c_iflag;
261 out->c_oflag = (tcflag_t)in->c_oflag;
262 out->c_cflag = (tcflag_t)in->c_cflag;
263 out->c_lflag = (tcflag_t)in->c_lflag;
264
265
266 bcopy(in->c_cc, out->c_cc, sizeof(in->c_cc));
267
268 out->c_ispeed = (speed_t)in->c_ispeed;
269 out->c_ospeed = (speed_t)in->c_ospeed;
270}
271
272
273
274
275
276int
277ttyopen(device, tp)
278 dev_t device;
279 register struct tty *tp;
280{
281 int s;
282 boolean_t funnel_state;
283
284 funnel_state = thread_funnel_set(kernel_flock, TRUE);
285 s = spltty();
286 tp->t_dev = device;
287 if (!ISSET(tp->t_state, TS_ISOPEN)) {
288 SET(tp->t_state, TS_ISOPEN);
289 if (ISSET(tp->t_cflag, CLOCAL)) {
290 SET(tp->t_state, TS_CONNECTED); }
291 bzero(&tp->t_winsize, sizeof(tp->t_winsize));
292 }
293
294#ifndef NeXT
295
296
297
298
299 clist_alloc_cblocks(&tp->t_canq, TTYHOG, 512);
300 clist_alloc_cblocks(&tp->t_outq, TTMAXHIWAT + OBUFSIZ + 100,
301 TTMAXHIWAT + OBUFSIZ + 100);
302 clist_alloc_cblocks(&tp->t_rawq, TTYHOG, TTYHOG);
303#endif
304
305 splx(s);
306 thread_funnel_set(kernel_flock, funnel_state);
307 return (0);
308}
309
310
311
312
313
314
315
316
317
318int
319ttyclose(tp)
320 register struct tty *tp;
321{
322 int s;
323
324 s = spltty();
325 if (constty == tp) {
326 constty = NULL;
327
328splx(s);
329spltty();
330
331#ifdef NeXT
332
333
334
335
336 (*cdevsw[major(tp->t_dev)].d_ioctl)
337 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
338#endif
339 }
340
341 ttyflush(tp, FREAD | FWRITE);
342#ifndef NeXT
343 clist_free_cblocks(&tp->t_canq);
344 clist_free_cblocks(&tp->t_outq);
345 clist_free_cblocks(&tp->t_rawq);
346#endif
347
348#if NSNP > 0
349 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
350 snpdown((struct snoop *)tp->t_sc);
351#endif
352
353 tp->t_gen++;
354 tp->t_line = TTYDISC;
355 tp->t_pgrp = NULL;
356 tp->t_session = NULL;
357 tp->t_state = 0;
358#if NeXT
359 selthreadclear(&tp->t_wsel);
360 selthreadclear(&tp->t_rsel);
361#endif
362 splx(s);
363 return (0);
364}
365
366#define FLUSHQ(q) { \
367 if ((q)->c_cc) \
368 ndflush(q, (q)->c_cc); \
369}
370
371
372#define TTBREAKC(c, lflag) \
373 ((c) == '\n' || (((c) == cc[VEOF] || \
374 (c) == cc[VEOL] || ((c) == cc[VEOL2] && lflag & IEXTEN)) && \
375 (c) != _POSIX_VDISABLE))
376
377
378
379
380int
381ttyinput(c, tp)
382 register int c;
383 register struct tty *tp;
384{
385 register tcflag_t iflag, lflag;
386 register cc_t *cc;
387 int i, err, retval;
388 boolean_t funnel_state;
389
390 funnel_state = thread_funnel_set(kernel_flock, TRUE);
391
392
393
394
395 lflag = tp->t_lflag;
396 if (ISSET(lflag, PENDIN))
397 ttypend(tp);
398
399
400
401 if (ISSET(lflag, ICANON)) {
402 ++tk_cancc;
403 ++tp->t_cancc;
404 } else {
405 ++tk_rawcc;
406 ++tp->t_rawcc;
407 }
408 ++tk_nin;
409
410
411
412
413
414
415
416 iflag = tp->t_iflag;
417 if (tp->t_rawq.c_cc + tp->t_canq.c_cc > I_HIGH_WATER - 3 &&
418 (!ISSET(lflag, ICANON) || tp->t_canq.c_cc != 0) &&
419 (ISSET(tp->t_cflag, CRTS_IFLOW) || ISSET(iflag, IXOFF)) &&
420 !ISSET(tp->t_state, TS_TBLOCK))
421 ttyblock(tp);
422
423
424 cc = tp->t_cc;
425 err = (ISSET(c, TTY_ERRORMASK));
426 if (err) {
427 CLR(c, TTY_ERRORMASK);
428 if (ISSET(err, TTY_BI)) {
429 if (ISSET(iflag, IGNBRK)) {
430 thread_funnel_set(kernel_flock, funnel_state);
431 return (0);
432 }
433 if (ISSET(iflag, BRKINT)) {
434 ttyflush(tp, FREAD | FWRITE);
435 pgsignal(tp->t_pgrp, SIGINT, 1);
436 goto endcase;
437 }
438 if (ISSET(iflag, PARMRK))
439 goto parmrk;
440 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK))
441 || ISSET(err, TTY_FE)) {
442 if (ISSET(iflag, IGNPAR)) {
443 thread_funnel_set(kernel_flock, funnel_state);
444 return (0);
445 }
446 else if (ISSET(iflag, PARMRK)) {
447parmrk:
448 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >
449 MAX_INPUT - 3)
450 goto input_overflow;
451 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
452 (void)putc(0 | TTY_QUOTE, &tp->t_rawq);
453 (void)putc(c | TTY_QUOTE, &tp->t_rawq);
454 goto endcase;
455 } else
456 c = 0;
457 }
458 }
459
460 if (!ISSET(tp->t_state, TS_TYPEN) && ISSET(iflag, ISTRIP))
461 CLR(c, 0x80);
462 if (!ISSET(lflag, EXTPROC)) {
463
464
465
466 if (ISSET(tp->t_state, TS_LNCH)) {
467 SET(c, TTY_QUOTE);
468 CLR(tp->t_state, TS_LNCH);
469 }
470
471
472
473
474
475
476
477
478
479
480
481
482 if (ISSET(lflag, IEXTEN)) {
483 if (CCEQ(cc[VLNEXT], c)) {
484 if (ISSET(lflag, ECHO)) {
485 if (ISSET(lflag, ECHOE)) {
486 (void)ttyoutput('^', tp);
487 (void)ttyoutput('\b', tp);
488 } else
489 ttyecho(c, tp);
490 }
491 SET(tp->t_state, TS_LNCH);
492 goto endcase;
493 }
494 if (CCEQ(cc[VDISCARD], c)) {
495 if (ISSET(lflag, FLUSHO))
496 CLR(tp->t_lflag, FLUSHO);
497 else {
498 ttyflush(tp, FWRITE);
499 ttyecho(c, tp);
500 if (tp->t_rawq.c_cc + tp->t_canq.c_cc)
501 ttyretype(tp);
502 SET(tp->t_lflag, FLUSHO);
503 }
504 goto startoutput;
505 }
506 }
507
508
509
510 if (ISSET(lflag, ISIG)) {
511 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) {
512 if (!ISSET(lflag, NOFLSH))
513 ttyflush(tp, FREAD | FWRITE);
514 ttyecho(c, tp);
515 pgsignal(tp->t_pgrp,
516 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
517 goto endcase;
518 }
519 if (CCEQ(cc[VSUSP], c)) {
520 if (!ISSET(lflag, NOFLSH))
521 ttyflush(tp, FREAD);
522 ttyecho(c, tp);
523 pgsignal(tp->t_pgrp, SIGTSTP, 1);
524 goto endcase;
525 }
526 }
527
528
529
530 if (ISSET(iflag, IXON)) {
531 if (CCEQ(cc[VSTOP], c)) {
532 if (!ISSET(tp->t_state, TS_TTSTOP)) {
533 SET(tp->t_state, TS_TTSTOP);
534 ttystop(tp, 0);
535 thread_funnel_set(kernel_flock, funnel_state);
536 return (0);
537 }
538 if (!CCEQ(cc[VSTART], c)) {
539 thread_funnel_set(kernel_flock, funnel_state);
540 return (0);
541 }
542
543
544
545 goto endcase;
546 }
547 if (CCEQ(cc[VSTART], c))
548 goto restartoutput;
549 }
550
551
552
553 if (c == '\r') {
554 if (ISSET(iflag, IGNCR)) {
555 thread_funnel_set(kernel_flock, funnel_state);
556 return (0);
557 }
558 else if (ISSET(iflag, ICRNL))
559 c = '\n';
560 } else if (c == '\n' && ISSET(iflag, INLCR))
561 c = '\r';
562 }
563 if (!ISSET(tp->t_lflag, EXTPROC) && ISSET(lflag, ICANON)) {
564
565
566
567
568
569
570
571 if (CCEQ(cc[VERASE], c)) {
572 if (tp->t_rawq.c_cc)
573 ttyrub(unputc(&tp->t_rawq), tp);
574 goto endcase;
575 }
576
577
578
579 if (CCEQ(cc[VKILL], c)) {
580 if (ISSET(lflag, ECHOKE) &&
581 tp->t_rawq.c_cc == tp->t_rocount &&
582 !ISSET(lflag, ECHOPRT))
583 while (tp->t_rawq.c_cc)
584 ttyrub(unputc(&tp->t_rawq), tp);
585 else {
586 ttyecho(c, tp);
587 if (ISSET(lflag, ECHOK) ||
588 ISSET(lflag, ECHOKE))
589 ttyecho('\n', tp);
590 FLUSHQ(&tp->t_rawq);
591 tp->t_rocount = 0;
592 }
593 CLR(tp->t_state, TS_LOCAL);
594 goto endcase;
595 }
596
597
598
599 if (CCEQ(cc[VWERASE], c) && ISSET(lflag, IEXTEN)) {
600 int ctype;
601
602
603
604
605 while ((c = unputc(&tp->t_rawq)) == ' ' || c == '\t')
606 ttyrub(c, tp);
607 if (c == -1)
608 goto endcase;
609
610
611
612
613 ttyrub(c, tp);
614 c = unputc(&tp->t_rawq);
615 if (c == -1)
616 goto endcase;
617 if (c == ' ' || c == '\t') {
618 (void)putc(c, &tp->t_rawq);
619 goto endcase;
620 }
621 ctype = ISALPHA(c);
622
623
624
625 do {
626 ttyrub(c, tp);
627 c = unputc(&tp->t_rawq);
628 if (c == -1)
629 goto endcase;
630 } while (c != ' ' && c != '\t' &&
631 (!ISSET(lflag, ALTWERASE) || ISALPHA(c) == ctype));
632 (void)putc(c, &tp->t_rawq);
633 goto endcase;
634 }
635
636
637
638 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) {
639 ttyretype(tp);
640 goto endcase;
641 }
642
643
644
645 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
646 if (ISSET(lflag, ISIG))
647 pgsignal(tp->t_pgrp, SIGINFO, 1);
648 if (!ISSET(lflag, NOKERNINFO))
649 ttyinfo(tp);
650 goto endcase;
651 }
652 }
653
654
655
656 if (tp->t_rawq.c_cc + tp->t_canq.c_cc >= MAX_INPUT) {
657input_overflow:
658 if (ISSET(iflag, IMAXBEL)) {
659 if (tp->t_outq.c_cc < tp->t_hiwat)
660 (void)ttyoutput(CTRL('g'), tp);
661 }
662 goto endcase;
663 }
664
665 if ( c == 0377 && ISSET(iflag, PARMRK) && !ISSET(iflag, ISTRIP)
666 && ISSET(iflag, IGNBRK|IGNPAR) != (IGNBRK|IGNPAR))
667 (void)putc(0377 | TTY_QUOTE, &tp->t_rawq);
668
669
670
671
672
673 if (putc(c, &tp->t_rawq) >= 0) {
674 if (!ISSET(lflag, ICANON)) {
675 ttwakeup(tp);
676 ttyecho(c, tp);
677 goto endcase;
678 }
679 if (TTBREAKC(c, lflag)) {
680 tp->t_rocount = 0;
681 catq(&tp->t_rawq, &tp->t_canq);
682 ttwakeup(tp);
683 } else if (tp->t_rocount++ == 0)
684 tp->t_rocol = tp->t_column;
685 if (ISSET(tp->t_state, TS_ERASE)) {
686
687
688
689 CLR(tp->t_state, TS_ERASE);
690 (void)ttyoutput('/', tp);
691 }
692 i = tp->t_column;
693 ttyecho(c, tp);
694 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ECHO)) {
695
696
697
698 i = min(2, tp->t_column - i);
699 while (i > 0) {
700 (void)ttyoutput('\b', tp);
701 i--;
702 }
703 }
704 }
705endcase:
706
707
708
709 if (ISSET(tp->t_state, TS_TTSTOP) &&
710 !ISSET(iflag, IXANY) && cc[VSTART] != cc[VSTOP]) {
711 thread_funnel_set(kernel_flock, funnel_state);
712 return (0);
713 }
714restartoutput:
715 CLR(tp->t_lflag, FLUSHO);
716 CLR(tp->t_state, TS_TTSTOP);
717startoutput:
718 retval = ttstart(tp);
719 thread_funnel_set(kernel_flock, funnel_state);
720 return (retval);
721}
722
723
724
725
726
727
728
729static int
730ttyoutput(c, tp)
731 register int c;
732 register struct tty *tp;
733{
734 register tcflag_t oflag;
735 register int col, s;
736
737 oflag = tp->t_oflag;
738 if (!ISSET(oflag, OPOST)) {
739 if (ISSET(tp->t_lflag, FLUSHO))
740 return (-1);
741 if (putc(c, &tp->t_outq))
742 return (c);
743 tk_nout++;
744 tp->t_outcc++;
745 return (-1);
746 }
747
748
749
750
751
752
753 CLR(c, ~TTY_CHARMASK);
754 if (c == '\t' &&
755 ISSET(oflag, OXTABS) && !ISSET(tp->t_lflag, EXTPROC)) {
756 c = 8 - (tp->t_column & 7);
757 if (!ISSET(tp->t_lflag, FLUSHO)) {
758 s = spltty();
759 c -= b_to_q(" ", c, &tp->t_outq);
760 tk_nout += c;
761 tp->t_outcc += c;
762 splx(s);
763 }
764 tp->t_column += c;
765 return (c ? -1 : '\t');
766 }
767 if (c == CEOT && ISSET(oflag, ONOEOT))
768 return (-1);
769
770
771
772
773
774 if (c == '\n' && ISSET(tp->t_oflag, ONLCR)) {
775 tk_nout++;
776 tp->t_outcc++;
777 if (putc('\r', &tp->t_outq))
778 return (c);
779 }
780 tk_nout++;
781 tp->t_outcc++;
782 if (!ISSET(tp->t_lflag, FLUSHO) && putc(c, &tp->t_outq))
783 return (c);
784
785 col = tp->t_column;
786 switch (CCLASS(c)) {
787 case BACKSPACE:
788 if (col > 0)
789 --col;
790 break;
791 case CONTROL:
792 break;
793 case NEWLINE:
794 case RETURN:
795 col = 0;
796 break;
797 case ORDINARY:
798 ++col;
799 break;
800 case TAB:
801 col = (col + 8) & ~7;
802 break;
803 }
804 tp->t_column = col;
805 return (-1);
806}
807
808
809
810
811
812
813
814int
815ttioctl(register struct tty *tp,
816 u_long cmd, caddr_t data, int flag,
817 struct proc *p)
818{
819 int s, error;
820 struct uthread *ut;
821
822 ut = (struct uthread *)get_bsdthread_info(current_thread());
823
824 switch (cmd) {
825 case TIOCFLUSH:
826 case TIOCSETA:
827 case TIOCSETA_64:
828 case TIOCSETD:
829 case TIOCSETAF:
830 case TIOCSETAF_64:
831 case TIOCSETAW:
832 case TIOCSETAW_64:
833#ifdef notdef
834 case TIOCSPGRP:
835#endif
836 case TIOCSTAT:
837 case TIOCSTI:
838 case TIOCSWINSZ:
839#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
840 case TIOCLBIC:
841 case TIOCLBIS:
842 case TIOCLSET:
843 case TIOCSETC:
844 case OTIOCSETD:
845 case TIOCSETN:
846 case TIOCSETP:
847 case TIOCSLTC:
848#endif
849 while (isbackground(p, tp) &&
850 (p->p_flag & P_PPWAIT) == 0 &&
851 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
852 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
853 if (p->p_pgrp->pg_jobc == 0)
854 return (EIO);
855 pgsignal(p->p_pgrp, SIGTTOU, 1);
856 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH | PTTYBLOCK, "ttybg1",
857 0);
858 if (error)
859 return (error);
860 }
861 break;
862 }
863
864 switch (cmd) {
865 case FIOASYNC:
866 s = spltty();
867 if (*(int *)data)
868 SET(tp->t_state, TS_ASYNC);
869 else
870 CLR(tp->t_state, TS_ASYNC);
871 splx(s);
872 break;
873 case FIONBIO:
874 break;
875 case FIONREAD:
876 s = spltty();
877 *(int *)data = ttnread(tp);
878 splx(s);
879 break;
880 case TIOCEXCL:
881 s = spltty();
882 SET(tp->t_state, TS_XCLUDE);
883 splx(s);
884 break;
885 case TIOCFLUSH: {
886 register int flags = *(int *)data;
887
888 if (flags == 0)
889 flags = FREAD | FWRITE;
890 else
891 flags &= FREAD | FWRITE;
892 ttyflush(tp, flags);
893 break;
894 }
895#ifdef NeXT
896 case TIOCSCONS: {
897
898 int bogusData = 1;
899 data = (caddr_t) &bogusData;
900
901
902 }
903#endif
904 case TIOCCONS: {
905 if (*(int *)data) {
906 if (constty && constty != tp &&
907 ISSET(constty->t_state, TS_CONNECTED)) {
908 return (EBUSY);
909 }
910#if defined(NeXT) || !defined(UCONSOLE)
911 if ( (error = suser(kauth_cred_get(), &p->p_acflag)) )
912 return (error);
913#endif
914 constty = tp;
915 } else if (tp == constty) {
916 constty = NULL;
917 }
918#ifdef NeXT
919 if (constty) {
920 (*cdevsw[major(cons.t_dev)].d_ioctl)
921 (cons.t_dev, KMIOCDISABLCONS, NULL, 0, p);
922 } else {
923 (*cdevsw[major(tp->t_dev)].d_ioctl)
924 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, p);
925 }
926#endif
927 break;
928 }
929 case TIOCDRAIN:
930 error = ttywait(tp);
931 if (error)
932 return (error);
933 break;
934 case TIOCGETA:
935 case TIOCGETA_64: {
936 if (IS_64BIT_PROCESS(p)) {
937 termios32to64(&tp->t_termios, (struct user_termios *)data);
938 } else {
939 bcopy(&tp->t_termios, data, sizeof(struct termios));
940 }
941 break;
942 }
943 case TIOCGETD:
944 *(int *)data = tp->t_line;
945 break;
946 case TIOCGWINSZ:
947 *(struct winsize *)data = tp->t_winsize;
948 break;
949 case TIOCGPGRP:
950 if (!isctty(p, tp))
951 return (ENOTTY);
952 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
953 break;
954#ifdef TIOCHPCL
955 case TIOCHPCL:
956 s = spltty();
957 SET(tp->t_cflag, HUPCL);
958 splx(s);
959 break;
960#endif
961 case TIOCNXCL:
962 s = spltty();
963 CLR(tp->t_state, TS_XCLUDE);
964 splx(s);
965 break;
966 case TIOCOUTQ:
967 *(int *)data = tp->t_outq.c_cc;
968 break;
969 case TIOCSETA:
970 case TIOCSETA_64:
971 case TIOCSETAW:
972 case TIOCSETAW_64:
973 case TIOCSETAF:
974 case TIOCSETAF_64: {
975 register struct termios *t = (struct termios *)data;
976 struct termios lcl_termios;
977
978 if (IS_64BIT_PROCESS(p)) {
979 termios64to32((struct user_termios *)data, &lcl_termios);
980 t = &lcl_termios;
981 }
982 if (t->c_ispeed < 0 || t->c_ospeed < 0)
983 return (EINVAL);
984 s = spltty();
985 if (cmd == TIOCSETAW || cmd == TIOCSETAF ||
986 cmd == TIOCSETAW_64 || cmd == TIOCSETAF_64) {
987 error = ttywait(tp);
988 if (error) {
989 splx(s);
990 return (error);
991 }
992 if (cmd == TIOCSETAF || cmd == TIOCSETAF_64)
993 ttyflush(tp, FREAD);
994 }
995 if (!ISSET(t->c_cflag, CIGNORE)) {
996
997
998
999 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
1000 splx(s);
1001 return (error);
1002 }
1003 if (ISSET(t->c_cflag, CLOCAL) &&
1004 !ISSET(tp->t_cflag, CLOCAL)) {
1005
1006
1007
1008
1009
1010
1011 CLR(tp->t_state, TS_ZOMBIE);
1012
1013 wakeup(TSA_CARR_ON(tp));
1014 ttwakeup(tp);
1015 ttwwakeup(tp);
1016 }
1017 if ((ISSET(tp->t_state, TS_CARR_ON) ||
1018 ISSET(t->c_cflag, CLOCAL)) &&
1019 !ISSET(tp->t_state, TS_ZOMBIE))
1020 SET(tp->t_state, TS_CONNECTED);
1021 else
1022 CLR(tp->t_state, TS_CONNECTED);
1023 tp->t_cflag = t->c_cflag;
1024 tp->t_ispeed = t->c_ispeed;
1025 tp->t_ospeed = t->c_ospeed;
1026 ttsetwater(tp);
1027 }
1028 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
1029 cmd != TIOCSETAF && cmd != TIOCSETAF_64) {
1030 if (ISSET(t->c_lflag, ICANON))
1031 SET(tp->t_lflag, PENDIN);
1032 else {
1033
1034
1035
1036
1037
1038
1039#ifndef NeXT
1040 if (tp->t_canq.c_cbreserved > 0 &&
1041 tp->t_rawq.c_cbreserved > 0) {
1042 catq(&tp->t_rawq, &tp->t_canq);
1043
1044
1045
1046
1047
1048 catq(&tp->t_canq, &tp->t_rawq);
1049 }
1050#else
1051 if (tp->t_rawq.c_cs && tp->t_canq.c_cs) {
1052 struct clist tq;
1053
1054 catq(&tp->t_rawq, &tp->t_canq);
1055 tq = tp->t_rawq;
1056 tp->t_rawq = tp->t_canq;
1057 tp->t_canq = tq;
1058 }
1059#endif
1060 CLR(tp->t_lflag, PENDIN);
1061 }
1062 ttwakeup(tp);
1063 }
1064 tp->t_iflag = t->c_iflag;
1065 tp->t_oflag = t->c_oflag;
1066
1067
1068
1069 if (ISSET(tp->t_lflag, EXTPROC))
1070 SET(t->c_lflag, EXTPROC);
1071 else
1072 CLR(t->c_lflag, EXTPROC);
1073 tp->t_lflag = t->c_lflag | ISSET(tp->t_lflag, PENDIN);
1074 if (t->c_cc[VMIN] != tp->t_cc[VMIN] ||
1075 t->c_cc[VTIME] != tp->t_cc[VTIME])
1076 ttwakeup(tp);
1077 bcopy(t->c_cc, tp->t_cc, sizeof(t->c_cc));
1078 splx(s);
1079 break;
1080 }
1081 case TIOCSETD: {
1082 register int t = *(int *)data;
1083 dev_t device = tp->t_dev;
1084
1085 if (t >= nlinesw)
1086 return (ENXIO);
1087 if (t != tp->t_line) {
1088 s = spltty();
1089 (*linesw[tp->t_line].l_close)(tp, flag);
1090 error = (*linesw[t].l_open)(device, tp);
1091 if (error) {
1092 (void)(*linesw[tp->t_line].l_open)(device, tp);
1093 splx(s);
1094 return (error);
1095 }
1096 tp->t_line = t;
1097 splx(s);
1098 }
1099 break;
1100 }
1101 case TIOCSTART:
1102 s = spltty();
1103 if (ISSET(tp->t_state, TS_TTSTOP) ||
1104 ISSET(tp->t_lflag, FLUSHO)) {
1105 CLR(tp->t_lflag, FLUSHO);
1106 CLR(tp->t_state, TS_TTSTOP);
1107 ttstart(tp);
1108 }
1109 splx(s);
1110 break;
1111 case TIOCSTI:
1112 if (suser(kauth_cred_get(), NULL) && (flag & FREAD) == 0)
1113 return (EPERM);
1114 if (suser(kauth_cred_get(), NULL) && !isctty(p, tp))
1115 return (EACCES);
1116 s = spltty();
1117 (*linesw[tp->t_line].l_rint)(*(u_char *)data, tp);
1118 splx(s);
1119 break;
1120 case TIOCSTOP:
1121 s = spltty();
1122 if (!ISSET(tp->t_state, TS_TTSTOP)) {
1123 SET(tp->t_state, TS_TTSTOP);
1124 ttystop(tp, 0);
1125 }
1126 splx(s);
1127 break;
1128 case TIOCSCTTY:
1129
1130 if (!SESS_LEADER(p) ||
1131 ((p->p_session->s_ttyvp || tp->t_session) &&
1132 (tp->t_session != p->p_session)))
1133 return (EPERM);
1134 tp->t_session = p->p_session;
1135 tp->t_pgrp = p->p_pgrp;
1136 p->p_session->s_ttyp = tp;
1137 p->p_flag |= P_CONTROLT;
1138
1139
1140
1141 tty_pgsignal(tp->t_pgrp, SIGCONT);
1142 break;
1143 case TIOCSPGRP: {
1144 register struct pgrp *pgrp = pgfind(*(int *)data);
1145
1146 if (!isctty(p, tp))
1147 return (ENOTTY);
1148 else if (pgrp == NULL || pgrp->pg_session != p->p_session)
1149 return (EPERM);
1150 tp->t_pgrp = pgrp;
1151
1152
1153
1154 tty_pgsignal(tp->t_pgrp, SIGCONT);
1155 break;
1156 }
1157 case TIOCSTAT:
1158 s = spltty();
1159 ttyinfo(tp);
1160 splx(s);
1161 break;
1162 case TIOCSWINSZ:
1163 if (bcmp((caddr_t)&tp->t_winsize, data,
1164 sizeof (struct winsize))) {
1165 tp->t_winsize = *(struct winsize *)data;
1166 pgsignal(tp->t_pgrp, SIGWINCH, 1);
1167 }
1168 break;
1169 case TIOCSDRAINWAIT:
1170 error = suser(kauth_cred_get(), &p->p_acflag);
1171 if (error)
1172 return (error);
1173 tp->t_timeout = *(int *)data * hz;
1174 wakeup(TSA_OCOMPLETE(tp));
1175 wakeup(TSA_OLOWAT(tp));
1176 break;
1177 case TIOCGDRAINWAIT:
1178 *(int *)data = tp->t_timeout / hz;
1179 break;
1180 default:
1181#if COMPAT_43_TTY || defined(COMPAT_SUNOS)
1182#ifdef NeXT
1183 return (ttcompat(tp, cmd, data, flag, p));
1184#else
1185 return (ttcompat(tp, cmd, data, flag));
1186#endif
1187#else
1188 return (ENOTTY);
1189#endif
1190 }
1191
1192 return (0);
1193}
1194
1195int
1196ttyselect(tp, rw, wql, p)
1197 struct tty *tp;
1198 int rw;
1199 void * wql;
1200 struct proc *p;
1201{
1202 int s;
1203
1204 if (tp == NULL)
1205 return (ENXIO);
1206
1207 s = spltty();
1208 switch (rw) {
1209 case FREAD:
1210 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
1211 goto win;
1212 selrecord(p, &tp->t_rsel, wql);
1213 break;
1214 case FWRITE:
1215 if ((tp->t_outq.c_cc <= tp->t_lowat &&
1216 ISSET(tp->t_state, TS_CONNECTED))
1217 || ISSET(tp->t_state, TS_ZOMBIE)) {
1218win: splx(s);
1219 return (1);
1220 }
1221 selrecord(p, &tp->t_wsel, wql);
1222 break;
1223 }
1224 splx(s);
1225 return (0);
1226}
1227
1228
1229
1230
1231
1232int
1233ttselect(dev, rw, wql, p)
1234 dev_t dev;
1235 int rw;
1236 void * wql;
1237 struct proc *p;
1238{
1239#ifndef NeXT
1240 return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, wql, p);
1241#else
1242 return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, wql, p);
1243#endif
1244}
1245
1246
1247
1248
1249static int
1250ttnread(tp)
1251 struct tty *tp;
1252{
1253 int nread;
1254
1255 if (ISSET(tp->t_lflag, PENDIN))
1256 ttypend(tp);
1257 nread = tp->t_canq.c_cc;
1258 if (!ISSET(tp->t_lflag, ICANON)) {
1259 nread += tp->t_rawq.c_cc;
1260 if (nread < tp->t_cc[VMIN] && tp->t_cc[VTIME] == 0)
1261 nread = 0;
1262 }
1263 return (nread);
1264}
1265
1266
1267
1268
1269int
1270ttywait(tp)
1271 register struct tty *tp;
1272{
1273 int error, s;
1274
1275 error = 0;
1276 s = spltty();
1277 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1278 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1279 (*tp->t_oproc)(tp);
1280 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1281 ISSET(tp->t_state, TS_CONNECTED)) {
1282 SET(tp->t_state, TS_SO_OCOMPLETE);
1283 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1284 TTOPRI | PCATCH, "ttywai",
1285 tp->t_timeout);
1286 if (error) {
1287 if (error == EWOULDBLOCK)
1288 error = EIO;
1289 break;
1290 }
1291 } else
1292 break;
1293 }
1294 if (!error && (tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)))
1295 error = EIO;
1296 splx(s);
1297 return (error);
1298}
1299
1300static void
1301ttystop(tp, rw)
1302 struct tty *tp;
1303 int rw;
1304{
1305#ifdef sun4c
1306 (*tp->t_stop)(tp, rw);
1307#elif defined(NeXT)
1308 (*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
1309#else
1310 (*cdevsw[major(tp->t_dev)]->d_stop)(tp, rw);
1311#endif
1312}
1313
1314
1315
1316
1317static int
1318ttywflush(tp)
1319 struct tty *tp;
1320{
1321 int error;
1322
1323 if ((error = ttywait(tp)) == 0)
1324 ttyflush(tp, FREAD);
1325 return (error);
1326}
1327
1328
1329
1330
1331void
1332ttyflush(tp, rw)
1333 register struct tty *tp;
1334 int rw;
1335{
1336 register int s;
1337
1338 s = spltty();
1339#if 0
1340again:
1341#endif
1342 if (rw & FWRITE) {
1343 FLUSHQ(&tp->t_outq);
1344 CLR(tp->t_state, TS_TTSTOP);
1345 }
1346 ttystop(tp, rw);
1347 if (rw & FREAD) {
1348 FLUSHQ(&tp->t_canq);
1349 FLUSHQ(&tp->t_rawq);
1350 CLR(tp->t_lflag, PENDIN);
1351 tp->t_rocount = 0;
1352 tp->t_rocol = 0;
1353 CLR(tp->t_state, TS_LOCAL);
1354 ttwakeup(tp);
1355 if (ISSET(tp->t_state, TS_TBLOCK)) {
1356 if (rw & FWRITE)
1357 FLUSHQ(&tp->t_outq);
1358 ttyunblock(tp);
1359
1360
1361
1362
1363
1364
1365
1366
1367 CLR(tp->t_state, TS_TBLOCK);
1368
1369#if 0
1370 if (ISSET(tp->t_iflag, IXOFF)) {
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380 SET(tp->t_state, TS_SO_OCOMPLETE);
1381 ttysleep(tp, TSA_OCOMPLETE(tp), TTOPRI,
1382 "ttyfls", hz / 10);
1383
1384
1385
1386 CLR(tp->t_state, TS_TBLOCK);
1387 goto again;
1388 }
1389#endif
1390 }
1391 }
1392 if (rw & FWRITE) {
1393 FLUSHQ(&tp->t_outq);
1394 ttwwakeup(tp);
1395 }
1396 splx(s);
1397}
1398
1399
1400
1401
1402void
1403termioschars(t)
1404 struct termios *t;
1405{
1406
1407 bcopy(ttydefchars, t->c_cc, sizeof t->c_cc);
1408}
1409
1410
1411
1412
1413void
1414ttychars(tp)
1415 struct tty *tp;
1416{
1417
1418 termioschars(&tp->t_termios);
1419}
1420
1421
1422
1423
1424
1425
1426void
1427ttyblock(tp)
1428 struct tty *tp;
1429{
1430
1431 SET(tp->t_state, TS_TBLOCK);
1432 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTOP] != _POSIX_VDISABLE &&
1433 putc(tp->t_cc[VSTOP], &tp->t_outq) != 0)
1434 CLR(tp->t_state, TS_TBLOCK);
1435 ttstart(tp);
1436}
1437
1438
1439
1440
1441
1442
1443static void
1444ttyunblock(tp)
1445 struct tty *tp;
1446{
1447
1448 CLR(tp->t_state, TS_TBLOCK);
1449 if (ISSET(tp->t_iflag, IXOFF) && tp->t_cc[VSTART] != _POSIX_VDISABLE &&
1450 putc(tp->t_cc[VSTART], &tp->t_outq) != 0)
1451 SET(tp->t_state, TS_TBLOCK);
1452 ttstart(tp);
1453}
1454
1455#if defined(NeXT) || defined(notyet)
1456
1457
1458
1459
1460void
1461ttrstrt(tp_arg)
1462 void *tp_arg;
1463{
1464 struct tty *tp;
1465 int s;
1466
1467#if DIAGNOSTIC
1468 if (tp_arg == NULL)
1469 panic("ttrstrt");
1470#endif
1471 tp = tp_arg;
1472 s = spltty();
1473
1474 CLR(tp->t_state, TS_TIMEOUT);
1475 ttstart(tp);
1476
1477 splx(s);
1478}
1479#endif
1480
1481int
1482ttstart(tp)
1483 struct tty *tp;
1484{
1485 boolean_t funnel_state;
1486
1487 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1488
1489 if (tp->t_oproc != NULL)
1490 (*tp->t_oproc)(tp);
1491 thread_funnel_set(kernel_flock, funnel_state);
1492 return (0);
1493}
1494
1495
1496
1497
1498int
1499ttylclose(tp, flag)
1500 struct tty *tp;
1501 int flag;
1502{
1503 boolean_t funnel_state;
1504
1505 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1506 if ( (flag & FNONBLOCK) || ttywflush(tp))
1507 ttyflush(tp, FREAD | FWRITE);
1508 thread_funnel_set(kernel_flock, funnel_state);
1509 return (0);
1510}
1511
1512
1513
1514
1515
1516
1517int
1518ttymodem(tp, flag)
1519 register struct tty *tp;
1520 int flag;
1521{
1522 boolean_t funnel_state;
1523
1524 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1525
1526 if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) {
1527
1528
1529
1530
1531
1532 if (flag) {
1533 CLR(tp->t_state, TS_CAR_OFLOW);
1534 CLR(tp->t_state, TS_TTSTOP);
1535 ttstart(tp);
1536 } else if (!ISSET(tp->t_state, TS_CAR_OFLOW)) {
1537 SET(tp->t_state, TS_CAR_OFLOW);
1538 SET(tp->t_state, TS_TTSTOP);
1539 ttystop(tp, 0);
1540 }
1541 } else if (flag == 0) {
1542
1543
1544
1545 CLR(tp->t_state, TS_CARR_ON);
1546 if (ISSET(tp->t_state, TS_ISOPEN) &&
1547 !ISSET(tp->t_cflag, CLOCAL)) {
1548 SET(tp->t_state, TS_ZOMBIE);
1549 CLR(tp->t_state, TS_CONNECTED);
1550 if (tp->t_session && tp->t_session->s_leader)
1551 psignal(tp->t_session->s_leader, SIGHUP);
1552 ttyflush(tp, FREAD | FWRITE);
1553 thread_funnel_set(kernel_flock, funnel_state);
1554 return (0);
1555 }
1556 } else {
1557
1558
1559
1560 SET(tp->t_state, TS_CARR_ON);
1561 if (!ISSET(tp->t_state, TS_ZOMBIE))
1562 SET(tp->t_state, TS_CONNECTED);
1563 wakeup(TSA_CARR_ON(tp));
1564 ttwakeup(tp);
1565 ttwwakeup(tp);
1566 }
1567 thread_funnel_set(kernel_flock, funnel_state);
1568 return (1);
1569}
1570
1571
1572
1573
1574
1575static void
1576ttypend(tp)
1577 register struct tty *tp;
1578{
1579 struct clist tq;
1580 register int c;
1581
1582 CLR(tp->t_lflag, PENDIN);
1583 SET(tp->t_state, TS_TYPEN);
1584#ifndef NeXT
1585
1586
1587
1588
1589
1590
1591 tq = tp->t_rawq;
1592 bzero(&tp->t_rawq, sizeof tp->t_rawq);
1593 tp->t_rawq.c_cbmax = tq.c_cbmax;
1594 tp->t_rawq.c_cbreserved = tq.c_cbreserved;
1595#else
1596 tq = tp->t_rawq;
1597 tp->t_rawq.c_cc = 0;
1598 tp->t_rawq.c_cf = tp->t_rawq.c_cl = 0;
1599#endif
1600 while ((c = getc(&tq)) >= 0)
1601 ttyinput(c, tp);
1602 CLR(tp->t_state, TS_TYPEN);
1603}
1604
1605
1606
1607
1608int
1609ttread(tp, uio, flag)
1610 register struct tty *tp;
1611 struct uio *uio;
1612 int flag;
1613{
1614 register struct clist *qp;
1615 register int c;
1616 register tcflag_t lflag;
1617 register cc_t *cc = tp->t_cc;
1618 register struct proc *p = current_proc();
1619 int s, first, error = 0;
1620 int has_etime = 0, last_cc = 0;
1621 long slp = 0;
1622 boolean_t funnel_state;
1623 struct uthread *ut;
1624
1625 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1626
1627 ut = (struct uthread *)get_bsdthread_info(current_thread());
1628
1629loop:
1630 s = spltty();
1631 lflag = tp->t_lflag;
1632
1633
1634
1635 if (ISSET(lflag, PENDIN)) {
1636 ttypend(tp);
1637 splx(s);
1638 s = spltty();
1639 lflag = tp->t_lflag;
1640 }
1641
1642
1643
1644
1645 if (isbackground(p, tp)) {
1646 splx(s);
1647 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
1648 (ut->uu_sigmask & sigmask(SIGTTIN)) ||
1649 p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) {
1650 thread_funnel_set(kernel_flock, funnel_state);
1651 return (EIO);
1652 }
1653 pgsignal(p->p_pgrp, SIGTTIN, 1);
1654 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg2", 0);
1655 if (error){
1656 thread_funnel_set(kernel_flock, funnel_state);
1657 return (error);
1658 }
1659 goto loop;
1660 }
1661
1662 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1663 splx(s);
1664 thread_funnel_set(kernel_flock, funnel_state);
1665 return (0);
1666 }
1667
1668
1669
1670
1671
1672
1673
1674 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1675
1676 if (flag & IO_NDELAY) {
1677 if (qp->c_cc > 0)
1678 goto read;
1679 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1680 splx(s);
1681 thread_funnel_set(kernel_flock, funnel_state);
1682 return (0);
1683 }
1684 splx(s);
1685 thread_funnel_set(kernel_flock, funnel_state);
1686 return (EWOULDBLOCK);
1687 }
1688 if (!ISSET(lflag, ICANON)) {
1689 int m = cc[VMIN];
1690 long t = cc[VTIME];
1691 struct timeval etime, timecopy;
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701 if (t == 0) {
1702 if (qp->c_cc < m)
1703 goto sleep;
1704 if (qp->c_cc > 0)
1705 goto read;
1706
1707
1708 splx(s);
1709 thread_funnel_set(kernel_flock, funnel_state);
1710 return (0);
1711 }
1712 t *= 100000;
1713#define diff(t1, t2) (((t1).tv_sec - (t2).tv_sec) * 1000000 + \
1714 ((t1).tv_usec - (t2).tv_usec))
1715 if (m > 0) {
1716 if (qp->c_cc <= 0)
1717 goto sleep;
1718 if (qp->c_cc >= m)
1719 goto read;
1720 microuptime(&timecopy);
1721 if (!has_etime) {
1722
1723 has_etime = 1;
1724
1725 etime.tv_sec = t / 1000000;
1726 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1727 timeradd(&etime, &timecopy, &etime);
1728
1729 slp = t;
1730 } else if (qp->c_cc > last_cc) {
1731
1732
1733 etime.tv_sec = t / 1000000;
1734 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1735 timeradd(&etime, &timecopy, &etime);
1736
1737 slp = t;
1738 } else {
1739
1740 if (timercmp(&etime, &timecopy, <=))
1741 goto read;
1742
1743 slp = diff(etime, timecopy);
1744 }
1745 last_cc = qp->c_cc;
1746 } else {
1747 if (qp->c_cc > 0)
1748 goto read;
1749 microuptime(&timecopy);
1750 if (!has_etime) {
1751 has_etime = 1;
1752
1753 etime.tv_sec = t / 1000000;
1754 etime.tv_usec = (t - (etime.tv_sec * 1000000));
1755 timeradd(&etime, &timecopy, &etime);
1756
1757 slp = t;
1758 } else {
1759 if (timercmp(&etime, &timecopy, <=)) {
1760
1761 splx(s);
1762 thread_funnel_set(kernel_flock, funnel_state);
1763 return (0);
1764 }
1765 slp = diff(etime, timecopy);
1766 }
1767 }
1768#undef diff
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1779 goto sleep;
1780 }
1781 if (qp->c_cc <= 0) {
1782sleep:
1783
1784
1785
1786 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
1787 ISSET(tp->t_state, TS_CONNECTED) ?
1788 "ttyin" : "ttyhup", (int)slp);
1789 splx(s);
1790 if (error == EWOULDBLOCK)
1791 error = 0;
1792 else if (error) {
1793 thread_funnel_set(kernel_flock, funnel_state);
1794 return (error);
1795 }
1796
1797
1798
1799
1800
1801
1802 slp = 0;
1803 goto loop;
1804 }
1805read:
1806 splx(s);
1807
1808
1809
1810 first = 1;
1811#ifdef NeXT
1812 if (ISSET(lflag, ICANON)
1813 || (ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) )
1814#else
1815 if (ISSET(lflag, ICANON | ISIG))
1816#endif
1817 goto slowcase;
1818 for (;;) {
1819 char ibuf[IBUFSIZ];
1820 int icc;
1821
1822 icc = min(uio_resid(uio), IBUFSIZ);
1823 icc = q_to_b(qp, ibuf, icc);
1824 if (icc <= 0) {
1825 if (first)
1826 goto loop;
1827 break;
1828 }
1829 error = uiomove(ibuf, icc, uio);
1830
1831
1832
1833
1834#if NSNP > 0
1835 if (ISSET(tp->t_lflag, ECHO) &&
1836 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1837 snpin((struct snoop *)tp->t_sc, ibuf, icc);
1838#endif
1839 if (error)
1840 break;
1841 if (uio_resid(uio) == 0)
1842 break;
1843 first = 0;
1844 }
1845 goto out;
1846slowcase:
1847 for (;;) {
1848 c = getc(qp);
1849 if (c < 0) {
1850 if (first)
1851 goto loop;
1852 break;
1853 }
1854
1855
1856
1857 if (CCEQ(cc[VDSUSP], c) &&
1858 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
1859 pgsignal(tp->t_pgrp, SIGTSTP, 1);
1860 if (first) {
1861 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
1862 "ttybg3", 0);
1863 if (error)
1864 break;
1865 goto loop;
1866 }
1867 break;
1868 }
1869
1870
1871
1872 if (CCEQ(cc[VEOF], c) && ISSET(lflag, ICANON))
1873 break;
1874
1875
1876
1877 error = ureadc(c, uio);
1878 if (error)
1879
1880 break;
1881#if NSNP > 0
1882
1883
1884
1885
1886 if (ISSET(tp->t_lflag, ECHO) &&
1887 ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
1888 snpinc((struct snoop *)tp->t_sc, (char)c);
1889#endif
1890 if (uio_resid(uio) == 0)
1891 break;
1892
1893
1894
1895
1896 if (ISSET(lflag, ICANON) && TTBREAKC(c, lflag))
1897 break;
1898 first = 0;
1899 }
1900
1901out:
1902
1903
1904
1905
1906 s = spltty();
1907 if (ISSET(tp->t_state, TS_TBLOCK) &&
1908 tp->t_rawq.c_cc + tp->t_canq.c_cc <= I_LOW_WATER)
1909 ttyunblock(tp);
1910 splx(s);
1911
1912 thread_funnel_set(kernel_flock, funnel_state);
1913 return (error);
1914}
1915
1916
1917
1918
1919
1920
1921
1922
1923int
1924ttycheckoutq(tp, wait)
1925 register struct tty *tp;
1926 int wait;
1927{
1928 int hiwat, s;
1929 sigset_t oldsig;
1930 struct uthread *ut;
1931
1932 ut = (struct uthread *)get_bsdthread_info(current_thread());
1933
1934 hiwat = tp->t_hiwat;
1935 s = spltty();
1936 oldsig = wait ? ut->uu_siglist : 0;
1937 if (tp->t_outq.c_cc > hiwat + OBUFSIZ + 100)
1938 while (tp->t_outq.c_cc > hiwat) {
1939 ttstart(tp);
1940 if (tp->t_outq.c_cc <= hiwat)
1941 break;
1942 if (wait == 0 || ut->uu_siglist != oldsig) {
1943 splx(s);
1944 return (0);
1945 }
1946 SET(tp->t_state, TS_SO_OLOWAT);
1947 tsleep(TSA_OLOWAT(tp), PZERO - 1, "ttoutq", hz);
1948 }
1949 splx(s);
1950 return (1);
1951}
1952
1953
1954
1955
1956int
1957ttwrite(tp, uio, flag)
1958 register struct tty *tp;
1959 register struct uio *uio;
1960 int flag;
1961{
1962 register char *cp = NULL;
1963 register int cc, ce;
1964 register struct proc *p;
1965 int i, hiwat, count, error, s;
1966 char obuf[OBUFSIZ];
1967 boolean_t funnel_state;
1968 struct uthread *ut;
1969
1970 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1971
1972 ut = (struct uthread *)get_bsdthread_info(current_thread());
1973 hiwat = tp->t_hiwat;
1974
1975 count = uio_resid(uio);
1976 error = 0;
1977 cc = 0;
1978loop:
1979 s = spltty();
1980 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1981 splx(s);
1982 if (uio_resid(uio) == count)
1983 error = EIO;
1984 goto out;
1985 }
1986 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1987 if (flag & IO_NDELAY) {
1988 splx(s);
1989 error = EWOULDBLOCK;
1990 goto out;
1991 }
1992 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
1993 "ttydcd", 0);
1994 splx(s);
1995 if (error) {
1996 goto out; }
1997 goto loop;
1998 }
1999 splx(s);
2000
2001
2002
2003 p = current_proc();
2004 if (isbackground(p, tp) &&
2005 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
2006 (p->p_sigignore & sigmask(SIGTTOU)) == 0 &&
2007 (ut->uu_sigmask & sigmask(SIGTTOU)) == 0) {
2008 if (p->p_pgrp->pg_jobc == 0) {
2009 error = EIO;
2010 goto out;
2011 }
2012 pgsignal(p->p_pgrp, SIGTTOU, 1);
2013 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg4", 0);
2014 if (error)
2015 goto out;
2016 goto loop;
2017 }
2018
2019
2020
2021
2022
2023 while (uio_resid(uio) > 0 || cc > 0) {
2024 if (ISSET(tp->t_lflag, FLUSHO)) {
2025 uio_setresid(uio, 0);
2026 thread_funnel_set(kernel_flock, funnel_state);
2027 return (0);
2028 }
2029 if (tp->t_outq.c_cc > hiwat)
2030 goto ovhiwat;
2031
2032
2033
2034
2035 if (cc == 0) {
2036 cc = min(uio_resid(uio), OBUFSIZ);
2037 cp = obuf;
2038 error = uiomove(cp, cc, uio);
2039 if (error) {
2040 cc = 0;
2041 break;
2042 }
2043#if NSNP > 0
2044 if (ISSET(tp->t_state, TS_SNOOP) && tp->t_sc != NULL)
2045 snpin((struct snoop *)tp->t_sc, cp, cc);
2046#endif
2047 }
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057 while (cc > 0) {
2058 if (!ISSET(tp->t_oflag, OPOST))
2059 ce = cc;
2060 else {
2061 ce = cc - scanc((u_int)cc, (u_char *)cp,
2062 char_type, CCLASSMASK);
2063
2064
2065
2066
2067 if (ce == 0) {
2068 tp->t_rocount = 0;
2069 if (ttyoutput(*cp, tp) >= 0) {
2070#ifdef NeXT
2071
2072 goto overfull;
2073#else
2074
2075 ttstart(tp);
2076 if (flag & IO_NDELAY) {
2077 error = EWOULDBLOCK;
2078 goto out;
2079 }
2080 error = ttysleep(tp, &lbolt,
2081 TTOPRI|PCATCH,
2082 "ttybf1", 0);
2083 if (error)
2084 goto out;
2085 goto loop;
2086#endif
2087 }
2088 cp++;
2089 cc--;
2090 if (ISSET(tp->t_lflag, FLUSHO) ||
2091 tp->t_outq.c_cc > hiwat)
2092 goto ovhiwat;
2093 continue;
2094 }
2095 }
2096
2097
2098
2099
2100
2101
2102
2103
2104 tp->t_rocount = 0;
2105 i = b_to_q(cp, ce, &tp->t_outq);
2106 ce -= i;
2107 tp->t_column += ce;
2108 cp += ce, cc -= ce, tk_nout += ce;
2109 tp->t_outcc += ce;
2110 if (i > 0) {
2111#ifdef NeXT
2112
2113 goto overfull;
2114#else
2115
2116 ttstart(tp);
2117 if (flag & IO_NDELAY) {
2118 error = EWOULDBLOCK;
2119 goto out;
2120 }
2121 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH,
2122 "ttybf2", 0);
2123 if (error)
2124 goto out;
2125 goto loop;
2126#endif
2127 }
2128 if (ISSET(tp->t_lflag, FLUSHO) ||
2129 tp->t_outq.c_cc > hiwat)
2130 break;
2131 }
2132 ttstart(tp);
2133 }
2134out:
2135
2136
2137
2138
2139
2140 uio_setresid(uio, (uio_resid(uio) + cc));
2141 thread_funnel_set(kernel_flock, funnel_state);
2142 return (error);
2143
2144#ifdef NeXT
2145overfull:
2146
2147
2148
2149
2150
2151
2152
2153 hiwat = tp->t_outq.c_cc - 1;
2154#endif
2155
2156ovhiwat:
2157 ttstart(tp);
2158 s = spltty();
2159
2160
2161
2162
2163 if (tp->t_outq.c_cc <= hiwat) {
2164 splx(s);
2165 goto loop;
2166 }
2167 if (flag & IO_NDELAY) {
2168 splx(s);
2169 uio_setresid(uio, (uio_resid(uio) + cc));
2170 thread_funnel_set(kernel_flock, funnel_state);
2171 return (uio_resid(uio) == count ? EWOULDBLOCK : 0);
2172 }
2173 SET(tp->t_state, TS_SO_OLOWAT);
2174 error = ttysleep(tp, TSA_OLOWAT(tp), TTOPRI | PCATCH, "ttywri",
2175 tp->t_timeout);
2176 splx(s);
2177 if (error == EWOULDBLOCK)
2178 error = EIO;
2179 if (error)
2180 goto out;
2181 goto loop;
2182}
2183
2184
2185
2186
2187
2188static void
2189ttyrub(c, tp)
2190 register int c;
2191 register struct tty *tp;
2192{
2193 register u_char *cp;
2194 register int savecol;
2195 int tabc, s;
2196
2197 if (!ISSET(tp->t_lflag, ECHO) || ISSET(tp->t_lflag, EXTPROC))
2198 return;
2199 CLR(tp->t_lflag, FLUSHO);
2200 if (ISSET(tp->t_lflag, ECHOE)) {
2201 if (tp->t_rocount == 0) {
2202
2203
2204
2205 ttyretype(tp);
2206 return;
2207 }
2208 if (c == ('\t' | TTY_QUOTE) || c == ('\n' | TTY_QUOTE))
2209 ttyrubo(tp, 2);
2210 else {
2211 CLR(c, ~TTY_CHARMASK);
2212 switch (CCLASS(c)) {
2213 case ORDINARY:
2214 ttyrubo(tp, 1);
2215 break;
2216 case BACKSPACE:
2217 case CONTROL:
2218 case NEWLINE:
2219 case RETURN:
2220 case VTAB:
2221 if (ISSET(tp->t_lflag, ECHOCTL))
2222 ttyrubo(tp, 2);
2223 break;
2224 case TAB:
2225 if (tp->t_rocount < tp->t_rawq.c_cc) {
2226 ttyretype(tp);
2227 return;
2228 }
2229 s = spltty();
2230 savecol = tp->t_column;
2231 SET(tp->t_state, TS_CNTTB);
2232 SET(tp->t_lflag, FLUSHO);
2233 tp->t_column = tp->t_rocol;
2234#ifndef NeXT
2235 cp = tp->t_rawq.c_cf;
2236 if (cp)
2237 tabc = *cp;
2238 for (; cp; cp = nextc(&tp->t_rawq, cp, &tabc))
2239 ttyecho(tabc, tp);
2240#else
2241 for (cp = firstc(&tp->t_rawq, &tabc); cp;
2242 cp = nextc(&tp->t_rawq, cp, &tabc))
2243 ttyecho(tabc, tp);
2244#endif
2245 CLR(tp->t_lflag, FLUSHO);
2246 CLR(tp->t_state, TS_CNTTB);
2247 splx(s);
2248
2249
2250 savecol -= tp->t_column;
2251 tp->t_column += savecol;
2252 if (savecol > 8)
2253 savecol = 8;
2254 while (--savecol >= 0)
2255 (void)ttyoutput('\b', tp);
2256 break;
2257 default:
2258#define PANICSTR "ttyrub: would panic c = %d, val = %d\n"
2259 (void)printf(PANICSTR, c, CCLASS(c));
2260#ifdef notdef
2261 panic(PANICSTR, c, CCLASS(c));
2262#endif
2263 }
2264 }
2265 } else if (ISSET(tp->t_lflag, ECHOPRT)) {
2266 if (!ISSET(tp->t_state, TS_ERASE)) {
2267 SET(tp->t_state, TS_ERASE);
2268 (void)ttyoutput('\\', tp);
2269 }
2270 ttyecho(c, tp);
2271 } else
2272 ttyecho(tp->t_cc[VERASE], tp);
2273 --tp->t_rocount;
2274}
2275
2276
2277
2278
2279static void
2280ttyrubo(struct tty *tp, int count)
2281{
2282
2283 while (count-- > 0) {
2284 (void)ttyoutput('\b', tp);
2285 (void)ttyoutput(' ', tp);
2286 (void)ttyoutput('\b', tp);
2287 }
2288}
2289
2290
2291
2292
2293
2294
2295static void
2296ttyretype(tp)
2297 register struct tty *tp;
2298{
2299 register u_char *cp;
2300 int s, c;
2301
2302
2303 if (tp->t_cc[VREPRINT] != _POSIX_VDISABLE)
2304 ttyecho(tp->t_cc[VREPRINT], tp);
2305
2306 (void)ttyoutput('\n', tp);
2307
2308
2309
2310
2311
2312
2313 s = spltty();
2314#ifndef NeXT
2315 for (cp = tp->t_canq.c_cf, c = (cp != NULL ? *cp : 0);
2316 cp != NULL; cp = nextc(&tp->t_canq, cp, &c))
2317 ttyecho(c, tp);
2318 for (cp = tp->t_rawq.c_cf, c = (cp != NULL ? *cp : 0);
2319 cp != NULL; cp = nextc(&tp->t_rawq, cp, &c))
2320 ttyecho(c, tp);
2321#else NeXT
2322 for (cp = firstc(&tp->t_canq, &c); cp; cp = nextc(&tp->t_canq, cp, &c))
2323 ttyecho(c, tp);
2324 for (cp = firstc(&tp->t_rawq, &c); cp; cp = nextc(&tp->t_rawq, cp, &c))
2325 ttyecho(c, tp);
2326#endif
2327 CLR(tp->t_state, TS_ERASE);
2328 splx(s);
2329
2330 tp->t_rocount = tp->t_rawq.c_cc;
2331 tp->t_rocol = 0;
2332}
2333
2334
2335
2336
2337static void
2338ttyecho(c, tp)
2339 register int c;
2340 register struct tty *tp;
2341{
2342
2343 if (!ISSET(tp->t_state, TS_CNTTB))
2344 CLR(tp->t_lflag, FLUSHO);
2345 if ((!ISSET(tp->t_lflag, ECHO) &&
2346 (c != '\n' || !ISSET(tp->t_lflag, ECHONL))) ||
2347 ISSET(tp->t_lflag, EXTPROC))
2348 return;
2349 if (ISSET(tp->t_lflag, ECHOCTL) &&
2350 ((ISSET(c, TTY_CHARMASK) <= 037 && c != '\t' && c != '\n') ||
2351 ISSET(c, TTY_CHARMASK) == 0177)) {
2352 (void)ttyoutput('^', tp);
2353 CLR(c, ~TTY_CHARMASK);
2354 if (c == 0177)
2355 c = '?';
2356 else
2357 c += 'A' - 1;
2358 }
2359 (void)ttyoutput(c, tp);
2360}
2361
2362
2363
2364
2365void
2366ttwakeup(tp)
2367 register struct tty *tp;
2368{
2369
2370#ifndef NeXT
2371 if (tp->t_rsel.si_pid != 0)
2372#endif
2373 selwakeup(&tp->t_rsel);
2374 if (ISSET(tp->t_state, TS_ASYNC))
2375 pgsignal(tp->t_pgrp, SIGIO, 1);
2376 wakeup(TSA_HUP_OR_INPUT(tp));
2377}
2378
2379
2380
2381
2382void
2383ttwwakeup(tp)
2384 register struct tty *tp;
2385{
2386#ifndef NeXT
2387 if (tp->t_wsel.si_pid != 0 && tp->t_outq.c_cc <= tp->t_lowat)
2388#else
2389 if (tp->t_outq.c_cc <= tp->t_lowat)
2390#endif
2391 selwakeup(&tp->t_wsel);
2392 if (ISSET(tp->t_state, TS_BUSY | TS_SO_OCOMPLETE) ==
2393 TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
2394 CLR(tp->t_state, TS_SO_OCOMPLETE);
2395 wakeup(TSA_OCOMPLETE(tp));
2396 }
2397 if (ISSET(tp->t_state, TS_SO_OLOWAT) &&
2398 tp->t_outq.c_cc <= tp->t_lowat) {
2399 CLR(tp->t_state, TS_SO_OLOWAT);
2400 wakeup(TSA_OLOWAT(tp));
2401 }
2402}
2403
2404
2405
2406
2407
2408int
2409ttspeedtab(speed, table)
2410 int speed;
2411 register struct speedtab *table;
2412{
2413
2414 for ( ; table->sp_speed != -1; table++)
2415 if (table->sp_speed == speed)
2416 return (table->sp_code);
2417 return (-1);
2418}
2419
2420
2421
2422
2423
2424
2425
2426
2427void
2428ttsetwater(struct tty *tp)
2429{
2430 int cps;
2431 unsigned int x;
2432
2433#define CLAMP(x, h, l) ((x) > h ? h : ((x) < l) ? l : (x))
2434
2435 cps = tp->t_ospeed / 10;
2436 tp->t_lowat = x = CLAMP(cps / 2, TTMAXLOWAT, TTMINLOWAT);
2437 x += cps;
2438 x = CLAMP(x, TTMAXHIWAT, TTMINHIWAT);
2439 tp->t_hiwat = roundup(x, CBSIZE);
2440#undef CLAMP
2441}
2442
2443
2444#include <mach/thread_info.h>
2445
2446
2447extern kern_return_t thread_info_internal(thread_t thread,
2448 thread_flavor_t flavor,
2449 thread_info_t thread_info_out,
2450 mach_msg_type_number_t *thread_info_count);
2451
2452
2453
2454
2455void
2456ttyinfo(struct tty *tp)
2457{
2458 int load;
2459 thread_t thread;
2460 uthread_t uthread;
2461 struct proc *p;
2462 struct proc *pick;
2463 const char *state;
2464 struct timeval utime;
2465 struct timeval stime;
2466 thread_basic_info_data_t basic_info;
2467 mach_msg_type_number_t mmtn = THREAD_BASIC_INFO_COUNT;
2468
2469 if (ttycheckoutq(tp,0) == 0)
2470 return;
2471
2472
2473 load = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT;
2474 ttyprintf(tp, "load: %d.%02d ", load / 100, load % 100);
2475
2476
2477
2478
2479
2480 if (tp->t_session == NULL) {
2481 ttyprintf(tp, "not a controlling terminal\n");
2482 tp->t_rocount = 0;
2483 return;
2484}
2485 if (tp->t_pgrp == NULL) {
2486 ttyprintf(tp, "no foreground process group\n");
2487 tp->t_rocount = 0;
2488 return;
2489 }
2490
2491 if ((p = tp->t_pgrp->pg_members.lh_first) == NULL) {
2492 ttyprintf(tp, "empty foreground process group\n");
2493 tp->t_rocount = 0;
2494 return;
2495 }
2496
2497
2498
2499
2500
2501 for (pick = NULL; p != NULL; p = p->p_pglist.le_next) {
2502 if (proc_compare(pick, p))
2503 pick = p;
2504 }
2505
2506 if (TAILQ_EMPTY(&pick->p_uthlist) ||
2507 (uthread = TAILQ_FIRST(&pick->p_uthlist)) == NULL ||
2508 (thread = uthread->uu_act) == NULL ||
2509 (thread_info_internal(thread, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &mmtn) != KERN_SUCCESS)) {
2510 ttyprintf(tp, "foreground process without thread\n");
2511 tp->t_rocount = 0;
2512 return;
2513 }
2514
2515 switch(basic_info.run_state) {
2516 case TH_STATE_RUNNING:
2517 state = "running";
2518 break;
2519 case TH_STATE_STOPPED:
2520 state = "stopped";
2521 break;
2522 case TH_STATE_WAITING:
2523 state = "waiting";
2524 break;
2525 case TH_STATE_UNINTERRUPTIBLE:
2526 state = "uninterruptible";
2527 break;
2528 case TH_STATE_HALTED:
2529 state = "halted";
2530 break;
2531 default:
2532 state = "unknown";
2533 break;
2534 }
2535 calcru(pick, &utime, &stime, NULL);
2536
2537
2538 ttyprintf(tp, " cmd: %s %d %s %ld.%02ldu %ld.%02lds\n",
2539 pick->p_comm,
2540 pick->p_pid,
2541 state,
2542 (long)utime.tv_sec, utime.tv_usec / 10000,
2543 (long)stime.tv_sec, stime.tv_usec / 10000);
2544 tp->t_rocount = 0;
2545}
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559#define ISRUN(p) (((p)->p_stat == SRUN) || ((p)->p_stat == SIDL))
2560#define TESTAB(a, b) ((a)<<1 | (b))
2561#define ONLYA 2
2562#define ONLYB 1
2563#define BOTH 3
2564
2565static int
2566proc_compare(p1, p2)
2567 register struct proc *p1, *p2;
2568{
2569
2570 if (p1 == NULL)
2571 return (1);
2572
2573
2574
2575 switch (TESTAB(ISRUN(p1), ISRUN(p2))) {
2576 case ONLYA:
2577 return (0);
2578 case ONLYB:
2579 return (1);
2580 case BOTH:
2581
2582
2583
2584 if (p2->p_estcpu > p1->p_estcpu)
2585 return (1);
2586 if (p1->p_estcpu > p2->p_estcpu)
2587 return (0);
2588 return (p2->p_pid > p1->p_pid);
2589 }
2590
2591
2592
2593 switch (TESTAB(p1->p_stat == SZOMB, p2->p_stat == SZOMB)) {
2594 case ONLYA:
2595 return (1);
2596 case ONLYB:
2597 return (0);
2598 case BOTH:
2599 return (p2->p_pid > p1->p_pid);
2600 }
2601
2602
2603
2604 if (p2->p_slptime > p1->p_slptime)
2605 return (0);
2606 if (p1->p_slptime > p2->p_slptime)
2607 return (1);
2608 return (p2->p_pid > p1->p_pid);
2609}
2610
2611
2612
2613
2614int
2615tputchar(c, tp)
2616 int c;
2617 struct tty *tp;
2618{
2619 register int s;
2620
2621 s = spltty();
2622 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2623 splx(s);
2624 return (-1);
2625 }
2626 if (c == '\n')
2627 (void)ttyoutput('\r', tp);
2628 (void)ttyoutput(c, tp);
2629 ttstart(tp);
2630 splx(s);
2631 return (0);
2632}
2633
2634
2635
2636
2637
2638
2639
2640int
2641ttysleep(struct tty *tp, void *chan, int pri, const char *wmesg, int timo)
2642{
2643 int error;
2644 int gen;
2645
2646 gen = tp->t_gen;
2647 error = tsleep(chan, pri, wmesg, timo);
2648 if (error)
2649 return (error);
2650 return (tp->t_gen == gen ? 0 : ERESTART);
2651}
2652
2653#ifdef NeXT
2654
2655
2656
2657struct tty *
2658ttymalloc(void)
2659{
2660 struct tty *tp;
2661
2662 MALLOC(tp, struct tty *, sizeof(struct tty), M_TTYS, M_WAITOK|M_ZERO);
2663 if (tp != NULL) {
2664
2665 clalloc(&tp->t_rawq, TTYCLSIZE, 1);
2666 clalloc(&tp->t_canq, TTYCLSIZE, 1);
2667
2668 clalloc(&tp->t_outq, TTYCLSIZE, 0);
2669 }
2670 return(tp);
2671}
2672
2673
2674
2675
2676void
2677ttyfree(tp)
2678struct tty *tp;
2679{
2680 clfree(&tp->t_rawq);
2681 clfree(&tp->t_canq);
2682 clfree(&tp->t_outq);
2683 FREE(tp, M_TTYS);
2684}
2685
2686#else
2687
2688#ifdef notyet
2689
2690
2691
2692
2693
2694
2695
2696
2697struct tty *
2698ttymalloc()
2699{
2700 struct tty *tp;
2701
2702 MALLOC(tp, struct tty *, sizeof *tp, M_TTYS, M_WAITOK|M_ZERO);
2703 return (tp);
2704}
2705#endif
2706
2707#if 0
2708
2709
2710
2711
2712void
2713ttyfree(tp)
2714 struct tty *tp;
2715{
2716 FREE(tp, M_TTYS);
2717}
2718#endif
2719#endif
2720