add listen-timeout to function as an accept timeout
[socat/sam.git] / xioshutdown.c
blob3b2a765ea5ccf7bd61de22f05abda5f6a609bdcd
1 /* source: xioshutdown.c */
2 /* Copyright Gerhard Rieger 2001-2009 */
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 Notice("SIGALRM while waiting for w/o child process to die, killing it now");
15 Kill(socat_kill_pid, SIGTERM);
18 int xioshutdown(xiofile_t *sock, int how) {
19 int result = 0;
21 if (sock->tag == XIO_TAG_INVALID) {
22 Error("xioshutdown(): invalid file descriptor");
23 errno = EINVAL;
24 return -1;
27 if (sock->tag == XIO_TAG_DUAL) {
28 if ((how+1)&1) {
29 result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
31 if ((how+1)&2) {
32 result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
34 return result;
37 switch (sock->stream.howtoshut) {
38 char writenull;
39 case XIOSHUT_NONE:
40 return 0;
41 case XIOSHUT_CLOSE:
42 if (Close(sock->stream.fd) < 0) {
43 Info2("close(%d): %s",
44 sock->stream.fd, strerror(errno));
46 return 0;
47 case XIOSHUT_DOWN:
48 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
49 Info3("shutdown(%d, %d): %s",
50 sock->stream.fd, how, strerror(errno));
52 return 0;
53 #if _WITH_SOCKET
54 case XIOSHUT_NULL:
55 /* send an empty packet; only useful on datagram sockets? */
56 xiowrite(sock, &writenull, 0);
57 return 0;
58 #endif /* _WITH_SOCKET */
59 default: ;
62 if (false) {
64 #if WITH_OPENSSL
65 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
66 sycSSL_shutdown (sock->stream.para.openssl.ssl);
67 /*! what about half/full close? */
68 #endif /* WITH_OPENSSL */
70 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
71 if ((how+1)&1) {
72 if (Close(sock->stream.fd) < 0) {
73 Info2("close(%d): %s",
74 sock->stream.fd, strerror(errno));
77 if ((how+1)&2) {
78 if (Close(sock->stream.para.bipipe.fdout) < 0) {
79 Info2("close(%d): %s",
80 sock->stream.para.bipipe.fdout, strerror(errno));
84 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
85 if ((how+1)&1) {
86 if (Close(sock->stream.fd) < 0) {
87 Info2("close(%d): %s",
88 sock->stream.fd, strerror(errno));
91 if ((how+1)&2) {
92 if (Close(sock->stream.para.exec.fdout) < 0) {
93 Info2("close(%d): %s",
94 sock->stream.para.exec.fdout, strerror(errno));
97 #if _WITH_SOCKET
98 } else if (sock->stream.howtoend == END_SHUTDOWN) {
99 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
100 Info3("shutdown(%d, %d): %s",
101 sock->stream.fd, how, strerror(errno));
103 } else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
104 if ((result = Shutdown(sock->stream.fd, how)) < 0) {
105 Info3("shutdown(%d, %d): %s",
106 sock->stream.fd, how, strerror(errno));
108 if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
109 /* the child process might want to flush some data before terminating
111 int status = 0;
113 /* we wait for the child process to die, but to prevent timeout
114 we raise an alarm after some time.
115 NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
116 therefore we have to do the kill in the signal handler */
117 Signal(SIGALRM, signal_kill_pid);
118 socat_kill_pid = sock->stream.para.exec.pid;
119 #if HAVE_SETITIMER
120 /*! with next feature release, we get usec resolution and an option */
121 #else
122 Alarm(1 /*! sock->stream.para.exec.waitdie */);
123 #endif /* !HAVE_SETITIMER */
124 if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
125 Warn3("waitpid("F_pid", %p, 0): %s",
126 sock->stream.para.exec.pid, &status, strerror(errno));
128 Alarm(0);
130 } else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_RECVFROM) {
131 if (how >= 1) {
132 if (Close(sock->stream.fd) < 0) {
133 Info2("close(%d): %s",
134 sock->stream.fd, strerror(errno));
136 sock->stream.eof = 2;
137 sock->stream.fd = -1;
139 #endif /* _WITH_SOCKET */
140 #if 0
141 } else {
142 Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
143 return -1;
144 #endif
147 #if 0
148 else if (sock->stream.howtoend == END_CLOSE &&
149 sock->stream.dtype == DATA_STREAM) {
150 return result;
152 #if WITH_TERMIOS
153 if (sock->stream.ttyvalid) {
154 if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
155 Warn2("cannot restore terminal settings on fd %d: %s",
156 sock->stream.fd, strerror(errno));
159 #endif /* WITH_TERMIOS */
160 #endif
162 return result;