This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 9545e120545f07de4315fb6282d7bd14d666240b
Author: raiden00pl <[email protected]>
AuthorDate: Sat Aug 22 07:42:22 2026 +0200

    system/readline: add caller-selectable control handling
    
    Let CPython handle Ctrl-D and signals without changing existing NSH 
behavior.
    
    Signed-off-by: raiden00pl <[email protected]>
    Assisted-by: Claude Code
---
 include/system/readline.h         | 18 ++++++++++++++++++
 system/readline/readline.h        |  2 +-
 system/readline/readline_common.c | 15 ++++++++++++---
 system/readline/readline_fd.c     | 33 +++++++++++++++++++++++++++++----
 4 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/include/system/readline.h b/include/system/readline.h
index 8f40c92c1..2deb2a976 100644
--- a/include/system/readline.h
+++ b/include/system/readline.h
@@ -42,6 +42,11 @@
 #  undef CONFIG_READLINE_TABCOMPLETION
 #endif
 
+/* readline_fd_ex() options */
+
+#define READLINE_CTRL_D_EOF      (1 << 0)
+#define READLINE_RETURN_ON_EINTR (1 << 1)
+
 /* Make sure that the are valid values for all tab-completion settings */
 
 #ifdef CONFIG_READLINE_TABCOMPLETION
@@ -176,6 +181,19 @@ FAR const struct extmatch_vtable_s *
 
 ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd);
 
+/****************************************************************************
+ * Name: readline_fd_ex
+ *
+ *   readline_fd_ex() extends readline_fd() with caller-selected options.
+ *   READLINE_CTRL_D_EOF makes Ctrl-D return EOF when the line is empty.
+ *   READLINE_RETURN_ON_EINTR makes an interrupted input read return -EINTR
+ *   instead of being retried.
+ *
+ ****************************************************************************/
+
+ssize_t readline_fd_ex(FAR char *buf, int buflen, int infd, int outfd,
+                       unsigned int options);
+
 /****************************************************************************
  * Name: readline_stream
  *
diff --git a/system/readline/readline.h b/system/readline/readline.h
index b4b5927f8..c255a6580 100644
--- a/system/readline/readline.h
+++ b/system/readline/readline.h
@@ -84,6 +84,6 @@ struct rl_common_s
  ****************************************************************************/
 
 ssize_t readline_common(FAR struct rl_common_s *vtbl,
-                        FAR char *buf, int buflen);
+                        FAR char *buf, int buflen, unsigned int options);
 
 #endif /* __APPS_SYSTEM_READLINE_READLINE_H */
diff --git a/system/readline/readline_common.c 
b/system/readline/readline_common.c
index 872fcf768..742759ebb 100644
--- a/system/readline/readline_common.c
+++ b/system/readline/readline_common.c
@@ -49,12 +49,13 @@
 #  define RL_CMDHIST_LINELEN    CONFIG_READLINE_CMD_HISTORY_LINELEN
 #endif
 
+#define CTRL_D  4   /* ^D - EOF or delete at cursor */
+
 #ifdef CONFIG_READLINE_EDIT_EMACS
-/* Emacs-style control key codes */
+/* Additional Emacs-style control key codes */
 
 #  define CTRL_A  1   /* ^A - Home */
 #  define CTRL_B  2   /* ^B - Left */
-#  define CTRL_D  4   /* ^D - Delete at cursor */
 #  define CTRL_E  5   /* ^E - End */
 #  define CTRL_F  6   /* ^F - Right */
 #  define CTRL_K  11  /* ^K - Kill to end of line */
@@ -849,7 +850,7 @@ FAR const struct extmatch_vtable_s *
  ****************************************************************************/
 
 ssize_t readline_common(FAR struct rl_common_s *vtbl, FAR char *buf,
-                        int buflen)
+                        int buflen, unsigned int options)
 {
   int escape;
   int nch;
@@ -1440,6 +1441,14 @@ ssize_t readline_common(FAR struct rl_common_s *vtbl, 
FAR char *buf,
           return submit_line(buf, nch);
         }
 
+      /* Some callers use the conventional empty-line Ctrl-D as EOF. */
+
+      else if (ch == CTRL_D && (options & READLINE_CTRL_D_EOF) != 0 &&
+               nch == 0)
+        {
+          return EOF;
+        }
+
       /* Emacs-style control keys */
 
 #ifdef CONFIG_READLINE_EDIT_EMACS
diff --git a/system/readline/readline_fd.c b/system/readline/readline_fd.c
index 0490af266..cc9d5cb18 100644
--- a/system/readline/readline_fd.c
+++ b/system/readline/readline_fd.c
@@ -43,9 +43,11 @@
 struct readline_s
 {
   struct rl_common_s vtbl;
-  int infd;
+  unsigned int       options;
+  int                infd;
+  int                errcode;
 #ifdef CONFIG_READLINE_ECHO
-  int outfd;
+  int                outfd;
 #endif
 };
 
@@ -93,7 +95,13 @@ static int readline_getc(FAR struct rl_common_s *vtbl)
            */
 
           int errcode = errno;
-          if (errcode != EINTR)
+          if (errcode == EINTR &&
+              (priv->options & READLINE_RETURN_ON_EINTR) != 0)
+            {
+              priv->errcode = errcode;
+              return EOF;
+            }
+          else if (errcode != EINTR)
             {
               /* Return EOF on any errors that we cannot handle */
 
@@ -219,6 +227,16 @@ static void readline_write(FAR struct rl_common_s *vtbl,
  ****************************************************************************/
 
 ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd)
+{
+  return readline_fd_ex(buf, buflen, infd, outfd, 0);
+}
+
+/****************************************************************************
+ * Name: readline_fd_ex
+ ****************************************************************************/
+
+ssize_t readline_fd_ex(FAR char *buf, int buflen, int infd, int outfd,
+                       unsigned int options)
 {
   UNUSED(outfd);
 
@@ -244,6 +262,8 @@ ssize_t readline_fd(FAR char *buf, int buflen, int infd, 
int outfd)
 
   vtbl.vtbl.rl_getc  = readline_getc;
   vtbl.infd          = infd;
+  vtbl.options       = options;
+  vtbl.errcode       = 0;
 
 #ifdef CONFIG_READLINE_ECHO
   vtbl.vtbl.rl_putc  = readline_putc;
@@ -253,12 +273,17 @@ ssize_t readline_fd(FAR char *buf, int buflen, int infd, 
int outfd)
 
   /* The let the common readline logic do the work */
 
-  ret = readline_common(&vtbl.vtbl, buf, buflen);
+  ret = readline_common(&vtbl.vtbl, buf, buflen, options);
 
   if (restore_termios)
     {
       tcsetattr(infd, TCSANOW, &cfg);
     }
 
+  if (vtbl.errcode != 0)
+    {
+      ret = -vtbl.errcode;
+    }
+
   return ret;
 }

Reply via email to