NetBSD Problem Report #46943
From www@NetBSD.org Tue Sep 11 11:53:44 2012
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
by www.NetBSD.org (Postfix) with ESMTP id 902A363B9BC
for <gnats-bugs@gnats.NetBSD.org>; Tue, 11 Sep 2012 11:53:44 +0000 (UTC)
Message-Id: <20120911115343.4D24A63B86D@www.NetBSD.org>
Date: Tue, 11 Sep 2012 11:53:43 +0000 (UTC)
From: sdaoden@gmail.com
Reply-To: sdaoden@gmail.com
To: gnats-bugs@NetBSD.org
Subject: editline(3): add EL_RESTART_READ.
X-Send-Pr-Version: www-1.0
>Number: 46943
>Category: lib
>Synopsis: editline(3): add EL_RESTART_READ.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: lib-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Sep 11 11:55:00 +0000 2012
>Originator: Steffen Nurpmeso
>Release: netbsd-6-base
>Organization:
>Environment:
None. netbsd-6-base as of 08-31, manually patched up.
>Description:
Add an option to automatically restart read(2) for EINTR
errors.
While trying to wrap my head around FreeBSD PR bin/169773
(still no good for some more minutes) the question arose
how to handle EINTR errors for el_gets().
Normally one could say el_gets_continue() to restart editing,
but that doesn't exist. If you are on a sh(1) prompt, what
to do? Loose user content, blablabla :-) (Sorry, tired.)
Options:
- fiddle around with signal handling to force auto-restart.
Sometimes hard to do.
- fiddle around with former user input and a renew prompt.
'Am new to editline(3), HowTo?
Also this looks shitty (sorry), jumping to a new line etc.
- let editline(3) handle EINTR cases on special request.
Solution presented here. At low level, but documented
to possibly be restricted to builtin character reading
(though user-hook my check via el_get() what desired
behaviour is, of course).
>How-To-Repeat:
Try to deal with EINTR when implementing sh(1) prompt easily,
i.e., by calling el_gets(), without irritating user.
(Yes, not doing so myself, only trying to find shallow solution and better patch for FreeBSD.)
>Fix:
Ok, i'm still not running NetBSD here, so this is *only* a source diff.
(A rather similar one worked fine on FreeBSD yesterday. After looking
at NetBSD sources it must be said that this is some further, but still,
that shouldn't matter for the problem in general and this diff in
particular. Thanks!)
Add an EL_RESTART_READ option to editline(3)
Make it possible to realize read(2) restarts after EINTR errors
without actually going the expensive (and sometimes impossible
or at least undesirable) way through signal handling.
---
src/lib/libedit/editline.3 | 20 ++++++++++++++++++++
src/lib/libedit/el.c | 12 ++++++++++++
src/lib/libedit/el.h | 1 +
src/lib/libedit/histedit.h | 2 ++
src/lib/libedit/read.c | 2 ++
5 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/src/lib/libedit/editline.3 b/src/lib/libedit/editline.3
index d44037c..7540562 100644
--- a/src/lib/libedit/editline.3
+++ b/src/lib/libedit/editline.3
@@ -432,6 +432,22 @@ check this
(using
.Fn el_get )
to determine if editing should be enabled or not.
+.It Dv EL_RESTART_READ , Fa "int flag"
+If
+.Fa flag
+is not zero (as per default),
+then
+.Fn el_getc
+and
+.Fn el_gets
+will restart character reads that failed with
+.Dv EINTR
+errors.
+Note this may be restricted to the builtin character read function
+.Dv EL_BUILTIN_GETCFN
+(see
+.Dv EL_GETCFN
+below).
.It Dv EL_UNBUFFERED , Fa "int flag"
If
.Fa flag
@@ -541,6 +557,10 @@ Retrieve
previously registered with the corresponding
.Fn el_set
call.
+.It Dv EL_RESTART_READ , Fa "int"
+Return non-zero if reading of characters is automatically restarted for
+.Dv EINTR
+errors.
.It Dv EL_UNBUFFERED , Fa "int"
Return non-zero if unbuffered mode is enabled.
.It Dv EL_PREP_TERM , Fa "int"
diff --git a/src/lib/libedit/el.c b/src/lib/libedit/el.c
index f44e8a5..9d27987 100644
--- a/src/lib/libedit/el.c
+++ b/src/lib/libedit/el.c
@@ -298,6 +298,13 @@ FUN(el,set)(EditLine *el, int op, ...)
el->el_data = va_arg(ap, void *);
break;
+ case EL_RESTART_READ:
+ if (va_arg(ap, int))
+ el->el_flags |= RESTART_READ;
+ else
+ el->el_flags &= ~RESTART_READ;
+ break;
+
case EL_UNBUFFERED:
rv = va_arg(ap, int);
if (rv && !(el->el_flags & UNBUFFERED)) {
@@ -438,6 +445,11 @@ FUN(el,get)(EditLine *el, int op, ...)
rv = 0;
break;
+ case EL_RESTART_READ:
+ *va_arg(ap, int *) = ((el->el_flags & RESTART_READ) != 0);
+ rv = 0;
+ break;
+
case EL_UNBUFFERED:
*va_arg(ap, int *) = ((el->el_flags & UNBUFFERED) != 0);
rv = 0;
diff --git a/src/lib/libedit/el.h b/src/lib/libedit/el.h
index 70c67b8..18cdde7 100644
--- a/src/lib/libedit/el.h
+++ b/src/lib/libedit/el.h
@@ -61,6 +61,7 @@
#define IGNORE_EXTCHARS 0x20 /* Ignore characters read > 0xff */
#define NARROW_HISTORY 0x40
#define NARROW_READ 0x80
+#define RESTART_READ 0x100
typedef int bool_t; /* True or not */
diff --git a/src/lib/libedit/histedit.h b/src/lib/libedit/histedit.h
index b066593..86c2220 100644
--- a/src/lib/libedit/histedit.h
+++ b/src/lib/libedit/histedit.h
@@ -156,6 +156,8 @@ unsigned char _el_fn_complete(EditLine *, int);
#define EL_PROMPT_ESC 21 /* , prompt_func, Char); set/get */
#define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */
#define EL_RESIZE 23 /* , el_zfunc_t, void *); set */
+#define EL_RESTART_READ 24 /* , int); set/get */
+
#define EL_BUILTIN_GETCFN (NULL)
diff --git a/src/lib/libedit/read.c b/src/lib/libedit/read.c
index 7986394..3e2ef4b 100644
--- a/src/lib/libedit/read.c
+++ b/src/lib/libedit/read.c
@@ -331,6 +331,8 @@ read_char(EditLine *el, Char *cp)
default:
break;
}
+ if (e == EINTR && (el->el_flags & RESTART_READ))
+ goto again;
if (!tried && read__fixio(el->el_infd, e) == 0)
tried = 1;
else {
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.