From 72eca76d20674c4d8018c5e945f45a4f1a340943 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 14 Oct 2018 10:05:23 +0100 Subject: [PATCH] New system for handling SSH signals. This is in much the same style as the ttymodes revamp, using a header file which can be included in different ways to either iterate over _all_ the signals in the known list or just the ones for which a definition exists on the target OS. So this doesn't actually _remove_ the horrid pile of ifdefs in mainchan_rcvd_exit_signal, but at least it puts it somewhere less intrusive and more reusable. --- mainchan.c | 124 +++++++++++++-------------------------------------- putty.h | 13 ++++-- sshsignals.h | 53 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 97 deletions(-) create mode 100644 sshsignals.h diff --git a/mainchan.c b/mainchan.c index e1b75eb6..f70b7936 100644 --- a/mainchan.c +++ b/mainchan.c @@ -432,57 +432,20 @@ static int mainchan_rcvd_exit_signal( char *signame_str; /* - * Translate the signal description back into a locally - * meaningful number. + * Translate the signal description back into a locally meaningful + * number, or 128 if the string didn't match any we recognise. */ + exitcode = 128; - if (0) - ; -#define TRANSLATE_SIGNAL(s) \ - else if (ptrlen_eq_string(signame, #s)) \ - exitcode = 128 + SIG ## s -#ifdef SIGABRT - TRANSLATE_SIGNAL(ABRT); -#endif -#ifdef SIGALRM - TRANSLATE_SIGNAL(ALRM); -#endif -#ifdef SIGFPE - TRANSLATE_SIGNAL(FPE); -#endif -#ifdef SIGHUP - TRANSLATE_SIGNAL(HUP); -#endif -#ifdef SIGILL - TRANSLATE_SIGNAL(ILL); -#endif -#ifdef SIGINT - TRANSLATE_SIGNAL(INT); -#endif -#ifdef SIGKILL - TRANSLATE_SIGNAL(KILL); -#endif -#ifdef SIGPIPE - TRANSLATE_SIGNAL(PIPE); -#endif -#ifdef SIGQUIT - TRANSLATE_SIGNAL(QUIT); -#endif -#ifdef SIGSEGV - TRANSLATE_SIGNAL(SEGV); -#endif -#ifdef SIGTERM - TRANSLATE_SIGNAL(TERM); -#endif -#ifdef SIGUSR1 - TRANSLATE_SIGNAL(USR1); -#endif -#ifdef SIGUSR2 - TRANSLATE_SIGNAL(USR2); -#endif -#undef TRANSLATE_SIGNAL - else - exitcode = 128; + #define SIGNAL_SUB(s) \ + if (ptrlen_eq_string(signame, #s)) \ + exitcode = 128 + SIG ## s; + #define SIGNAL_MAIN(s, text) SIGNAL_SUB(s) + #define SIGNALS_LOCAL_ONLY + #include "sshsignals.h" + #undef SIGNAL_SUB + #undef SIGNAL_MAIN + #undef SIGNALS_LOCAL_ONLY ssh_got_exitcode(mc->ppl->ssh, exitcode); if (exitcode == 128) @@ -509,31 +472,6 @@ static int mainchan_rcvd_exit_signal_numeric( return TRUE; } -/* - * List of signal names defined by RFC 4254. These include all the ISO - * C signals, but are a subset of the POSIX required signals. - * - * The list macro takes parameters MAIN and SUB, which is an arbitrary - * UI decision to expose the signals we think users are most likely to - * want, with extra descriptive text, and relegate the less probable - * ones to a submenu for people who know what they're doing. - */ -#define SIGNAL_LIST(MAIN, SUB) \ - MAIN(INT, "Interrupt") \ - MAIN(TERM, "Terminate") \ - MAIN(KILL, "Kill") \ - MAIN(QUIT, "Quit") \ - MAIN(HUP, "Hangup") \ - SUB(ABRT) \ - SUB(ALRM) \ - SUB(FPE) \ - SUB(ILL) \ - SUB(PIPE) \ - SUB(SEGV) \ - SUB(USR1) \ - SUB(USR2) \ - /* end of list */ - void mainchan_get_specials( mainchan *mc, add_special_fn_t add_special, void *ctx) { @@ -541,36 +479,36 @@ void mainchan_get_specials( add_special(ctx, "Break", SS_BRK, 0); - #define ADD_MAIN(name, desc) \ + #define SIGNAL_MAIN(name, desc) \ add_special(ctx, "SIG" #name " (" desc ")", SS_SIG ## name, 0); - #define ADD_SUB(name) \ - add_special(ctx, "SIG" #name, SS_SIG ## name, 0); + #define SIGNAL_SUB(name) + #include "sshsignals.h" + #undef SIGNAL_MAIN + #undef SIGNAL_SUB - #define NO_ADD_SUB(name) - #define NO_ADD_MAIN(name, desc) - - SIGNAL_LIST(ADD_MAIN, NO_ADD_SUB); add_special(ctx, "More signals", SS_SUBMENU, 0); - SIGNAL_LIST(NO_ADD_MAIN, ADD_SUB); - add_special(ctx, NULL, SS_EXITMENU, 0); - #undef ADD_MAIN - #undef ADD_SUB - #undef NO_ADD_MAIN - #undef NO_ADD_SUB + #define SIGNAL_MAIN(name, desc) + #define SIGNAL_SUB(name) \ + add_special(ctx, "SIG" #name, SS_SIG ## name, 0); + #include "sshsignals.h" + #undef SIGNAL_MAIN + #undef SIGNAL_SUB + + add_special(ctx, NULL, SS_EXITMENU, 0); } static const char *ssh_signal_lookup(SessionSpecialCode code) { - #define CHECK_SUB(name) \ + #define SIGNAL_SUB(name) \ if (code == SS_SIG ## name) return #name; - #define CHECK_MAIN(name, desc) CHECK_SUB(name) + #define SIGNAL_MAIN(name, desc) SIGNAL_SUB(name) + #include "sshsignals.h" + #undef SIGNAL_MAIN + #undef SIGNAL_SUB - SIGNAL_LIST(CHECK_MAIN, CHECK_SUB); + /* If none of those clauses matched, fail lookup. */ return NULL; - - #undef CHECK_MAIN - #undef CHECK_SUB } void mainchan_special_cmd(mainchan *mc, SessionSpecialCode code, int arg) diff --git a/putty.h b/putty.h index dcf37286..6c380360 100644 --- a/putty.h +++ b/putty.h @@ -211,11 +211,16 @@ typedef enum { /* * Send a POSIX-style signal. (Useful in SSH and also pterm.) + * + * We use the master list in sshsignals.h to define these enum + * values, which will come out looking like names of the form + * SS_SIGABRT, SS_SIGINT etc. */ - SS_SIGABRT, SS_SIGALRM, SS_SIGFPE, SS_SIGHUP, SS_SIGILL, - SS_SIGINT, SS_SIGKILL, SS_SIGPIPE, SS_SIGQUIT, SS_SIGSEGV, - SS_SIGTERM, SS_SIGUSR1, SS_SIGUSR2, - + #define SIGNAL_MAIN(name, text) SS_SIG ## name, + #define SIGNAL_SUB(name) SS_SIG ## name, + #include "sshsignals.h" + #undef SIGNAL_MAIN + #undef SIGNAL_SUB /* * These aren't really special commands, but they appear in the diff --git a/sshsignals.h b/sshsignals.h new file mode 100644 index 00000000..b213c34f --- /dev/null +++ b/sshsignals.h @@ -0,0 +1,53 @@ +/* + * List of signal names known to SSH, indicating whether PuTTY's UI + * for special session commands likes to put them in the main specials + * menu or in a submenu (and if the former, what title they have). + * + * This is a separate header file rather than my usual style of a + * parametric list macro, because in this case I need to be able to + * #ifdef out each mode in case it's not defined on a particular + * target system. + * + * If you want only the locally defined signals, #define + * SIGNALS_LOCAL_ONLY before including this header. + */ + +#if !defined SIGNALS_LOCAL_ONLY || defined SIGINT +SIGNAL_MAIN(INT, "Interrupt") +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGTERM +SIGNAL_MAIN(TERM, "Terminate") +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGKILL +SIGNAL_MAIN(KILL, "Kill") +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGQUIT +SIGNAL_MAIN(QUIT, "Quit") +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGHUP +SIGNAL_MAIN(HUP, "Hangup") +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGABRT +SIGNAL_SUB(ABRT) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGALRM +SIGNAL_SUB(ALRM) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGFPE +SIGNAL_SUB(FPE) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGILL +SIGNAL_SUB(ILL) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGPIPE +SIGNAL_SUB(PIPE) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGSEGV +SIGNAL_SUB(SEGV) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGUSR1 +SIGNAL_SUB(USR1) +#endif +#if !defined SIGNALS_LOCAL_ONLY || defined SIGUSR2 +SIGNAL_SUB(USR2) +#endif