From 63d08fc308767b775c883eaf89e3b865ebd965af Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 18 Oct 2018 20:37:59 +0100 Subject: [PATCH] uxpty: support SS_SIG* and SS_BRK specials. The SS_SIGFOO family are implemented by sending a signal directly to the pid of the immediate child process. I had had the vague idea that it might be more desirable to send the specified signal to the foreground process group in the tty. That way, you'd be able to SIGINT (say) the foreground job in a shell session, and return to the shell _prompt_ without terminating the whole session, and you could do this in an emergency even if the job was a full-screen application which had configured termios so that no keystroke generated SIGINT. But as far as I can see there's no actual way to do that. I wasn't able to find any ioctl or termios call to send a signal to a pty's foreground pgrp, and you can't even do it manually via kill(2) because first you'd have to find out what the pgrp id _is_, and according to the man pages, you can only call tcgetpgrp on the slave end of the pty and even then only if it's your controlling terminal. So SS_SIGFOO goes to the child process, because that's the only place I can find that I _can_ send it to sensibly. SS_BRK translates to tcsendbreak, of course (though I haven't actually seen any effect of calling this on a pty master, not even if I set PARMRK on the slave end which by my understanding _ought_ to show me when break events occur). --- unix/uxpty.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/unix/uxpty.c b/unix/uxpty.c index a2b01e70..6ff62b69 100644 --- a/unix/uxpty.c +++ b/unix/uxpty.c @@ -1229,8 +1229,31 @@ static void pty_size(Backend *be, int width, int height) */ static void pty_special(Backend *be, SessionSpecialCode code, int arg) { - /* Pty *pty = container_of(be, Pty, backend); */ - /* Do nothing! */ + Pty *pty = container_of(be, Pty, backend); + + if (code == SS_BRK) { + tcsendbreak(pty->master_fd, 0); + return; + } + + { + int sig = -1; + + #define SIGNAL_SUB(name) if (code == SS_SIG ## name) sig = SIG ## name; + #define SIGNAL_MAIN(name, text) SIGNAL_SUB(name) + #define SIGNALS_LOCAL_ONLY + #include "sshsignals.h" + #undef SIGNAL_SUB + #undef SIGNAL_MAIN + #undef SIGNALS_LOCAL_ONLY + + if (sig != -1) { + if (!pty->child_dead) + kill(pty->child_pid, sig); + return; + } + } + return; }