version 1.7.3.0
[socat.git] / xioshutdown.c
blobe7833de4bdb4f19cdee19bef2b49532b1942e5e3
1 /* source: xioshutdown.c */
2 /* Copyright Gerhard Rieger */
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 static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
13 static void signal_kill_pid(int dummy) {
14 int _errno;
15 _errno = errno;
16 diag_in_handler = 1;
17 Notice("SIGALRM while waiting for wo child process to die, killing it now");
18 Kill(socat_kill_pid, SIGTERM);
19 diag_in_handler = 0;
20 errno = _errno;
23 int xioshutdown(xiofile_t *sock, int how) {
24 int result = 0;
26 if (sock->tag == XIO_TAG_INVALID) {
27 Error("xioshutdown(): invalid file descriptor");
28 errno = EINVAL;
29 return -1;
32 if (sock->tag == XIO_TAG_DUAL) {
33 if ((how+1)&1) {
34 result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
36 if ((how+1)&2) {
37 result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
39 return result;
42 switch (sock->stream.howtoshut) {
43 char writenull;
44 case XIOSHUT_NONE:
45 return 0;
46 case XIOSHUT_CLOSE:
47 if (Close(sock->stream.fd) < 0) {
48 Info2("close(%d): %s",
49 sock->stream.fd, strerror(errno));
51 return 0;
52 case XIOSHUT_DOWN:
53 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
54 Info3("shutdown(%d, %d): %s",
55 sock->stream.fd, how, strerror(errno));
57 return 0;
58 #if _WITH_SOCKET
59 case XIOSHUT_NULL:
60 /* send an empty packet; only useful on datagram sockets? */
61 xiowrite(sock, &writenull, 0);
62 return 0;
63 #endif /* _WITH_SOCKET */
64 default: ;
67 if (false) {
69 #if WITH_OPENSSL
70 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
71 sycSSL_shutdown (sock->stream.para.openssl.ssl);
72 /*! what about half/full close? */
73 #endif /* WITH_OPENSSL */
75 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
76 if ((how+1)&1) {
77 if (Close(sock->stream.fd) < 0) {
78 Info2("close(%d): %s",
79 sock->stream.fd, strerror(errno));
82 if ((how+1)&2) {
83 if (Close(sock->stream.para.bipipe.fdout) < 0) {
84 Info2("close(%d): %s",
85 sock->stream.para.bipipe.fdout, strerror(errno));
89 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
90 if ((how+1)&1) {
91 if (Close(sock->stream.fd) < 0) {
92 Info2("close(%d): %s",
93 sock->stream.fd, strerror(errno));
96 if ((how+1)&2) {
97 if (Close(sock->stream.para.exec.fdout) < 0) {
98 Info2("close(%d): %s",
99 sock->stream.para.exec.fdout, strerror(errno));
102 #if _WITH_SOCKET
103 } else if (sock->stream.howtoend == END_SHUTDOWN) {
104 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
105 Info3("shutdown(%d, %d): %s",
106 sock->stream.fd, how, strerror(errno));
108 } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
109 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
110 Info3("shutdown(%d, %d): %s",
111 sock->stream.fd, how, strerror(errno));
113 if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
114 /* the child process might want to flush some data before terminating
116 int status = 0;
118 /* we wait for the child process to die, but to prevent timeout
119 we raise an alarm after some time.
120 NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
121 therefore we have to do the kill in the signal handler */
123 struct sigaction act;
124 sigfillset(&act.sa_mask);
125 act.sa_flags = 0;
126 act.sa_handler = signal_kill_pid;
127 Sigaction(SIGALRM, &act, NULL);
129 socat_kill_pid = sock->stream.para.exec.pid;
130 #if HAVE_SETITIMER
131 /*! with next feature release, we get usec resolution and an option */
132 #else
133 Alarm(1 /*! sock->stream.para.exec.waitdie */);
134 #endif /* !HAVE_SETITIMER */
135 if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
136 Warn3("waitpid("F_pid", %p, 0): %s",
137 sock->stream.para.exec.pid, &status, strerror(errno));
139 Alarm(0);
141 } else if ((sock->stream.dtype & XIODATA_MASK) ==
142 (XIODATA_RECVFROM & XIODATA_MASK)) {
143 if (how >= 1) {
144 if (Close(sock->stream.fd) < 0) {
145 Info2("close(%d): %s",
146 sock->stream.fd, strerror(errno));
148 sock->stream.eof = 2;
149 sock->stream.fd = -1;
151 #endif /* _WITH_SOCKET */
152 #if 0
153 } else {
154 Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
155 return -1;
156 #endif
159 #if 0
160 else if (sock->stream.howtoend == END_CLOSE &&
161 sock->stream.dtype == DATA_STREAM) {
162 return result;
164 #if WITH_TERMIOS
165 if (sock->stream.ttyvalid) {
166 if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
167 Warn2("cannot restore terminal settings on fd %d: %s",
168 sock->stream.fd, strerror(errno));
171 #endif /* WITH_TERMIOS */
172 #endif
174 return result;