NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/46943: editline(3): add EL_RESTART_READ.



>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 {



Home | Main Index | Thread Index | Old Index