mirror of
https://github.com/sheumann/hush.git
synced 2024-12-22 14:30:31 +00:00
Revise signal handling to work with GNO.
This involved using signal() rather than sigaction(), which GNO doesn't have. signal() doesn't have the signal-blocking feature of sigaction(), but I've tried to emulate it.
This commit is contained in:
parent
036b92595c
commit
cbdfea4c97
@ -448,7 +448,11 @@ extern char *mkdtemp(char *template) FAST_FUNC;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SIGHANDLER_T
|
||||
# ifndef __GNO__
|
||||
typedef void (*sighandler_t)(int);
|
||||
# else
|
||||
typedef void (*sighandler_t)(int, int);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STPCPY
|
||||
|
@ -14,17 +14,6 @@
|
||||
/* All known arches use small ints for signals */
|
||||
smallint bb_got_signal;
|
||||
|
||||
void record_signo(int signo)
|
||||
{
|
||||
bb_got_signal = signo;
|
||||
}
|
||||
|
||||
/* Saves 2 bytes on x86! Oh my... */
|
||||
int FAST_FUNC sigaction_set(int signum, const struct sigaction *act)
|
||||
{
|
||||
return sigaction(signum, act, NULL);
|
||||
}
|
||||
|
||||
int FAST_FUNC sigprocmask_allsigs(int how)
|
||||
{
|
||||
sigset_t set;
|
||||
@ -47,35 +36,6 @@ void FAST_FUNC bb_signals(int sigs, void (*f)(int))
|
||||
}
|
||||
}
|
||||
|
||||
void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int))
|
||||
{
|
||||
int sig_no = 0;
|
||||
int bit = 1;
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = f;
|
||||
/*sa.sa_flags = 0;*/
|
||||
/*sigemptyset(&sa.sa_mask); - hope memset did it*/
|
||||
|
||||
while (sigs) {
|
||||
if (sigs & bit) {
|
||||
sigs -= bit;
|
||||
sigaction_set(sig_no, &sa);
|
||||
}
|
||||
sig_no++;
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void FAST_FUNC sig_block(int sig)
|
||||
{
|
||||
sigset_t ss;
|
||||
sigemptyset(&ss);
|
||||
sigaddset(&ss, sig);
|
||||
sigprocmask(SIG_BLOCK, &ss, NULL);
|
||||
}
|
||||
|
||||
void FAST_FUNC sig_unblock(int sig)
|
||||
{
|
||||
sigset_t ss;
|
||||
@ -84,13 +44,6 @@ void FAST_FUNC sig_unblock(int sig)
|
||||
sigprocmask(SIG_UNBLOCK, &ss, NULL);
|
||||
}
|
||||
|
||||
void FAST_FUNC wait_for_any_sig(void)
|
||||
{
|
||||
sigset_t ss;
|
||||
sigemptyset(&ss);
|
||||
sigsuspend(&ss);
|
||||
}
|
||||
|
||||
/* Assuming the sig is fatal */
|
||||
void FAST_FUNC kill_myself_with_sig(int sig)
|
||||
{
|
||||
@ -99,23 +52,3 @@ void FAST_FUNC kill_myself_with_sig(int sig)
|
||||
raise(sig);
|
||||
_exit(sig | 128); /* Should not reach it */
|
||||
}
|
||||
|
||||
void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int))
|
||||
{
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
/*sigemptyset(&sa.sa_mask);*/
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sa.sa_handler = handler;
|
||||
sigaction_set(sig, &sa);
|
||||
}
|
||||
|
||||
void FAST_FUNC signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int))
|
||||
{
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
/*sigemptyset(&sa.sa_mask);*/
|
||||
/*sa.sa_flags = 0;*/
|
||||
sa.sa_handler = handler;
|
||||
sigaction_set(sig, &sa);
|
||||
}
|
||||
|
64
shell/hush.c
64
shell/hush.c
@ -826,19 +826,25 @@ struct globals {
|
||||
unsigned long memleak_value;
|
||||
int debug_indent;
|
||||
#endif
|
||||
#ifndef __GNO__
|
||||
struct sigaction sa;
|
||||
#endif
|
||||
char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2];
|
||||
};
|
||||
#define G (*ptr_to_globals)
|
||||
/* Not #defining name to G.name - this quickly gets unwieldy
|
||||
* (too many defines). Also, I actually prefer to see when a variable
|
||||
* is global, thus "G." prefix is a useful hint */
|
||||
#define INIT_G() do { \
|
||||
#ifndef __GNO__
|
||||
# define INIT_G() do { \
|
||||
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
|
||||
/* memset(&G.sa, 0, sizeof(G.sa)); */ \
|
||||
sigfillset(&G.sa.sa_mask); \
|
||||
G.sa.sa_flags = SA_RESTART; \
|
||||
} while (0)
|
||||
#else
|
||||
# define INIT_G() SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)))
|
||||
#endif
|
||||
|
||||
|
||||
/* Function prototypes for builtins */
|
||||
@ -1478,8 +1484,28 @@ static void record_pending_signo(int sig)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __GNO__
|
||||
# pragma databank 1
|
||||
static void record_pending_signo_wrapper_gno(int sig, int code)
|
||||
{
|
||||
/* Block all blockable signals now, to attempt to emulate the
|
||||
* behavior if this handler had been installed by the original
|
||||
* sigaction() call rather than GNO's signal().
|
||||
*/
|
||||
sigset_t new_mask, old_mask;
|
||||
sigfillset(&new_mask);
|
||||
sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
|
||||
record_pending_signo(sig);
|
||||
|
||||
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
}
|
||||
# pragma databank 0
|
||||
#endif
|
||||
|
||||
static sighandler_t install_sighandler(int sig, sighandler_t handler)
|
||||
{
|
||||
#ifndef __GNO__
|
||||
struct sigaction old_sa;
|
||||
|
||||
/* We could use signal() to install handlers... almost:
|
||||
@ -1494,6 +1520,10 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler)
|
||||
G.sa.sa_handler = handler;
|
||||
sigaction(sig, &G.sa, &old_sa);
|
||||
return old_sa.sa_handler;
|
||||
#else
|
||||
/* GNO doesn't have sigaction(), so we'll have to use signal(). */
|
||||
return signal(sig, handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_HUSH_JOB
|
||||
@ -1527,6 +1557,26 @@ static void sigexit(int sig)
|
||||
|
||||
kill_myself_with_sig(sig); /* does not return */
|
||||
}
|
||||
|
||||
# ifdef __GNO__
|
||||
# pragma databank 1
|
||||
static void sigexit_wrapper_gno(int sig, int code)
|
||||
{
|
||||
/* Block all blockable signals now, to attempt to emulate the
|
||||
* behavior if this handler had been installed by the original
|
||||
* sigaction() call rather than GNO's signal().
|
||||
*/
|
||||
sigset_t new_mask, old_mask;
|
||||
sigfillset(&new_mask);
|
||||
sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||
|
||||
sigexit(sig);
|
||||
|
||||
// Shouldn't get here, but just in case...
|
||||
sigprocmask(SIG_SETMASK, &old_mask, NULL);
|
||||
}
|
||||
# pragma databank 0
|
||||
# endif
|
||||
#else
|
||||
|
||||
# define disable_restore_tty_pgrp_on_exit() ((void)0)
|
||||
@ -1543,12 +1593,20 @@ static sighandler_t pick_sighandler(unsigned sig)
|
||||
#if ENABLE_HUSH_JOB
|
||||
/* is sig fatal? */
|
||||
if (G_fatal_sig_mask & sigmask)
|
||||
# ifndef __GNO__
|
||||
handler = sigexit;
|
||||
# else
|
||||
handler = sigexit_wrapper_gno;
|
||||
# endif
|
||||
else
|
||||
#endif
|
||||
/* sig has special handling? */
|
||||
if (G.special_sig_mask & sigmask) {
|
||||
#ifndef __GNO__
|
||||
handler = record_pending_signo;
|
||||
#else
|
||||
handler = record_pending_signo_wrapper_gno;
|
||||
#endif
|
||||
/* TTIN/TTOU/TSTP can't be set to record_pending_signo
|
||||
* in order to ignore them: they will be raised
|
||||
* in an endless loop when we try to do some
|
||||
@ -8632,7 +8690,11 @@ static int FAST_FUNC builtin_trap(char **argv)
|
||||
continue;
|
||||
|
||||
if (new_cmd)
|
||||
#ifndef __GNO__
|
||||
handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
|
||||
#else
|
||||
handler = (new_cmd[0] ? record_pending_signo_wrapper_gno : SIG_IGN);
|
||||
#endif
|
||||
else
|
||||
/* We are removing trap handler */
|
||||
handler = pick_sighandler(sig);
|
||||
|
Loading…
Reference in New Issue
Block a user