/* source: xiosignal.c */ /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains code for handling signals (except SIGCHLD) */ #include "config.h" #include "xioconfig.h" /* what features are enabled */ #include "sysincludes.h" #include "mytypes.h" #include "compat.h" #include "error.h" #include "sycls.h" #define SOCAT_MAXPIDS 4 struct socat_sig_desc { int sig_use; pid_t sig_pids[SOCAT_MAXPIDS]; } ; #if 0 size_t socat_sigint_use; /* how many pids are set in following array */ static pid_t socat_sigint_pids[SOCAT_MAXPIDS]; size_t socat_sigquit_use; /* how many pids are set in following array */ static pid_t socat_sigquit_pids[SOCAT_MAXPIDS]; #else static struct socat_sig_desc socat_sighup; static struct socat_sig_desc socat_sigint; static struct socat_sig_desc socat_sigquit; #endif /* is async-signal-safe */ static struct socat_sig_desc *socat_get_sig_desc(int signum) { struct socat_sig_desc *sigdesc; switch (signum) { case SIGHUP: sigdesc = &socat_sighup; break; case SIGINT: sigdesc = &socat_sigint; break; case SIGQUIT: sigdesc = &socat_sigquit; break; default: sigdesc = NULL; break; } return sigdesc; } /* a signal handler that possibly passes the signal to sub processes */ void socatsignalpass(int sig) { int i; struct socat_sig_desc *sigdesc; int _errno; _errno = errno; diag_in_handler = 1; Notice1("socatsignalpass(sig=%d)", sig); if ((sigdesc = socat_get_sig_desc(sig)) == NULL) { /* is async-signal-safe */ diag_in_handler = 0; errno = _errno; return; } { /*debug*/ int n = 0; for (i=0; isig_use; ++i) { if (sigdesc->sig_pids[i]) { ++n; if (Kill(sigdesc->sig_pids[i], sig) < 0) { Warn2("kill("F_pid", %d): %m", sigdesc->sig_pids[i], sig); } } } if (n >= 0) Info1("socatsignalpass(): propagated signal to %d sub processes", n); } #if !HAVE_SIGACTION Signal(sig, socatsignalpass); #endif /* !HAVE_SIGACTION */ Debug("socatsignalpass() ->"); diag_in_handler = 0; errno = _errno; } /* register the sub process pid for passing of signals of type signum. Only for SIGHUP, SIGINT, and SIGQUIT! returns 0 on success or <0 if an error occurred */ int xio_opt_signal(pid_t pid, int signum) { struct socat_sig_desc *sigdesc; if ((sigdesc = socat_get_sig_desc(signum)) == NULL) { Error("sub process registered for unsupported signal"); return -1; } if (sigdesc->sig_use >= SOCAT_MAXPIDS) { Error1("too many sub processes registered for signal %d", signum); return -1; } if (sigdesc->sig_use == 0) { /* the special signal handler has not been registered yet - do it now */ #if HAVE_SIGACTION struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_flags = 0/*|SA_RESTART*/; act.sa_handler = socatsignalpass; sigfillset(&act.sa_mask); if (Sigaction(signum, &act, NULL) < 0) { /*! man does not say that errno is defined */ Warn3("sigaction(%d, %p, NULL): %s", signum, &act, strerror(errno)); } #else Signal(signum, socatsignalpass); #endif /* !HAVE_SIGACTION */ } sigdesc->sig_pids[sigdesc->sig_use++] = pid; return 0; }