Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 08 Sep 2012 17:44:56 +0200
From:      Steffen "Daode" Nurpmeso <sdaoden@gmail.com>
To:        freebsd-bugs@FreeBSD.org
Cc:        jilles@FreeBSD.org, eadler@FreeBSD.org, markjdb@gmail.com
Subject:   Re: bin/169773: sh(1): Resizing causes /bin/sh to repeat edit operations
Message-ID:  <504b67f8.hU%2BoKTUxDdq8oHD59qxE1DdF@dietcurd.wild-life.local>
In-Reply-To: <201209061926.q86JQwAC087821@freefall.freebsd.org>
References:  <201209061926.q86JQwAC087821@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
 |Synopsis: sh(1): Resizing causes /bin/sh to repeat edit operations
 |
 |http://www.freebsd.org/cgi/query-pr.cgi?pr=169773

Oh, what a mess :)
I agree with Mark that the handling of OKCMD is simply wrong, but
it turned out to be wrong to simply use a different value for it.
Also the passing through of errno is incomplete in there.  (The
documented interface doesn't state anything about errno or useful
error handling at all, and however!)

It's a rather quick first diff for editline(3), i have no more
time but since it took almost three hours to come that far someone
else may build on top of it (or simply try it or ... wait for a
second).

I *think* it effectively results in editline(3) behaving the way
it is supposed to work (retrying once after a whatever signal,
then failing for a second one).  Since el_gets() now fails (as it
is supposed to), sh(1) will behave wrong in that the current line
gets "thrown away".  (I guess the supposed way is to temporarily
adjust PROMPT if one wants to continue what is on the line yet?
But i still have no idea of editline(3) :->)

It would be better if editline(3) could be configured to simply
restart upon EINTR, or to fixate that behaviour (for FreeBSD)?
I don't think it is acceptable to loose a line of user content due
to a simple resize?
So long and ciao,

--steffen

diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index 7d7f54b..5b51577 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -238,8 +238,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
 	el->el_errno = 0;
 	do {
 		if ((num = el_getc(el, ch)) != 1) {	/* if EOF or error */
-			el->el_errno = num == 0 ? 0 : errno;
-			return (num);
+			return (num < 0 ? 1 : 0);
 		}
 
 #ifdef	KANJI
@@ -294,16 +293,18 @@ read_char(EditLine *el, char *cp)
 
  again:
 	el->el_signal->sig_no = 0;
-	while ((num_read = read(el->el_infd, cp, 1)) == -1) {
+	while ((num_read = read(el->el_infd, cp, 1)) < 0) {
+		int e = errno;
 		if (el->el_signal->sig_no == SIGCONT) {
 			sig_set(el);
 			el_set(el, EL_REFRESH);
 			goto again;
 		}
-		if (!tried && read__fixio(el->el_infd, errno) == 0)
+		if (! tried && read__fixio(el->el_infd, e) == 0)
 			tried = 1;
 		else {
 			*cp = '\0';
+			errno = e;
 			return (-1);
 		}
 	}
@@ -369,8 +370,10 @@ el_getc(EditLine *el, char *cp)
 	(void) fprintf(el->el_errfile, "Reading a character\n");
 #endif /* DEBUG_READ */
 	num_read = (*el->el_read.read_char)(el, cp);
+	if (num_read < 0)
+		el->el_errno = errno;
 #ifdef DEBUG_READ
-	(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
+	(void) fprintf(el->el_errfile, "Got <%c> (return %d)\n", *cp, num_read);
 #endif /* DEBUG_READ */
 	return (num_read);
 }
@@ -511,6 +514,7 @@ el_gets(EditLine *el, int *nread)
 #endif /* DEBUG_EDIT */
 		/* if EOF or error */
 		if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
+			num = -1;
 #ifdef DEBUG_READ
 			(void) fprintf(el->el_errfile,
 			    "Returning from el_gets %d\n", num);




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?504b67f8.hU%2BoKTUxDdq8oHD59qxE1DdF>