+ /*
+ * Process the user's data in at most OBUFSIZ
+ * chunks. Perform any output translation.
+ * Keep track of high water mark, sleep on overflow
+ * awaiting device aid in acquiring new space.
+ */
+ while (uio->uio_resid > 0 || cc > 0) {
+ if (tp->t_lflag&FLUSHO) {
+ uio->uio_resid = 0;
+ return (0);
+ }
+ if (tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ /*
+ * Grab a hunk of data from the user,
+ * unless we have some leftover from last time.
+ */
+ if (cc == 0) {
+ cc = min(uio->uio_resid, OBUFSIZ);
+ cp = obuf;
+ error = uiomove(cp, cc, uio);
+ if (error) {
+ cc = 0;
+ break;
+ }
+ }
+#ifdef notdef
+ /*
+ * If nothing fancy need be done, grab those characters we
+ * can handle without any of ttyoutput's processing and
+ * just transfer them to the output q. For those chars
+ * which require special processing (as indicated by the
+ * bits in partab), call ttyoutput. After processing
+ * a hunk of data, look for FLUSHO so ^O's will take effect
+ * immediately.
+ */
+ while (cc > 0) {
+ if (!(tp->t_oflag&OPOST))
+ ce = cc;
+ else {
+ ce = cc - scanc((unsigned)cc, (u_char *)cp,
+ (u_char *)partab, 077);
+ /*
+ * If ce is zero, then we're processing
+ * a special character through ttyoutput.
+ */
+ if (ce == 0) {
+ tp->t_rocount = 0;
+ if (ttyoutput(*cp, tp) >= 0) {
+ /* no c-lists, wait a bit */
+ ttstart(tp);
+ if (error = tsleep((caddr_t)&lbolt,
+ TTOPRI | PCATCH, ttybuf, 0))
+ break;
+ goto loop;
+ }
+ cp++, cc--;
+ if (tp->t_lflag&FLUSHO ||
+ tp->t_outq.c_cc > hiwat)
+ goto ovhiwat;
+ continue;
+ }
+ }
+ /*
+ * A bunch of normal characters have been found,
+ * transfer them en masse to the output queue and
+ * continue processing at the top of the loop.
+ * If there are any further characters in this
+ * <= OBUFSIZ chunk, the first should be a character
+ * requiring special handling by ttyoutput.
+ */
+ tp->t_rocount = 0;
+ i = b_to_q(cp, ce, &tp->t_outq);
+ ce -= i;
+ tp->t_col += ce;
+ cp += ce, cc -= ce, tk_nout += ce;
+ tp->t_outcc += ce;
+ if (i > 0) {
+ /* out of c-lists, wait a bit */
+ ttstart(tp);
+ if (error = tsleep((caddr_t)&lbolt,
+ TTOPRI | PCATCH, ttybuf, 0))
+ break;
+ goto loop;
+ }
+ if (tp->t_lflag&FLUSHO || tp->t_outq.c_cc > hiwat)
+ break;
+ }
+ ttstart(tp);
+ ttstart(tp);
+ }
+out:
+ /*
+ * If cc is nonzero, we leave the uio structure inconsistent,
+ * as the offset and iov pointers have moved forward,
+ * but it doesn't matter (the call will either return short
+ * or restart with a new uio).
+ */
+ uio->uio_resid += cc;
+ return (error);
+
+ovhiwat:
+ ttstart(tp);
+ s = spltty();
+ /*
+ * This can only occur if FLUSHO is set in t_lflag,
+ * or if ttstart/oproc is synchronous (or very fast).
+ */
+ if (tp->t_outq.c_cc <= hiwat) {
+ splx(s);
+ goto loop;
+ }
+ if (flag & IO_NDELAY) {
+ splx(s);
+ uio->uio_resid += cc;
+ if (uio->uio_resid == cnt)
+ return (EWOULDBLOCK);
+ return (0);
+ }
+ tp->t_state |= TS_ASLEEP;
+ error = tsleep((caddr_t)&tp->t_outq, TTOPRI | PCATCH, ttyout, 0);
+ splx(s);
+ if (error)
+ goto out;
+ goto loop;
+}
+
+/*
+ * Rubout one character from the rawq of tp
+ * as cleanly as possible.
+ */
+ttyrub(c, tp)
+ register c;
+ register struct tty *tp;
+{
+ register char *cp;
+ register int savecol;
+ int s;
+ char *nextc();
+
+ if ((tp->t_lflag&ECHO) == 0)
+ return;
+ if (tp->t_lflag&ECHOE) {
+ if (tp->t_rocount == 0) {
+ /*
+ * Screwed by ttwrite; retype
+ */
+ ttyretype(tp);
+ return;
+ }
+ /* if tab or newline was escaped - XXX - not 8bit */
+ if (c == ('\t'|TTY_QUOTE) || c == ('\n'|TTY_QUOTE))
+ ttyrubo(tp, 2);
+ else switch (partab[c&=0377]&077) {
+
+ case ORDINARY:
+#ifdef notdef
+ ttyrubo(tp, 1);
+ break;
+
+ case VTAB:
+ case BACKSPACE:
+ case CONTROL:
+ case RETURN:
+ if (tp->t_lflag&ECHOCTL)
+ ttyrubo(tp, 2);
+ break;
+
+ case TAB: {
+ int c;
+
+ if (tp->t_rocount < tp->t_rawq.c_cc) {
+ ttyretype(tp);
+ return;
+ }
+ s = spltty();
+ savecol = tp->t_col;
+ tp->t_state |= TS_CNTTB;
+ tp->t_lflag |= FLUSHO;
+ tp->t_col = tp->t_rocol;
+ cp = tp->t_rawq.c_cf;
+ tp->t_lflag &= ~FLUSHO;
+ tp->t_state &= ~TS_CNTTB;
+ splx(s);
+ /*
+ * savecol will now be length of the tab
+ */
+ savecol -= tp->t_col;
+ tp->t_col += savecol;
+ if (savecol > 8)
+ savecol = 8; /* overflow screw */
+ while (--savecol >= 0)
+ (void) ttyoutput('\b', tp);
+ break;
+ }
+
+ default:
+ /* XXX */
+ printf("ttyrub: would panic c = %d, val = %d\n",
+ c, partab[c&=0377]&077);
+ /*panic("ttyrub");*/
+ }
+ } else if (tp->t_lflag&ECHOPRT) {
+ if ((tp->t_state&TS_ERASE) == 0) {
+ (void) ttyoutput('\\', tp);
+ tp->t_state |= TS_ERASE;
+ }
+ ttyecho(c, tp);
+ } else
+ ttyecho(tp->t_cc[VERASE], tp);
+ tp->t_rocount--;
+}
+
+/*
+ * Crt back over cnt chars perhaps
+ * erasing them.
+ */
+ttyrubo(tp, cnt)
+ register struct tty *tp;
+ int cnt;
+{
+ register char *rubostring = tp->t_lflag&ECHOE ? "\b \b" : "\b";
+
+ while (--cnt >= 0)
+ ttyoutstr("\b \b", tp);
+}
+
+/*
+ * Reprint the rawq line.
+ * We assume c_cc has already been checked.
+ */
+ttyretype(tp)
+ register struct tty *tp;
+{
+ register char *cp;
+ char *nextc();
+ int s, c;
+
+ if (tp->t_cc[VREPRINT] != POSIX_V_DISABLE)
+ ttyecho(tp->t_cc[VREPRINT], tp);
+ (void) ttyoutput('\n', tp);
+ s = spltty();
+ /*** XXX *** FIX *** NEXTC IS BROKEN - DOESN'T CHECK QUOTE
+ BIT OF FIRST CHAR ****/
+ for (cp = tp->t_canq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_canq, cp, &c)) {
+ ttyecho(c, tp);
+ }
+ for (cp = tp->t_rawq.c_cf, c=(cp?*cp:0); cp; cp = nextc(&tp->t_rawq, cp, &c)) {
+ ttyecho(c, tp);
+ }
+ tp->t_state &= ~TS_ERASE;
+ splx(s);
+ tp->t_rocount = tp->t_rawq.c_cc;
+ tp->t_rocol = 0;
+}
+
+/*
+ * Echo a typed character to the terminal.
+ */
+ttyecho(c, tp)
+ register c;
+ register struct tty *tp;
+{
+ c &= 0377;
+ if ((tp->t_state&TS_CNTTB) == 0)
+ tp->t_lflag &= ~FLUSHO;
+ if ((tp->t_lflag&ECHO) == 0 && !(tp->t_lflag&ECHONL && c == '\n'))
+ return;
+ if (tp->t_lflag&ECHOCTL) {
+ if ((c&TTY_CHARMASK) <= 037 && c != '\t' && c != '\n' ||
+ c == 0177) {
+ (void) ttyoutput('^', tp);
+ c &= TTY_CHARMASK;
+ if (c == 0177)
+ c = '?';
+#ifdef notdef
+#endif
+ else
+ c += 'A' - 1;
+ }
+ }
+ (void) ttyoutput(c, tp);
+ * send string cp to tp
+ */
+ttyoutstr(cp, tp)
+ register char *cp;
+ register struct tty *tp;
+{
+ register char c;
+
+ while (c = *cp++)
+ (void) ttyoutput(c, tp);
+}
+
+ttwakeup(tp)
+ struct tty *tp;
+{
+
+ if (tp->t_rsel) {
+ selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
+ tp->t_state &= ~TS_RCOLL;
+ tp->t_rsel = 0;
+ }
+ if (tp->t_state & TS_ASYNC)
+ pgsignal(tp->t_pgrp, SIGIO);
+ wakeup((caddr_t)&tp->t_rawq);
+}
+
+/*
+ * set tty hi and low water marks
+ *
+ * Try to arrange the dynamics so there's about one second
+ * from hi to low water.
+ *
+ */
+ttsetwater(tp)
+ struct tty *tp;
+{
+ register cps = tp->t_ospeed / 10;
+ register x;
+
+#define clamp(x, h, l) ((x)>h ? h : ((x)<l) ? l : (x))
+ tp->t_lowat = x = clamp(cps/2, TTMAXLOWAT, TTMINLOWAT);
+ x += cps;
+ x = clamp(x, TTMAXHIWAT, TTMINHIWAT);
+ tp->t_hiwat = roundup(x, CBSIZE);
+#undef clamp
+}
+
+ttspeedtab(speed, table)
+ struct speedtab table[];
+{
+ register int i;
+
+ for (i = 0; table[i].sp_speed != -1; i++)
+ if (table[i].sp_speed == speed)
+ return(table[i].sp_code);
+ return(-1);
+}
+
+/*
+ * (^T)
+ * Report on state of foreground process group.
+ */
+ttyinfo(tp)
+ struct tty *tp;
+{
+ register struct proc *p;
+
+ if (ttycheckoutq(tp,0) == 0)
+ return;
+ if (tp->t_session == NULL)
+ ttyprintf(tp, "kernel: not a controlling terminal\n");
+ else if (tp->t_pgrp == NULL ||
+ (p = tp->t_pgrp->pg_mem) == NULL)
+ ttyprintf(tp, "kernel: no foreground process group\n");
+ else {
+ int i = 0;
+
+ for (; p != NULL; p = p->p_pgrpnxt) {
+ ttyprintf(tp,
+ "kernel: pid: %d state: %x wchan: %x ticks: %d\n",
+ p->p_pid, p->p_stat, p->p_wchan, p->p_cpticks);
+ if (++i > 6) {
+ ttyprintf(tp, "kernel: more...\n");
+ break;
+ }
+ }
+ }
+}
+
+#define TOTTY 0x2 /* XXX should be in header */
+/*VARARGS2*/
+ttyprintf(tp, fmt, x1)
+ struct tty *tp;
+ char *fmt;
+ unsigned x1;
+{
+ prf(fmt, &x1, TOTTY, (caddr_t)tp);
+}
+
+/*
+ * Output char to tty; console putchar style.
+ */
+tputchar(c, tp)
+ int c;
+ struct tty *tp;
+{
+ register s = spltty();
+
+ if ((tp->t_state & (TS_CARR_ON | TS_ISOPEN))
+ == (TS_CARR_ON | TS_ISOPEN)) {
+ if (c == '\n')
+ (void) ttyoutput('\r', tp);
+ (void) ttyoutput(c, tp);
+ ttstart(tp);
+ splx(s);
+ return (0);
+ }
+ splx(s);
+ return (-1);