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) */
8 #include "xioconfig.h" /* what features are enabled */
10 #include "sysincludes.h"
19 #define SOCAT_MAXPIDS 4
21 struct socat_sig_desc
{
23 pid_t sig_pids
[SOCAT_MAXPIDS
];
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
];
32 static struct socat_sig_desc socat_sighup
;
33 static struct socat_sig_desc socat_sigint
;
34 static struct socat_sig_desc socat_sigquit
;
38 /* is async-signal-safe */
39 static struct socat_sig_desc
*socat_get_sig_desc(int signum
) {
40 struct socat_sig_desc
*sigdesc
;
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;
50 /* a signal handler that possibly passes the signal to sub processes */
51 void socatsignalpass(int sig
) {
53 struct socat_sig_desc
*sigdesc
;
58 Notice1("socatsignalpass(sig=%d)", sig
);
59 if ((sigdesc
= socat_get_sig_desc(sig
)) == NULL
) { /* is async-signal-safe */
67 for (i
=0; i
<sigdesc
->sig_use
; ++i
) {
68 if (sigdesc
->sig_pids
[i
]) {
70 if (Kill(sigdesc
->sig_pids
[i
], sig
) < 0) {
71 Warn2("kill("F_pid
", %d): %m",
72 sigdesc
->sig_pids
[i
], sig
);
77 Info1("socatsignalpass(): propagated signal to %d sub processes", n
);
80 Signal(sig
, socatsignalpass
);
81 #endif /* !HAVE_SIGACTION */
82 Debug("socatsignalpass() ->");
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");
99 if (sigdesc
->sig_use
>= SOCAT_MAXPIDS
) {
100 Error1("too many sub processes registered for signal %d", signum
);
103 if (sigdesc
->sig_use
== 0) {
104 /* the special signal handler has not been registered yet - do it now */
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
));
116 Signal(signum
, socatsignalpass
);
117 #endif /* !HAVE_SIGACTION */
119 sigdesc
->sig_pids
[sigdesc
->sig_use
++] = pid
;