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 * $Id: tty.c,v 1.62 1995/07/31 19:17:11 bde Exp $
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.
--- 719 unchanged lines hidden (view full) ---
767 else
768 flags &= FREAD | FWRITE;
769 ttyflush(tp, flags);
770 break;
771 }
772 case TIOCCONS: /* become virtual console */
773 if (*(int *)data) {
774 if (constty && constty != tp &&
775 ISSET(constty->t_state, TS_CONNECTED))
776 return (EBUSY);
777#ifndef UCONSOLE
778 if (error = suser(p->p_ucred, &p->p_acflag))
779 return (error);
780#endif
781 constty = tp;
782 } else if (tp == constty)
783 constty = NULL;
--- 52 unchanged lines hidden (view full) ---
836 }
837 if (!ISSET(t->c_cflag, CIGNORE)) {
838 /*
839 * Set device hardware.
840 */
841 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
842 splx(s);
843 return (error);
844 }
845 if (ISSET(t->c_cflag, CLOCAL) &&
846 !ISSET(tp->t_cflag, CLOCAL)) {
847 /*
848 * XXX disconnections would be too hard to
849 * get rid of without this kludge. The only
850 * way to get rid of controlling terminals
851 * is to exit from the session leader.
852 */
853 CLR(tp->t_state, TS_ZOMBIE);
854
855 wakeup(TSA_CARR_ON(tp));
856 ttwakeup(tp);
857 ttwwakeup(tp);
858 }
859 if ((ISSET(tp->t_state, TS_CARR_ON) ||
860 ISSET(t->c_cflag, CLOCAL)) &&
861 !ISSET(tp->t_state, TS_ZOMBIE))
862 SET(tp->t_state, TS_CONNECTED);
863 else
864 CLR(tp->t_state, TS_CONNECTED);
865 tp->t_cflag = t->c_cflag;
866 tp->t_ispeed = t->c_ispeed;
867 tp->t_ospeed = t->c_ospeed;
868 ttsetwater(tp);
869 }
870 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
871 cmd != TIOCSETAF) {
872 if (ISSET(t->c_lflag, ICANON))
873 SET(tp->t_lflag, PENDIN);
874 else {
875 /*
--- 146 unchanged lines hidden (view full) ---
1022 int s;
1023
1024 if (tp == NULL)
1025 return (ENXIO);
1026
1027 s = spltty();
1028 switch (rw) {
1029 case FREAD:
1030 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
1031 goto win;
1032 selrecord(p, &tp->t_rsel);
1033 break;
1034 case FWRITE:
1035 if ((tp->t_outq.c_cc <= tp->t_lowat &&
1036 ISSET(tp->t_state, TS_CONNECTED))
1037 || ISSET(tp->t_state, TS_ZOMBIE)) {
1038win: splx(s);
1039 return (1);
1040 }
1041 selrecord(p, &tp->t_wsel);
1042 break;
1043 }
1044 splx(s);
1045 return (0);
--- 39 unchanged lines hidden (view full) ---
1085ttywait(tp)
1086 register struct tty *tp;
1087{
1088 int error, s;
1089
1090 error = 0;
1091 s = spltty();
1092 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1093 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1094 (*tp->t_oproc)(tp);
1095 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1096 ISSET(tp->t_state, TS_CONNECTED)) {
1097 SET(tp->t_state, TS_SO_OCOMPLETE);
1098 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1099 TTOPRI | PCATCH, "ttywai",
1100 tp->t_timeout);
1101 if (error) {
1102 if (error == EWOULDBLOCK)
1103 error = EIO;
1104 break;
--- 205 unchanged lines hidden (view full) ---
1310 }
1311 } else if (flag == 0) {
1312 /*
1313 * Lost carrier.
1314 */
1315 CLR(tp->t_state, TS_CARR_ON);
1316 if (ISSET(tp->t_state, TS_ISOPEN) &&
1317 !ISSET(tp->t_cflag, CLOCAL)) {
1318 SET(tp->t_state, TS_ZOMBIE);
1319 CLR(tp->t_state, TS_CONNECTED);
1320 if (tp->t_session && tp->t_session->s_leader)
1321 psignal(tp->t_session->s_leader, SIGHUP);
1322 ttyflush(tp, FREAD | FWRITE);
1323 return (0);
1324 }
1325 } else {
1326 /*
1327 * Carrier now on.
1328 */
1329 SET(tp->t_state, TS_CARR_ON);
1330 if (!ISSET(tp->t_state, TS_ZOMBIE))
1331 SET(tp->t_state, TS_CONNECTED);
1332 wakeup(TSA_CARR_ON(tp));
1333 ttwakeup(tp);
1334 ttwwakeup(tp);
1335 }
1336 return (1);
1337}
1338
1339/*
1340 * Reinput pending characters after state switch
--- 32 unchanged lines hidden (view full) ---
1373 struct uio *uio;
1374 int flag;
1375{
1376 register struct clist *qp;
1377 register int c;
1378 register tcflag_t lflag;
1379 register cc_t *cc = tp->t_cc;
1380 register struct proc *p = curproc;
1381 int s, first, error = 0;
1382 int has_stime = 0, last_cc = 0;
1383 long slp = 0; /* XXX this should be renamed `timo'. */
1384
1385loop:
1386 s = spltty();
1387 lflag = tp->t_lflag;
1388 /*
1389 * take pending input first
--- 16 unchanged lines hidden (view full) ---
1406 return (EIO);
1407 pgsignal(p->p_pgrp, SIGTTIN, 1);
1408 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
1409 if (error)
1410 return (error);
1411 goto loop;
1412 }
1413
1414 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1415 splx(s);
1416 return (0); /* EOF */
1417 }
1418
1419 /*
1420 * If canonical, use the canonical queue,
1421 * else use the raw queue.
1422 *
1423 * (should get rid of clists...)
1424 */
1425 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1426
1427 if (flag & IO_NDELAY) {
1428 if (qp->c_cc > 0)
1429 goto read;
1430 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1431 splx(s);
1432 return (0);
1433 }
1434 splx(s);
1435 return (EWOULDBLOCK);
1436 }
1437 if (!ISSET(lflag, ICANON)) {
1438 int m = cc[VMIN];
--- 73 unchanged lines hidden (view full) ---
1512 * 32-bit arithmetic is enough for hz < 169.
1513 * XXX see hzto() for how to avoid overflow if hz
1514 * is large (divide by `tick' and/or arrange to
1515 * use hzto() if hz is large).
1516 */
1517 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1518 goto sleep;
1519 }
1520 if (qp->c_cc <= 0) {
1521sleep:
1522 /*
1523 * There is no input, or not enough input and we can block.
1524 */
1525 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
1526 ISSET(tp->t_state, TS_CONNECTED) ?
1527 "ttyin" : "ttyhup", (int)slp);
1528 splx(s);
1529 if (error == EWOULDBLOCK)
1530 error = 0;
1531 else if (error)
1532 return (error);
1533 /*
1534 * XXX what happens if another process eats some input
--- 157 unchanged lines hidden (view full) ---
1692 char obuf[OBUFSIZ];
1693
1694 hiwat = tp->t_hiwat;
1695 cnt = uio->uio_resid;
1696 error = 0;
1697 cc = 0;
1698loop:
1699 s = spltty();
1700 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1701 splx(s);
1702 if (uio->uio_resid == cnt)
1703 error = EIO;
1704 goto out;
1705 }
1706 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1707 if (flag & IO_NDELAY) {
1708 splx(s);
1709 error = EWOULDBLOCK;
1710 goto out;
1711 }
1712 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
1713 "ttydcd", 0);
1714 splx(s);
1715 if (error)
1716 goto out;
1717 goto loop;
1718 }
1719 splx(s);
1720 /*
1721 * Hang the process if it's in the background.
1722 */
1723 p = curproc;
1724 if (isbackground(p, tp) &&
1725 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
--- 317 unchanged lines hidden (view full) ---
2043/*
2044 * Wake up any readers on a tty.
2045 */
2046void
2047ttwakeup(tp)
2048 register struct tty *tp;
2049{
2050
2051 if (tp->t_rsel.si_pid != 0)
2052 selwakeup(&tp->t_rsel);
2053 if (ISSET(tp->t_state, TS_ASYNC))
2054 pgsignal(tp->t_pgrp, SIGIO, 1);
2055 wakeup(TSA_HUP_OR_INPUT(tp));
2056}
2057
2058/*
2059 * Wake up any writers on a tty.
2060 */
2061void
2062ttwwakeup(tp)
2063 register struct tty *tp;
--- 190 unchanged lines hidden (view full) ---
2254int
2255tputchar(c, tp)
2256 int c;
2257 struct tty *tp;
2258{
2259 register int s;
2260
2261 s = spltty();
2262 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2263 splx(s);
2264 return (-1);
2265 }
2266 if (c == '\n')
2267 (void)ttyoutput('\r', tp);
2268 (void)ttyoutput(c, tp);
2269 ttstart(tp);
2270 splx(s);
--- 56 unchanged lines hidden ---
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 * $Id: tty.c,v 1.62 1995/07/31 19:17:11 bde Exp $
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.
--- 719 unchanged lines hidden (view full) ---
767 else
768 flags &= FREAD | FWRITE;
769 ttyflush(tp, flags);
770 break;
771 }
772 case TIOCCONS: /* become virtual console */
773 if (*(int *)data) {
774 if (constty && constty != tp &&
775 ISSET(constty->t_state, TS_CONNECTED))
776 return (EBUSY);
777#ifndef UCONSOLE
778 if (error = suser(p->p_ucred, &p->p_acflag))
779 return (error);
780#endif
781 constty = tp;
782 } else if (tp == constty)
783 constty = NULL;
--- 52 unchanged lines hidden (view full) ---
836 }
837 if (!ISSET(t->c_cflag, CIGNORE)) {
838 /*
839 * Set device hardware.
840 */
841 if (tp->t_param && (error = (*tp->t_param)(tp, t))) {
842 splx(s);
843 return (error);
844 }
845 if (ISSET(t->c_cflag, CLOCAL) &&
846 !ISSET(tp->t_cflag, CLOCAL)) {
847 /*
848 * XXX disconnections would be too hard to
849 * get rid of without this kludge. The only
850 * way to get rid of controlling terminals
851 * is to exit from the session leader.
852 */
853 CLR(tp->t_state, TS_ZOMBIE);
854
855 wakeup(TSA_CARR_ON(tp));
856 ttwakeup(tp);
857 ttwwakeup(tp);
858 }
859 if ((ISSET(tp->t_state, TS_CARR_ON) ||
860 ISSET(t->c_cflag, CLOCAL)) &&
861 !ISSET(tp->t_state, TS_ZOMBIE))
862 SET(tp->t_state, TS_CONNECTED);
863 else
864 CLR(tp->t_state, TS_CONNECTED);
865 tp->t_cflag = t->c_cflag;
866 tp->t_ispeed = t->c_ispeed;
867 tp->t_ospeed = t->c_ospeed;
868 ttsetwater(tp);
869 }
870 if (ISSET(t->c_lflag, ICANON) != ISSET(tp->t_lflag, ICANON) &&
871 cmd != TIOCSETAF) {
872 if (ISSET(t->c_lflag, ICANON))
873 SET(tp->t_lflag, PENDIN);
874 else {
875 /*
--- 146 unchanged lines hidden (view full) ---
1022 int s;
1023
1024 if (tp == NULL)
1025 return (ENXIO);
1026
1027 s = spltty();
1028 switch (rw) {
1029 case FREAD:
1030 if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
1031 goto win;
1032 selrecord(p, &tp->t_rsel);
1033 break;
1034 case FWRITE:
1035 if ((tp->t_outq.c_cc <= tp->t_lowat &&
1036 ISSET(tp->t_state, TS_CONNECTED))
1037 || ISSET(tp->t_state, TS_ZOMBIE)) {
1038win: splx(s);
1039 return (1);
1040 }
1041 selrecord(p, &tp->t_wsel);
1042 break;
1043 }
1044 splx(s);
1045 return (0);
--- 39 unchanged lines hidden (view full) ---
1085ttywait(tp)
1086 register struct tty *tp;
1087{
1088 int error, s;
1089
1090 error = 0;
1091 s = spltty();
1092 while ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1093 ISSET(tp->t_state, TS_CONNECTED) && tp->t_oproc) {
1094 (*tp->t_oproc)(tp);
1095 if ((tp->t_outq.c_cc || ISSET(tp->t_state, TS_BUSY)) &&
1096 ISSET(tp->t_state, TS_CONNECTED)) {
1097 SET(tp->t_state, TS_SO_OCOMPLETE);
1098 error = ttysleep(tp, TSA_OCOMPLETE(tp),
1099 TTOPRI | PCATCH, "ttywai",
1100 tp->t_timeout);
1101 if (error) {
1102 if (error == EWOULDBLOCK)
1103 error = EIO;
1104 break;
--- 205 unchanged lines hidden (view full) ---
1310 }
1311 } else if (flag == 0) {
1312 /*
1313 * Lost carrier.
1314 */
1315 CLR(tp->t_state, TS_CARR_ON);
1316 if (ISSET(tp->t_state, TS_ISOPEN) &&
1317 !ISSET(tp->t_cflag, CLOCAL)) {
1318 SET(tp->t_state, TS_ZOMBIE);
1319 CLR(tp->t_state, TS_CONNECTED);
1320 if (tp->t_session && tp->t_session->s_leader)
1321 psignal(tp->t_session->s_leader, SIGHUP);
1322 ttyflush(tp, FREAD | FWRITE);
1323 return (0);
1324 }
1325 } else {
1326 /*
1327 * Carrier now on.
1328 */
1329 SET(tp->t_state, TS_CARR_ON);
1330 if (!ISSET(tp->t_state, TS_ZOMBIE))
1331 SET(tp->t_state, TS_CONNECTED);
1332 wakeup(TSA_CARR_ON(tp));
1333 ttwakeup(tp);
1334 ttwwakeup(tp);
1335 }
1336 return (1);
1337}
1338
1339/*
1340 * Reinput pending characters after state switch
--- 32 unchanged lines hidden (view full) ---
1373 struct uio *uio;
1374 int flag;
1375{
1376 register struct clist *qp;
1377 register int c;
1378 register tcflag_t lflag;
1379 register cc_t *cc = tp->t_cc;
1380 register struct proc *p = curproc;
1381 int s, first, error = 0;
1382 int has_stime = 0, last_cc = 0;
1383 long slp = 0; /* XXX this should be renamed `timo'. */
1384
1385loop:
1386 s = spltty();
1387 lflag = tp->t_lflag;
1388 /*
1389 * take pending input first
--- 16 unchanged lines hidden (view full) ---
1406 return (EIO);
1407 pgsignal(p->p_pgrp, SIGTTIN, 1);
1408 error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
1409 if (error)
1410 return (error);
1411 goto loop;
1412 }
1413
1414 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1415 splx(s);
1416 return (0); /* EOF */
1417 }
1418
1419 /*
1420 * If canonical, use the canonical queue,
1421 * else use the raw queue.
1422 *
1423 * (should get rid of clists...)
1424 */
1425 qp = ISSET(lflag, ICANON) ? &tp->t_canq : &tp->t_rawq;
1426
1427 if (flag & IO_NDELAY) {
1428 if (qp->c_cc > 0)
1429 goto read;
1430 if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) {
1431 splx(s);
1432 return (0);
1433 }
1434 splx(s);
1435 return (EWOULDBLOCK);
1436 }
1437 if (!ISSET(lflag, ICANON)) {
1438 int m = cc[VMIN];
--- 73 unchanged lines hidden (view full) ---
1512 * 32-bit arithmetic is enough for hz < 169.
1513 * XXX see hzto() for how to avoid overflow if hz
1514 * is large (divide by `tick' and/or arrange to
1515 * use hzto() if hz is large).
1516 */
1517 slp = (long) (((u_long)slp * hz) + 999999) / 1000000;
1518 goto sleep;
1519 }
1520 if (qp->c_cc <= 0) {
1521sleep:
1522 /*
1523 * There is no input, or not enough input and we can block.
1524 */
1525 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH,
1526 ISSET(tp->t_state, TS_CONNECTED) ?
1527 "ttyin" : "ttyhup", (int)slp);
1528 splx(s);
1529 if (error == EWOULDBLOCK)
1530 error = 0;
1531 else if (error)
1532 return (error);
1533 /*
1534 * XXX what happens if another process eats some input
--- 157 unchanged lines hidden (view full) ---
1692 char obuf[OBUFSIZ];
1693
1694 hiwat = tp->t_hiwat;
1695 cnt = uio->uio_resid;
1696 error = 0;
1697 cc = 0;
1698loop:
1699 s = spltty();
1700 if (ISSET(tp->t_state, TS_ZOMBIE)) {
1701 splx(s);
1702 if (uio->uio_resid == cnt)
1703 error = EIO;
1704 goto out;
1705 }
1706 if (!ISSET(tp->t_state, TS_CONNECTED)) {
1707 if (flag & IO_NDELAY) {
1708 splx(s);
1709 error = EWOULDBLOCK;
1710 goto out;
1711 }
1712 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH,
1713 "ttydcd", 0);
1714 splx(s);
1715 if (error)
1716 goto out;
1717 goto loop;
1718 }
1719 splx(s);
1720 /*
1721 * Hang the process if it's in the background.
1722 */
1723 p = curproc;
1724 if (isbackground(p, tp) &&
1725 ISSET(tp->t_lflag, TOSTOP) && (p->p_flag & P_PPWAIT) == 0 &&
--- 317 unchanged lines hidden (view full) ---
2043/*
2044 * Wake up any readers on a tty.
2045 */
2046void
2047ttwakeup(tp)
2048 register struct tty *tp;
2049{
2050
2051 if (tp->t_rsel.si_pid != 0)
2052 selwakeup(&tp->t_rsel);
2053 if (ISSET(tp->t_state, TS_ASYNC))
2054 pgsignal(tp->t_pgrp, SIGIO, 1);
2055 wakeup(TSA_HUP_OR_INPUT(tp));
2056}
2057
2058/*
2059 * Wake up any writers on a tty.
2060 */
2061void
2062ttwwakeup(tp)
2063 register struct tty *tp;
--- 190 unchanged lines hidden (view full) ---
2254int
2255tputchar(c, tp)
2256 int c;
2257 struct tty *tp;
2258{
2259 register int s;
2260
2261 s = spltty();
2262 if (!ISSET(tp->t_state, TS_CONNECTED)) {
2263 splx(s);
2264 return (-1);
2265 }
2266 if (c == '\n')
2267 (void)ttyoutput('\r', tp);
2268 (void)ttyoutput(c, tp);
2269 ttstart(tp);
2270 splx(s);
--- 56 unchanged lines hidden ---