Version 1.8.0.0
[socat.git] / xiosignal.c
blob6fe1e3bda17e52f554367dff91a1b3300d6a5067
1 /* source: xiosignal.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains code for handling signals (except SIGCHLD) */
7 #include "config.h"
8 #include "xioconfig.h" /* what features are enabled */
10 #include "sysincludes.h"
12 #include "mytypes.h"
13 #include "compat.h"
14 #include "error.h"
16 #include "sycls.h"
19 #define SOCAT_MAXPIDS 4
21 struct socat_sig_desc {
22 int sig_use;
23 pid_t sig_pids[SOCAT_MAXPIDS];
24 } ;
26 #if 0
27 size_t socat_sigint_use; /* how many pids are set in following array */
28 static pid_t socat_sigint_pids[SOCAT_MAXPIDS];
29 size_t socat_sigquit_use; /* how many pids are set in following array */
30 static pid_t socat_sigquit_pids[SOCAT_MAXPIDS];
31 #else
32 static struct socat_sig_desc socat_sighup;
33 static struct socat_sig_desc socat_sigint;
34 static struct socat_sig_desc socat_sigquit;
35 #endif
38 /* is async-signal-safe */
39 static struct socat_sig_desc *socat_get_sig_desc(int signum) {
40 struct socat_sig_desc *sigdesc;
41 switch (signum) {
42 case SIGHUP: sigdesc = &socat_sighup; break;
43 case SIGINT: sigdesc = &socat_sigint; break;
44 case SIGQUIT: sigdesc = &socat_sigquit; break;
45 default: sigdesc = NULL; break;
47 return sigdesc;
50 /* a signal handler that possibly passes the signal to sub processes */
51 void socatsignalpass(int sig) {
52 int i;
53 struct socat_sig_desc *sigdesc;
54 int _errno;
56 _errno = errno;
57 diag_in_handler = 1;
58 Notice1("socatsignalpass(sig=%d)", sig);
59 if ((sigdesc = socat_get_sig_desc(sig)) == NULL) { /* is async-signal-safe */
60 diag_in_handler = 0;
61 errno = _errno;
62 return;
65 { /*debug*/
66 int n = 0;
67 for (i=0; i<sigdesc->sig_use; ++i) {
68 if (sigdesc->sig_pids[i]) {
69 ++n;
70 if (Kill(sigdesc->sig_pids[i], sig) < 0) {
71 Warn2("kill("F_pid", %d): %m",
72 sigdesc->sig_pids[i], sig);
76 if (n >= 0)
77 Info1("socatsignalpass(): propagated signal to %d sub processes", n);
79 #if !HAVE_SIGACTION
80 Signal(sig, socatsignalpass);
81 #endif /* !HAVE_SIGACTION */
82 Debug("socatsignalpass() ->");
83 diag_in_handler = 0;
84 errno = _errno;
88 /* register the sub process pid for passing of signals of type signum.
89 Only for SIGHUP, SIGINT, and SIGQUIT!
90 returns 0 on success or <0 if an error occurred */
91 int xio_opt_signal(pid_t pid, int signum) {
92 struct socat_sig_desc *sigdesc;
94 if ((sigdesc = socat_get_sig_desc(signum)) == NULL) {
95 Error("sub process registered for unsupported signal");
96 return -1;
99 if (sigdesc->sig_use >= SOCAT_MAXPIDS) {
100 Error1("too many sub processes registered for signal %d", signum);
101 return -1;
103 if (sigdesc->sig_use == 0) {
104 /* the special signal handler has not been registered yet - do it now */
105 #if HAVE_SIGACTION
106 struct sigaction act;
107 memset(&act, 0, sizeof(struct sigaction));
108 act.sa_flags = 0/*|SA_RESTART*/;
109 act.sa_handler = socatsignalpass;
110 sigfillset(&act.sa_mask);
111 if (Sigaction(signum, &act, NULL) < 0) {
112 /*! man does not say that errno is defined */
113 Warn3("sigaction(%d, %p, NULL): %s", signum, &act, strerror(errno));
115 #else
116 Signal(signum, socatsignalpass);
117 #endif /* !HAVE_SIGACTION */
119 sigdesc->sig_pids[sigdesc->sig_use++] = pid;
120 return 0;