Check which getprotobynumber_r() variant to use
[socat.git] / xioshutdown.c
blobc9fef8d94cc316f9c50ae72cc012264f45dbcfa0
1 /* source: xioshutdown.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 is the source of the extended shutdown function */
8 #include "xiosysincludes.h"
9 #include "xioopen.h"
11 #include "xio-openssl.h"
13 static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
15 static void signal_kill_pid(int dummy) {
16 int _errno;
17 _errno = errno;
18 diag_in_handler = 1;
19 Notice("SIGALRM while waiting for wo child process to die, killing it now");
20 Kill(socat_kill_pid, SIGTERM);
21 diag_in_handler = 0;
22 errno = _errno;
25 int xioshutdown(xiofile_t *sock, int how) {
26 int result = 0;
28 if (sock->tag == XIO_TAG_INVALID) {
29 Error("xioshutdown(): invalid file descriptor");
30 errno = EINVAL;
31 return -1;
34 if (sock->tag == XIO_TAG_DUAL) {
35 if ((how+1)&1) {
36 result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
38 if ((how+1)&2) {
39 result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
41 return result;
44 switch (sock->stream.howtoshut) {
45 char writenull;
46 case XIOSHUT_NONE:
47 return 0;
48 case XIOSHUT_CLOSE:
49 if (Close(sock->stream.fd) < 0) {
50 Info2("close(%d): %s",
51 sock->stream.fd, strerror(errno));
53 return 0;
54 case XIOSHUT_DOWN:
55 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
56 Info3("shutdown(%d, %d): %s",
57 sock->stream.fd, how, strerror(errno));
59 return 0;
60 #if _WITH_SOCKET
61 case XIOSHUT_NULL:
62 /* send an empty packet; only useful on datagram sockets? */
63 xiowrite(sock, &writenull, 0);
64 return 0;
65 #endif /* _WITH_SOCKET */
66 default: ;
69 if (false) {
71 #if WITH_OPENSSL
72 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
73 xioshutdown_openssl(&sock->stream, how);
74 #endif /* WITH_OPENSSL */
76 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
77 if ((how+1)&1) {
78 if (Close(sock->stream.fd) < 0) {
79 Info2("close(%d): %s",
80 sock->stream.fd, strerror(errno));
83 if ((how+1)&2) {
84 if (Close(sock->stream.para.bipipe.fdout) < 0) {
85 Info2("close(%d): %s",
86 sock->stream.para.bipipe.fdout, strerror(errno));
90 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
91 if ((how+1)&1) {
92 if (Close(sock->stream.fd) < 0) {
93 Info2("close(%d): %s",
94 sock->stream.fd, strerror(errno));
97 if ((how+1)&2) {
98 if (Close(sock->stream.para.exec.fdout) < 0) {
99 Info2("close(%d): %s",
100 sock->stream.para.exec.fdout, strerror(errno));
103 #if _WITH_SOCKET
104 } else if (sock->stream.howtoend == END_SHUTDOWN) {
105 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
106 Info3("shutdown(%d, %d): %s",
107 sock->stream.fd, how, strerror(errno));
109 } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
110 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
111 Info3("shutdown(%d, %d): %s",
112 sock->stream.fd, how, strerror(errno));
114 if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
115 /* the child process might want to flush some data before terminating
117 int status = 0;
119 /* we wait for the child process to die, but to prevent timeout
120 we raise an alarm after some time.
121 NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
122 therefore we have to do the kill in the signal handler */
124 struct sigaction act;
125 sigfillset(&act.sa_mask);
126 act.sa_flags = 0;
127 act.sa_handler = signal_kill_pid;
128 Sigaction(SIGALRM, &act, NULL);
130 socat_kill_pid = sock->stream.para.exec.pid;
131 #if HAVE_SETITIMER
132 /*! with next feature release, we get usec resolution and an option */
133 #else
134 Alarm(1 /*! sock->stream.para.exec.waitdie */);
135 #endif /* !HAVE_SETITIMER */
136 if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
137 Warn3("waitpid("F_pid", %p, 0): %s",
138 sock->stream.para.exec.pid, &status, strerror(errno));
140 Alarm(0);
142 } else if ((sock->stream.dtype & XIODATA_MASK) ==
143 (XIODATA_RECVFROM & XIODATA_MASK)) {
144 if (how >= 1) {
145 if (Close(sock->stream.fd) < 0) {
146 Info2("close(%d): %s",
147 sock->stream.fd, strerror(errno));
149 sock->stream.eof = 2;
150 sock->stream.fd = -1;
152 #endif /* _WITH_SOCKET */
153 #if 0
154 } else {
155 Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
156 return -1;
157 #endif
160 #if 0
161 else if (sock->stream.howtoend == END_CLOSE &&
162 sock->stream.dtype == DATA_STREAM) {
163 return result;
165 #if WITH_TERMIOS
166 if (sock->stream.ttyvalid) {
167 if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
168 Warn2("cannot restore terminal settings on fd %d: %s",
169 sock->stream.fd, strerror(errno));
172 #endif /* WITH_TERMIOS */
173 #endif
175 return result;