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"
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
) {
21 if (sock
->tag
== XIO_TAG_INVALID
) {
22 Error("xioshutdown(): invalid file descriptor");
27 if (sock
->tag
== XIO_TAG_DUAL
) {
29 result
= xioshutdown((xiofile_t
*)sock
->dual
.stream
[0], 0);
32 result
|= xioshutdown((xiofile_t
*)sock
->dual
.stream
[1], 1);
37 switch (sock
->stream
.howtoshut
) {
42 if (Close(sock
->stream
.fd
) < 0) {
43 Info2("close(%d): %s",
44 sock
->stream
.fd
, strerror(errno
));
48 if ((result
= Shutdown(sock
->stream
.fd
, how
)) < 0) {
49 Info3("shutdown(%d, %d): %s",
50 sock
->stream
.fd
, how
, strerror(errno
));
55 /* send an empty packet; only useful on datagram sockets? */
56 xiowrite(sock
, &writenull
, 0);
58 #endif /* _WITH_SOCKET */
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
) {
72 if (Close(sock
->stream
.fd
) < 0) {
73 Info2("close(%d): %s",
74 sock
->stream
.fd
, strerror(errno
));
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
) {
86 if (Close(sock
->stream
.fd
) < 0) {
87 Info2("close(%d): %s",
88 sock
->stream
.fd
, strerror(errno
));
92 if (Close(sock
->stream
.para
.exec
.fdout
) < 0) {
93 Info2("close(%d): %s",
94 sock
->stream
.para
.exec
.fdout
, strerror(errno
));
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
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
;
120 /*! with next feature release, we get usec resolution and an option */
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
));
130 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) == XIODATA_RECVFROM
) {
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 */
142 Error1("xioshutdown(): bad data type specification %d", sock
->stream
.dtype
);
148 else if (sock
->stream
.howtoend
== END_CLOSE
&&
149 sock
->stream
.dtype
== DATA_STREAM
) {
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 */