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"
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
) {
17 Notice("SIGALRM while waiting for wo child process to die, killing it now");
18 Kill(socat_kill_pid
, SIGTERM
);
23 int xioshutdown(xiofile_t
*sock
, int how
) {
26 if (sock
->tag
== XIO_TAG_INVALID
) {
27 Error("xioshutdown(): invalid file descriptor");
32 if (sock
->tag
== XIO_TAG_DUAL
) {
34 result
= xioshutdown((xiofile_t
*)sock
->dual
.stream
[0], 0);
37 result
|= xioshutdown((xiofile_t
*)sock
->dual
.stream
[1], 1);
42 switch (sock
->stream
.howtoshut
) {
47 if (Close(sock
->stream
.fd
) < 0) {
48 Info2("close(%d): %s",
49 sock
->stream
.fd
, strerror(errno
));
53 if ((result
= Shutdown(sock
->stream
.fd
, how
)) < 0) {
54 Info3("shutdown(%d, %d): %s",
55 sock
->stream
.fd
, how
, strerror(errno
));
60 /* send an empty packet; only useful on datagram sockets? */
61 xiowrite(sock
, &writenull
, 0);
63 #endif /* _WITH_SOCKET */
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
) {
77 if (Close(sock
->stream
.fd
) < 0) {
78 Info2("close(%d): %s",
79 sock
->stream
.fd
, strerror(errno
));
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
) {
91 if (Close(sock
->stream
.fd
) < 0) {
92 Info2("close(%d): %s",
93 sock
->stream
.fd
, strerror(errno
));
97 if (Close(sock
->stream
.para
.exec
.fdout
) < 0) {
98 Info2("close(%d): %s",
99 sock
->stream
.para
.exec
.fdout
, strerror(errno
));
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
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
);
126 act
.sa_handler
= signal_kill_pid
;
127 Sigaction(SIGALRM
, &act
, NULL
);
129 socat_kill_pid
= sock
->stream
.para
.exec
.pid
;
131 /*! with next feature release, we get usec resolution and an option */
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
));
141 } else if ((sock
->stream
.dtype
& XIODATA_MASK
) ==
142 (XIODATA_RECVFROM
& XIODATA_MASK
)) {
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 */
154 Error1("xioshutdown(): bad data type specification %d", sock
->stream
.dtype
);
160 else if (sock
->stream
.howtoend
== END_CLOSE
&&
161 sock
->stream
.dtype
== DATA_STREAM
) {
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 */