mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
107 lines
2.9 KiB
C
107 lines
2.9 KiB
C
/* $Id: xiosignal.c,v 1.2 2003/12/23 21:22:38 gerhard Exp $ */
|
|
/* Copyright Gerhard Rieger 2001-2003 */
|
|
/* 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
|
|
|
|
|
|
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 eventually passes the signal to sub processes */
|
|
void socatsignalpass(int sig) {
|
|
int i;
|
|
struct socat_sig_desc *sigdesc;
|
|
|
|
Debug1("socatsignalpass(%d)", sig);
|
|
if ((sigdesc = socat_get_sig_desc(sig)) == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (i=0; i<sigdesc->sig_use; ++i) {
|
|
if (sigdesc->sig_pids[i]) {
|
|
if (Kill(sigdesc->sig_pids[i], sig) < 0) {
|
|
Warn3("kill("F_pid", %d): %s",
|
|
sigdesc->sig_pids[i], sig, strerror(errno));
|
|
}
|
|
}
|
|
}
|
|
#if !HAVE_SIGACTION
|
|
Signal(sig, socatsignalpass);
|
|
#endif /* !HAVE_SIGACTION */
|
|
Debug("socatsignalpass() ->");
|
|
}
|
|
|
|
|
|
/* 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 = SA_RESTART;
|
|
act.sa_handler = socatsignalpass;
|
|
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;
|
|
}
|
|
|