Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Aug 2008 19:45:07 GMT
From:      Ed Schouten <ed@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 148035 for review
Message-ID:  <200808211945.m7LJj7qe094837@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=148035

Change 148035 by ed@ed_flippo on 2008/08/21 19:44:34

	Make snp(4) work with pts(4) created TTY's. Because we copy data
	unbuffered to userspace, we must fall back to a buffered
	approach when we've got hooks. I don't completely like this
	method yet, but hey, at least I've got it working for now.

Affected files ...

.. //depot/projects/mpsafetty/sys/kern/tty_ttydisc.c#13 edit

Differences ...

==== //depot/projects/mpsafetty/sys/kern/tty_ttydisc.c#13 (text+ko) ====

@@ -79,6 +79,8 @@
 #define CTL_ALNUM(c)	(((c) >= '0' && (c) <= '9') || \
     ((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
 
+#define	TTY_STACKBUF	256
+
 void
 ttydisc_open(struct tty *tp)
 {
@@ -434,7 +436,7 @@
 int
 ttydisc_write(struct tty *tp, struct uio *uio, int ioflag)
 {
-	char ob[256];
+	char ob[TTY_STACKBUF];
 	char *obstart;
 	int error = 0;
 	unsigned int oblen = 0;
@@ -1081,31 +1083,61 @@
 		return (0);
 
 	len = ttyoutq_read(&tp->t_outq, buf, len);
-	ttydisc_wakeup_watermark(tp);
-
-	atomic_add_long(&tty_nout, len);
 
 	/* Invoke TTY hooks. XXX: ttyhook_getc_capture()? */
 	if (tp->t_hook != NULL && tp->t_hook->th_getc_capture != NULL)
 		tp->t_hook->th_getc_capture(tp, buf, len);
 
+	ttydisc_wakeup_watermark(tp);
+	atomic_add_long(&tty_nout, len);
+
 	return (len);
 }
 
 int
 ttydisc_getc_uio(struct tty *tp, struct uio *uio)
 {
-	int error;
+	int error = 0;
 	int obytes = uio->uio_resid;
+	size_t len;
+	char buf[TTY_STACKBUF];
 
 	tty_lock_assert(tp, MA_OWNED);
 
 	if (tp->t_flags & TF_STOPPED)
 		return (0);
 
-	error = ttyoutq_read_uio(&tp->t_outq, tp, uio);
+	/*
+	 * When a TTY hook is attached, we cannot perform unbuffered
+	 * copying to userspace. We just simulate it by copying data to
+	 * a shadow buffer.
+	 */
+	if (tp->t_hook != NULL && tp->t_hook->th_getc_capture != NULL) {
+		while (uio->uio_resid > 0) {
+			/* Read to shadow buffer. */
+			len = ttyoutq_read(&tp->t_outq, buf,
+			    MIN(uio->uio_resid, sizeof buf));
+			if (len == 0)
+				break;
+
+			/* Process with hook. Handle sudden removal. */
+			if (tp->t_hook != NULL &&
+			    tp->t_hook->th_getc_capture != NULL)
+				tp->t_hook->th_getc_capture(tp, buf, len);
+
+			/* Copy to userspace. */
+			tty_unlock(tp);
+			error = uiomove(buf, len, uio);
+			tty_lock(tp);
+			
+			if (error != 0)
+				break;
+		}
+	} else {
+		error = ttyoutq_read_uio(&tp->t_outq, tp, uio);
+	}
+
 	ttydisc_wakeup_watermark(tp);
-
 	atomic_add_long(&tty_nout, obytes - uio->uio_resid);
 
 	return (error);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808211945.m7LJj7qe094837>