File: xiosignal.c

package info (click to toggle)
socat 1.7.3.2-2
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 3,888 kB
  • sloc: ansic: 28,032; sh: 11,782; makefile: 146
file content (116 lines) | stat: -rw-r--r-- 3,207 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* 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(%d)", sig);
   if ((sigdesc = socat_get_sig_desc(sig)) == NULL) {	/* is async-signal-safe */
      diag_in_handler = 0;
      errno = _errno;
      return;
   }

   for (i=0; i<sigdesc->sig_use; ++i) {
      if (sigdesc->sig_pids[i]) {
	 if (Kill(sigdesc->sig_pids[i], sig) < 0) {
	    Warn2("kill("F_pid", %d): %m",
		  sigdesc->sig_pids[i], sig);
	 }
      }
   }
#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;
}