1/*- 2 * Copyright (c) 1982, 1986, 1990, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 22 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)tty.c 8.8 (Berkeley) 1/21/94 |
39 * $FreeBSD: head/sys/kern/tty.c 91140 2002-02-23 11:12:57Z tanimura $ |
40 */ 41 42/*- 43 * TODO: 44 * o Fix races for sending the start char in ttyflush(). 45 * o Handle inter-byte timeout for "MIN > 0, TIME > 0" in ttyselect(). 46 * With luck, there will be MIN chars before select() returns(). 47 * o Handle CLOCAL consistently for ptys. Perhaps disallow setting it. --- 22 unchanged lines hidden (view full) --- 70#include "opt_compat.h" 71#include "opt_uconsole.h" 72 73#include <sys/param.h> 74#include <sys/systm.h> 75#include <sys/filio.h> 76#include <sys/lock.h> 77#include <sys/mutex.h> |
78#include <sys/sx.h> |
79#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 80#include <sys/ioctl_compat.h> 81#endif 82#include <sys/proc.h> 83#define TTYDEFCHARS 84#include <sys/tty.h> 85#undef TTYDEFCHARS 86#include <sys/fcntl.h> --- 237 unchanged lines hidden (view full) --- 324 err = (ISSET(c, TTY_ERRORMASK)); 325 if (err) { 326 CLR(c, TTY_ERRORMASK); 327 if (ISSET(err, TTY_BI)) { 328 if (ISSET(iflag, IGNBRK)) 329 return (0); 330 if (ISSET(iflag, BRKINT)) { 331 ttyflush(tp, FREAD | FWRITE); |
332 if (tp->t_pgrp != NULL) { 333 PGRP_LOCK(tp->t_pgrp); 334 pgsignal(tp->t_pgrp, SIGINT, 1); 335 PGRP_UNLOCK(tp->t_pgrp); 336 } |
337 goto endcase; 338 } 339 if (ISSET(iflag, PARMRK)) 340 goto parmrk; 341 } else if ((ISSET(err, TTY_PE) && ISSET(iflag, INPCK)) 342 || ISSET(err, TTY_FE)) { 343 if (ISSET(iflag, IGNPAR)) 344 return (0); --- 61 unchanged lines hidden (view full) --- 406 /* 407 * Signals. 408 */ 409 if (ISSET(lflag, ISIG)) { 410 if (CCEQ(cc[VINTR], c) || CCEQ(cc[VQUIT], c)) { 411 if (!ISSET(lflag, NOFLSH)) 412 ttyflush(tp, FREAD | FWRITE); 413 ttyecho(c, tp); |
414 if (tp->t_pgrp != NULL) { 415 PGRP_LOCK(tp->t_pgrp); 416 pgsignal(tp->t_pgrp, 417 CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); 418 PGRP_UNLOCK(tp->t_pgrp); 419 } |
420 goto endcase; 421 } 422 if (CCEQ(cc[VSUSP], c)) { 423 if (!ISSET(lflag, NOFLSH)) 424 ttyflush(tp, FREAD); 425 ttyecho(c, tp); |
426 if (tp->t_pgrp != NULL) { 427 PGRP_LOCK(tp->t_pgrp); 428 pgsignal(tp->t_pgrp, SIGTSTP, 1); 429 PGRP_UNLOCK(tp->t_pgrp); 430 } |
431 goto endcase; 432 } 433 } 434 /* 435 * Handle start/stop characters. 436 */ 437 if (ISSET(iflag, IXON)) { 438 if (CCEQ(cc[VSTOP], c)) { --- 101 unchanged lines hidden (view full) --- 540 if (CCEQ(cc[VREPRINT], c) && ISSET(lflag, IEXTEN)) { 541 ttyretype(tp); 542 goto endcase; 543 } 544 /* 545 * ^T - kernel info and generate SIGINFO 546 */ 547 if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) { |
548 if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) { 549 PGRP_LOCK(tp->t_pgrp); |
550 pgsignal(tp->t_pgrp, SIGINFO, 1); |
551 PGRP_UNLOCK(tp->t_pgrp); 552 } |
553 if (!ISSET(lflag, NOKERNINFO)) 554 ttyinfo(tp); 555 goto endcase; 556 } 557 } 558 /* 559 * Check for input buffer overflow 560 */ --- 202 unchanged lines hidden (view full) --- 763 case TIOCLBIS: 764 case TIOCLSET: 765 case TIOCSETC: 766 case OTIOCSETD: 767 case TIOCSETN: 768 case TIOCSETP: 769 case TIOCSLTC: 770#endif |
771 PGRPSESS_SLOCK(); 772 PROC_LOCK(p); |
773 while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) && 774 !SIGISMEMBER(p->p_sigignore, SIGTTOU) && 775 !SIGISMEMBER(p->p_sigmask, SIGTTOU)) { |
776 if (p->p_pgrp->pg_jobc == 0) { 777 PROC_UNLOCK(p); 778 PGRPSESS_SUNLOCK(); |
779 return (EIO); |
780 } 781 PROC_UNLOCK(p); 782 PGRP_LOCK(p->p_pgrp); |
783 pgsignal(p->p_pgrp, SIGTTOU, 1); |
784 PGRP_UNLOCK(p->p_pgrp); |
785 error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1", 786 0); |
787 if (error) { 788 PGRPSESS_SUNLOCK(); |
789 return (error); |
790 } 791 PROC_LOCK(p); |
792 } |
793 PROC_UNLOCK(p); 794 PGRPSESS_SUNLOCK(); |
795 break; 796 } 797 798 switch (cmd) { /* Process the ioctl. */ 799 case FIOASYNC: /* set/clear async i/o */ 800 s = spltty(); 801 if (*(int *)data) 802 SET(tp->t_state, TS_ASYNC); --- 233 unchanged lines hidden (view full) --- 1036 if (!ISSET(tp->t_state, TS_TTSTOP)) { 1037 SET(tp->t_state, TS_TTSTOP); 1038 (*tp->t_stop)(tp, 0); 1039 } 1040 splx(s); 1041 break; 1042 case TIOCSCTTY: /* become controlling tty */ 1043 /* Session ctty vnode pointer set in vnode layer. */ |
1044 PGRPSESS_XLOCK(); |
1045 if (!SESS_LEADER(p) || 1046 ((p->p_session->s_ttyvp || tp->t_session) && |
1047 (tp->t_session != p->p_session))) { 1048 PGRPSESS_XUNLOCK(); |
1049 return (EPERM); |
1050 } |
1051 tp->t_session = p->p_session; 1052 tp->t_pgrp = p->p_pgrp; |
1053 SESS_LOCK(p->p_session); |
1054 p->p_session->s_ttyp = tp; |
1055 SESS_UNLOCK(p->p_session); 1056 PROC_LOCK(p); |
1057 p->p_flag |= P_CONTROLT; |
1058 PROC_UNLOCK(p); 1059 PGRPSESS_XUNLOCK(); |
1060 break; 1061 case TIOCSPGRP: { /* set pgrp of tty */ |
1062 register struct pgrp *pgrp; |
1063 |
1064 PGRPSESS_SLOCK(); 1065 pgrp = pgfind(*(int *)data); 1066 if (!isctty(p, tp)) { 1067 if (pgrp != NULL) 1068 PGRP_UNLOCK(pgrp); 1069 PGRPSESS_SUNLOCK(); |
1070 return (ENOTTY); |
1071 } 1072 if (pgrp == NULL) { 1073 PGRPSESS_SUNLOCK(); |
1074 return (EPERM); |
1075 } 1076 PGRP_UNLOCK(pgrp); 1077 if (pgrp->pg_session != p->p_session) { 1078 PGRPSESS_SUNLOCK(); 1079 return (EPERM); 1080 } 1081 PGRPSESS_SUNLOCK(); |
1082 tp->t_pgrp = pgrp; 1083 break; 1084 } 1085 case TIOCSTAT: /* simulate control-T */ 1086 s = spltty(); 1087 ttyinfo(tp); 1088 splx(s); 1089 break; 1090 case TIOCSWINSZ: /* set window size */ 1091 if (bcmp((caddr_t)&tp->t_winsize, data, 1092 sizeof (struct winsize))) { 1093 tp->t_winsize = *(struct winsize *)data; |
1094 if (tp->t_pgrp != NULL) { 1095 PGRP_LOCK(tp->t_pgrp); 1096 pgsignal(tp->t_pgrp, SIGWINCH, 1); 1097 PGRP_UNLOCK(tp->t_pgrp); 1098 } |
1099 } 1100 break; 1101 case TIOCSDRAINWAIT: 1102 error = suser_xxx(p->p_ucred, NULL, 0); 1103 if (error) 1104 return (error); 1105 tp->t_timeout = *(int *)data * hz; 1106 wakeup(TSA_OCOMPLETE(tp)); --- 402 unchanged lines hidden (view full) --- 1509 /* 1510 * Lost carrier. 1511 */ 1512 CLR(tp->t_state, TS_CARR_ON); 1513 if (ISSET(tp->t_state, TS_ISOPEN) && 1514 !ISSET(tp->t_cflag, CLOCAL)) { 1515 SET(tp->t_state, TS_ZOMBIE); 1516 CLR(tp->t_state, TS_CONNECTED); |
1517 if (tp->t_session) { 1518 PGRPSESS_SLOCK(); 1519 if (tp->t_session->s_leader) { 1520 struct proc *p; |
1521 |
1522 p = tp->t_session->s_leader; 1523 PROC_LOCK(p); 1524 psignal(p, SIGHUP); 1525 PROC_UNLOCK(p); 1526 } 1527 PGRPSESS_SUNLOCK(); |
1528 } 1529 ttyflush(tp, FREAD | FWRITE); 1530 return (0); 1531 } 1532 } else { 1533 /* 1534 * Carrier now on. 1535 */ --- 67 unchanged lines hidden (view full) --- 1603 lflag = tp->t_lflag; /* XXX ttypend() clobbers it */ 1604 } 1605 1606 /* 1607 * Hang process if it's in the background. 1608 */ 1609 if (isbackground(p, tp)) { 1610 splx(s); |
1611 PGRPSESS_SLOCK(); 1612 PROC_LOCK(p); |
1613 if (SIGISMEMBER(p->p_sigignore, SIGTTIN) || 1614 SIGISMEMBER(p->p_sigmask, SIGTTIN) || |
1615 (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) { 1616 PROC_UNLOCK(p); 1617 PGRPSESS_SUNLOCK(); |
1618 return (EIO); |
1619 } 1620 PROC_UNLOCK(p); 1621 PGRP_LOCK(p->p_pgrp); 1622 PGRPSESS_SUNLOCK(); |
1623 pgsignal(p->p_pgrp, SIGTTIN, 1); |
1624 PGRP_UNLOCK(p->p_pgrp); |
1625 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0); 1626 if (error) 1627 return (error); 1628 goto loop; 1629 } 1630 1631 if (ISSET(tp->t_state, TS_ZOMBIE)) { 1632 splx(s); --- 157 unchanged lines hidden (view full) --- 1790 goto loop; 1791 break; 1792 } 1793 /* 1794 * delayed suspend (^Y) 1795 */ 1796 if (CCEQ(cc[VDSUSP], c) && 1797 ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) { |
1798 if (tp->t_pgrp != NULL) { 1799 PGRP_LOCK(tp->t_pgrp); 1800 pgsignal(tp->t_pgrp, SIGTSTP, 1); 1801 PGRP_UNLOCK(tp->t_pgrp); 1802 } |
1803 if (first) { 1804 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, 1805 "ttybg3", 0); 1806 if (error) 1807 break; 1808 goto loop; 1809 } 1810 break; --- 111 unchanged lines hidden (view full) --- 1922 goto out; 1923 goto loop; 1924 } 1925 splx(s); 1926 /* 1927 * Hang the process if it's in the background. 1928 */ 1929 p = curproc; |
1930 PGRPSESS_SLOCK(); 1931 PROC_LOCK(p); |
1932 if (isbackground(p, tp) && 1933 ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) && 1934 !SIGISMEMBER(p->p_sigignore, SIGTTOU) && 1935 !SIGISMEMBER(p->p_sigmask, SIGTTOU)) { 1936 if (p->p_pgrp->pg_jobc == 0) { |
1937 PROC_UNLOCK(p); 1938 PGRPSESS_SUNLOCK(); |
1939 error = EIO; 1940 goto out; 1941 } |
1942 PROC_UNLOCK(p); 1943 PGRP_LOCK(p->p_pgrp); 1944 PGRPSESS_SUNLOCK(); |
1945 pgsignal(p->p_pgrp, SIGTTOU, 1); |
1946 PGRP_UNLOCK(p->p_pgrp); |
1947 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0); 1948 if (error) 1949 goto out; 1950 goto loop; |
1951 } else { 1952 PROC_UNLOCK(p); 1953 PGRPSESS_SUNLOCK(); |
1954 } 1955 /* 1956 * Process the user's data in at most OBUFSIZ chunks. Perform any 1957 * output translation. Keep track of high water mark, sleep on 1958 * overflow awaiting device aid in acquiring new space. 1959 */ 1960 while (uio->uio_resid > 0 || cc > 0) { 1961 if (ISSET(tp->t_lflag, FLUSHO)) { --- 444 unchanged lines hidden (view full) --- 2406 /* Print load average. */ 2407 tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; 2408 ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); 2409 2410 if (tp->t_session == NULL) 2411 ttyprintf(tp, "not a controlling terminal\n"); 2412 else if (tp->t_pgrp == NULL) 2413 ttyprintf(tp, "no foreground process group\n"); |
2414 else { |
2415 PGRP_LOCK(tp->t_pgrp); 2416 if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) { 2417 PGRP_UNLOCK(tp->t_pgrp); 2418 ttyprintf(tp, "empty foreground process group\n"); 2419 } else { 2420 PGRP_UNLOCK(tp->t_pgrp); 2421 mtx_lock_spin(&sched_lock); |
2422 |
2423 /* Pick interesting process. */ 2424 for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist)) 2425 if (proc_compare(pick, p)) 2426 pick = p; |
2427 |
2428 td = FIRST_THREAD_IN_PROC(pick); 2429 stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */ 2430 td->td_wmesg ? td->td_wmesg : "iowait"; 2431 calcru(pick, &utime, &stime, NULL); 2432 ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT || 2433 pick->p_stat == SZOMB ? 0 : 2434 pgtok(vmspace_resident_count(pick->p_vmspace)); 2435 mtx_unlock_spin(&sched_lock); |
2436 |
2437 ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, 2438 stmp); |
2439 |
2440 /* Print user time. */ 2441 ttyprintf(tp, "%lld.%02ldu ", 2442 utime.tv_sec, utime.tv_usec / 10000); |
2443 |
2444 /* Print system time. */ 2445 ttyprintf(tp, "%ld.%02lds ", 2446 (long)stime.tv_sec, stime.tv_usec / 10000); |
2447 |
2448 /* Print percentage cpu, resident set size. */ 2449 ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp); 2450 2451 } |
2452 } 2453 tp->t_rocount = 0; /* so pending input will be retyped if BS */ 2454} 2455 2456/* 2457 * Returns 1 if p2 is "better" than p1 2458 * 2459 * The algorithm for picking the "interesting" process is thus: --- 224 unchanged lines hidden --- |