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"
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
) {
19 Notice("SIGALRM while waiting for wo child process to die, killing it now");
20 Kill(socat_kill_pid
, SIGTERM
);
25 int xioshutdown(xiofile_t
*sock
, int how
) {
28 if (sock
->tag
== XIO_TAG_INVALID
) {
29 Error("xioshutdown(): invalid file descriptor");
34 if (sock
->tag
== XIO_TAG_DUAL
) {
36 result
= xioshutdown((xiofile_t
*)sock
->dual
.stream
[0], 0);
39 result
|= xioshutdown((xiofile_t
*)sock
->dual
.stream
[1], 1);
44 switch (sock
->stream
.howtoshut
) {
49 if (Close(sock
->stream
.fd
) < 0) {
50 Info2("close(%d): %s",
51 sock
->stream
.fd
, strerror(errno
));
55 if ((result
= Shutdown(sock
->stream
.fd
, how
)) < 0) {
56 Info3("shutdown(%d, %d): %s",
57 sock
->stream
.fd
, how
, strerror(errno
));
62 /* send an empty packet; only useful on datagram sockets? */
63 xiowrite(sock
, &writenull
, 0);
65 #endif /* _WITH_SOCKET */
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
) {
78 if (Close(sock
->stream
.fd
) < 0) {
79 Info2("close(%d): %s",
80 sock
->stream
.fd
, strerror(errno
));
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
) {
92 if (Close(sock
->stream
.fd
) < 0) {
93 Info2("close(%d): %s",
94 sock
->stream
.fd
, strerror(errno
));
98 if (Close(sock
->stream
.para
.exec
.fdout
) < 0) {
99 Info2("close(%d): %s",
100 sock
->stream
.para
.exec
.fdout
, strerror(errno
));
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
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
);
127 act
.sa_handler
= signal_kill_pid
;
128 Sigaction(SIGALRM
, &act
, NULL
);
130 socat_kill_pid
= sock
->stream
.para
.exec
.pid
;
132 /*! with next feature release, we get usec resolution and an option */
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
));
142 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) ==
143 (XIODATA_RECVFROM
& XIODATA_MASK
)) {
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 */
155 Error1("xioshutdown(): bad data type specification %d", sock
->stream
.dtype
);
161 else if (sock
->stream
.howtoend
== END_CLOSE
&&
162 sock
->stream
.dtype
== DATA_STREAM
) {
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 */