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
|| sock
->tag
& XIO_TAG_CLOSED
) {
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 result
= Shutdown(sock
->stream
.fd
, how
);
57 int level
, _errno
= errno
;
64 level
= E_INFO
; /* old behaviour */
67 Msg3(level
, "shutdown(%d, %d): %s",
68 sock
->stream
.fd
, how
, strerror(_errno
));
75 writenull
= '\0'; /* assign something to make gcc happy */
76 /* send an empty packet; only useful on datagram sockets? */
77 xiowrite(sock
, &writenull
, 0);
79 #endif /* _WITH_SOCKET */
82 /* XIOSHUT_UNSPEC passes on */
87 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) == XIODATA_OPENSSL
) {
88 xioshutdown_openssl(&sock
->stream
, how
);
89 #endif /* WITH_OPENSSL */
91 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) == XIODATA_PIPE
) {
93 if (Close(sock
->stream
.fd
) < 0) {
94 Info2("close(%d): %s",
95 sock
->stream
.fd
, strerror(errno
));
99 if (Close(sock
->stream
.para
.bipipe
.fdout
) < 0) {
100 Info2("close(%d): %s",
101 sock
->stream
.para
.bipipe
.fdout
, strerror(errno
));
105 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) == XIODATA_2PIPE
) {
107 if (Close(sock
->stream
.fd
) < 0) {
108 Info2("close(%d): %s",
109 sock
->stream
.fd
, strerror(errno
));
113 if (Close(sock
->stream
.para
.exec
.fdout
) < 0) {
114 Info2("close(%d): %s",
115 sock
->stream
.para
.exec
.fdout
, strerror(errno
));
119 } else if (sock
->stream
.howtoend
== END_SHUTDOWN
) {
120 if ((result
= Shutdown(sock
->stream
.fd
, how
)) < 0) {
121 Info3("shutdown(%d, %d): %s",
122 sock
->stream
.fd
, how
, strerror(errno
));
124 } else if (sock
->stream
.howtoend
== END_SHUTDOWN_KILL
) {
125 if ((result
= Shutdown(sock
->stream
.fd
, how
)) < 0) {
126 Info3("shutdown(%d, %d): %s",
127 sock
->stream
.fd
, how
, strerror(errno
));
129 if ((sock
->stream
.flags
&XIO_ACCMODE
) == XIO_WRONLY
) {
133 /* the child process might want to flush some data before terminating
137 /* we wait for the child process to die, but to prevent timeout
138 we raise an alarm after some time.
139 NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
140 therefore we have to do the kill in the signal handler */
142 struct sigaction act
;
143 sigfillset(&act
.sa_mask
);
145 act
.sa_handler
= signal_kill_pid
;
146 Sigaction(SIGALRM
, &act
, NULL
);
148 socat_kill_pid
= sock
->stream
.para
.exec
.pid
;
150 /*! with next feature release, we get usec resolution and an option */
152 Alarm(1 /*! sock->stream.para.exec.waitdie */);
153 #endif /* !HAVE_SETITIMER */
154 pid
= Waitpid(sock
->stream
.para
.exec
.pid
, &status
, 0);
160 Msg3(level
, "waitpid("F_pid
", %p, 0): %s",
161 sock
->stream
.para
.exec
.pid
, &status
, strerror(errno
));
165 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) ==
166 (XIODATA_RECVFROM
& XIODATA_MASK
)) {
168 if (Close(sock
->stream
.fd
) < 0) {
169 Info2("close(%d): %s",
170 sock
->stream
.fd
, strerror(errno
));
172 sock
->stream
.eof
= 2;
173 sock
->stream
.fd
= -1;
175 #endif /* _WITH_SOCKET */
178 Error1("xioshutdown(): bad data type specification %d", sock
->stream
.dtype
);
184 else if (sock
->stream
.howtoend
== END_CLOSE
&&
185 sock
->stream
.dtype
== DATA_STREAM
) {
189 if (sock
->stream
.ttyvalid
) {
190 if (Tcsetattr(sock
->stream
.fd
, TCSAFLUSH
, &sock
->stream
.savetty
) < 0) {
191 Warn2("cannot restore terminal settings on fd %d: %s",
192 sock
->stream
.fd
, strerror(errno
));
195 #endif /* WITH_TERMIOS */