From 51a02d25af355d4e819e8c97481adb2cf17ab975 Mon Sep 17 00:00:00 2001 From: schwarze Date: Thu, 12 Aug 2021 09:59:00 +0000 Subject: [PATCH] In the editline(3) branch of the sftp(1) event loop, 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@ --- usr.bin/ssh/sftp.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/usr.bin/ssh/sftp.c b/usr.bin/ssh/sftp.c index 7a82302858f..8b4c090b74c 100644 --- a/usr.bin/ssh/sftp.c +++ b/usr.bin/ssh/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 * @@ -230,6 +230,13 @@ cmd_interrupt(int signo) errno = olderrno; } +/* ARGSUSED */ +static void +read_interrupt(int signo) +{ + interrupted = 1; +} + /*ARGSUSED*/ static void sigchld_handler(int sig) @@ -2168,9 +2175,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) const char *line; int count = 0; - ssh_signal(SIGINT, SIG_IGN); - if (el == NULL) { + ssh_signal(SIGINT, SIG_IGN); if (interactive) printf("sftp> "); if (fgets(cmd, sizeof(cmd), infile) == NULL) { @@ -2179,9 +2185,21 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) break; } } else { + 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); -- 2.20.1