cat builtin: permit interrupt during writing; more: avoid SIGPIPE

(cherry picked from commit 353204547df46174e6b4273c43f56ed4dcb5794f)

Change-Id: I740d8da02577b8c7acc74c297f110a2a913ae2bf
diff --git a/mkshrc b/mkshrc
index 6d135a3..6c20d1f 100644
--- a/mkshrc
+++ b/mkshrc
@@ -1,4 +1,4 @@
-# Copyright (c) 2010, 2012, 2013
+# Copyright (c) 2010, 2012, 2013, 2014
 #	Thorsten Glaser <tg@mirbsd.org>
 # This file is provided under the same terms as mksh.
 #-
@@ -54,20 +54,23 @@
 }
 
 function more {
-	local dummy line llen curlin=0
-
-	cat "$@" | while IFS= read -r line; do
-		llen=${%line}
-		(( llen == -1 )) && llen=${#line}
-		(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
-		if (( (curlin += llen) >= LINES )); then
-			print -n -- '\033[7m--more--\033[0m'
-			read -u1 dummy
-			[[ $dummy = [Qq]* ]] && return 0
-			curlin=$llen
-		fi
-		print -r -- "$line"
-	done
+	(
+		set +m
+		cat "$@" |&
+		trap "rv=\$?; kill $! >/dev/null 2>&1; exit \$rv" EXIT
+		while IFS= read -pr line; do
+			llen=${%line}
+			(( llen == -1 )) && llen=${#line}
+			(( llen = llen ? (llen + COLUMNS - 1) / COLUMNS : 1 ))
+			if (( (curlin += llen) >= LINES )); then
+				print -n -- '\033[7m--more--\033[0m'
+				read -u1 || exit $?
+				[[ $REPLY = [Qq]* ]] && exit 0
+				curlin=$llen
+			fi
+			print -r -- "$line"
+		done
+	)
 }
 
 function setenv {
diff --git a/src/funcs.c b/src/funcs.c
index 6698f5e..53ab789 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -3761,12 +3761,14 @@
 				break;
 			while (n) {
 				w = write(STDOUT_FILENO, cp, n);
+				eno = errno;
+				/* give the user a chance to ^C out */
+				intrcheck();
 				if (w == -1) {
-					if (errno == EINTR)
+					if (eno == EINTR)
 						/* interrupted, try again */
 						continue;
 					/* an error occured during writing */
-					eno = errno;
 					bi_errorf("%s: %s", "<stdout>",
 					    cstrerror(eno));
 					rv = 1;