A long-time missing feature (or bug, depending on how you look at it) is that a Ctrl-C at the password prompt in scp does not restore the terminal settings, thus dropping you to the command prompt without any keyboard echo. (A "reset" command will fix it.) This is a pretty regular occurance for me, and some others I've talked to - usually when you realize that the scp command you typed has a typo and decide to abort. Strangely, ssh handles this correctly, but scp does not. The single handler in scp.c is killchild(), which should pass the SIGINT along to the ssh process, which would restore the terminal. However this doesn't work for some reason I couldn't discern - perhaps the ssh process is invoked in such a way that it doesn't have access to the terminal settings? I created the attached patch which fixes the problem by saving the terminal settings at the start of program execution and restoring them on SIGINT. Although this is slightly hacky I think it is good general practice to leave the terminal in the same state that it began in. Even if the ssh process were hardlocked this would still restore the terminal. Adam -------------- next part -------------- --- openssh-3.9p1/scp.c 2004-08-13 04:19:38.000000000 -0700 +++ openssh-3.9p1-ttyfix/scp.c 2004-11-22 00:54:45.679885981 -0800 @@ -105,12 +105,19 @@ /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; +/* Save terminal state for restore on exit */ +static struct termios _saved_tio; + static void killchild(int signo) { if (do_cmd_pid > 1) kill(do_cmd_pid, signo); + /* restore the terminal to its original state */ + if (tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio) == -1) + perror("tcsetattr"); + _exit(1); } @@ -218,6 +225,11 @@ extern char *optarg; extern int optind; + if (tcgetattr(fileno(stdin), &_saved_tio) == -1) { + perror("tcgetattr"); + return 0; + } + __progname = ssh_get_progname(argv[0]); args.list = NULL;
Adam Wiggins wrote:> A long-time missing feature (or bug, depending on how you look at it) is > that a Ctrl-C at the password prompt in scp does not restore the > terminal settings, thus dropping you to the command prompt without any > keyboard echo. (A "reset" command will fix it.) This is a pretty > regular occurance for me, and some others I've talked to - usually when > you realize that the scp command you typed has a typo and decide to > abort.Yeah, after a while "stty sane" gets old, doesn't it :-?> Strangely, ssh handles this correctly, but scp does not. The single > handler in scp.c is killchild(), which should pass the SIGINT along to > the ssh process, which would restore the terminal. However this doesn't > work for some reason I couldn't discern - perhaps the ssh process is > invoked in such a way that it doesn't have access to the terminal > settings?I think the problem is fundamentally a race. scp passes the signal to ssh then immediately exits. ssh will then get the passed signal (eg a SIGINT) plus a SIGPIPE (since the other end of its stdin/stdout descriptors have closed). Same applies to sftp too. I think that in many cases the SIGPIPE is killing ssh before the SIGINT handler has a chance to restore the terminal modes. The attached patch prevents this by waiting for ssh to exit before scp does. The problem doesn't seem to occur on OpenBSD, however I'm not sure if this is simply because the dice didn't come up right, or there's some mechanism which prevents it (eg process scheduling or a different signal delivery order). (I vaguely recall someone else mentioning this but a search of the archives failed to locate it. If anyone can point me to a reference I'll make sure it's credited appropriately). -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement. -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: openssh-scp-sftp-sigint.patch Url: lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20041207/68359fcc/attachment.ksh
Maybe Matching Threads
- [Bug 241] New: When I kill scp, the underlying ssh child process remains alive
- [PATCH nbdkit 1/3] server: Disallow password=- from non-tty and fix error message (RHBZ#1842440).
- OpenSSH, Cygwin, eXceed, and SIGINT
- Background R session on Unix and SIGINT
- Catch SIGINT from user in backend C++ code