]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: In the editline(3) branch of the sftp(1) event loop,
authorschwarze@openbsd.org <schwarze@openbsd.org>
Thu, 12 Aug 2021 09:59:00 +0000 (09:59 +0000)
committerDamien Miller <djm@mindrot.org>
Thu, 12 Aug 2021 13:05:33 +0000 (23:05 +1000)
handle SIGINT rather than ignoring it, such that the user can use Ctrl-C to
discard the currently edited command line and get a fresh prompt, just like
in ftp(1), bc(1), and in shells.

It is critical to not use ssl_signal() for this particular case
because that function unconditionally sets SA_RESTART, but here we
need the signal to interrupt the read(2) in the el_gets(3) event loop.

OK dtucker@ deraadt@

OpenBSD-Commit-ID: 8025115a773f52e9bb562eaab37ea2e021cc7299

sftp.c

diff --git a/sftp.c b/sftp.c
index 95b2e0b7c0f6fb50b291c0aa637dcad3ce0eec01..69f84cdcf1a495b444e807c648a3b2948400f7e1 100644 (file)
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.210 2021/08/07 00:12:09 djm Exp $ */
+/* $OpenBSD: sftp.c,v 1.211 2021/08/12 09:59:00 schwarze Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -252,6 +252,13 @@ cmd_interrupt(int signo)
        errno = olderrno;
 }
 
+/* ARGSUSED */
+static void
+read_interrupt(int signo)
+{
+       interrupted = 1;
+}
+
 /*ARGSUSED*/
 static void
 sigchld_handler(int sig)
@@ -2197,8 +2204,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
        interactive = !batchmode && isatty(STDIN_FILENO);
        err = 0;
        for (;;) {
-               ssh_signal(SIGINT, SIG_IGN);
-
                if (el == NULL) {
                        if (interactive)
                                printf("sftp> ");
@@ -2211,10 +2216,21 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
 #ifdef USE_LIBEDIT
                        const char *line;
                        int count = 0;
-
+                       struct sigaction sa;
+
+                       interrupted = 0;
+                       memset(&sa, 0, sizeof(sa));
+                       sa.sa_handler = read_interrupt;
+                       if (sigaction(SIGINT, &sa, NULL) == -1) {
+                               debug3("sigaction(%s): %s",
+                                   strsignal(SIGINT), strerror(errno));
+                               break;
+                       }
                        if ((line = el_gets(el, &count)) == NULL ||
                            count <= 0) {
                                printf("\n");
+                               if (interrupted)
+                                       continue;
                                break;
                        }
                        history(hl, &hev, H_ENTER, line);