1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* $Id: xioshutdown.c,v 1.18 2005/03/13 12:19:59 gerhard Exp $ */
/* Copyright Gerhard Rieger 2001-2005 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source of the extended shutdown function */
#include "xiosysincludes.h"
#include "xioopen.h"
static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
static void signal_kill_pid(int dummy) {
Notice("SIGALRM while waiting for w/o child process to die, killing it now");
Kill(socat_kill_pid, SIGTERM);
}
int xioshutdown(xiofile_t *sock, int how) {
int result = 0;
if (sock->tag == XIO_TAG_INVALID) {
Error("xioshutdown(): invalid file descriptor");
errno = EINVAL;
return -1;
}
if (sock->tag == XIO_TAG_DUAL) {
if ((how+1)&1) {
result = xioshutdown(sock->dual.stream[0], 0);
}
if ((how+1)&2) {
result |= xioshutdown(sock->dual.stream[1], 1);
}
#if WITH_OPENSSL
} else if (sock->stream.dtype == DATA_OPENSSL) {
sycSSL_shutdown (sock->stream.para.openssl.ssl);
/*! */
#endif /* WITH_OPENSSL */
} else if (sock->stream.dtype == DATA_PIPE) {
if ((how+1)&1) {
if (Close(sock->stream.fd) < 0) {
Warn2("close(%d): %s",
sock->stream.fd, strerror(errno));
}
}
if ((how+1)&2) {
if (Close(sock->stream.para.bipipe.fdout) < 0) {
Warn2("close(%d): %s",
sock->stream.para.bipipe.fdout, strerror(errno));
}
}
} else if (sock->stream.dtype == DATA_2PIPE) {
if ((how+1)&1) {
if (Close(sock->stream.fd) < 0) {
Warn2("close(%d): %s",
sock->stream.fd, strerror(errno));
}
}
if ((how+1)&2) {
if (Close(sock->stream.para.exec.fdout) < 0) {
Warn2("close(%d): %s",
sock->stream.para.exec.fdout, strerror(errno));
}
}
#if WITH_SOCKET
} else if (sock->stream.howtoend == END_SHUTDOWN) {
if ((result = Shutdown(sock->stream.fd, how)) < 0) {
Warn3("shutdown(%d, %d): %s",
sock->stream.fd, how, strerror(errno));
}
} else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
if ((result = Shutdown(sock->stream.fd, how)) < 0) {
Warn3("shutdown(%d, %d): %s",
sock->stream.fd, how, strerror(errno));
}
if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
/* the child process might want to flush some data before terminating
*/
int status = 0;
/* we wait for the child process to die, but to prevent timeout
we raise an alarm after some time.
NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
therefore we have to do the kill in the signal handler */
Signal(SIGALRM, signal_kill_pid);
socat_kill_pid = sock->stream.para.exec.pid;
#if HAVE_SETITIMER
/*! with next feature release, we get usec resolution and an option */
#else
Alarm(1 /*! sock->stream.para.exec.waitdie */);
#endif /* !HAVE_SETITIMER */
if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
Warn3("waitpid("F_pid", %p, 0): %s",
sock->stream.para.exec.pid, &status, strerror(errno));
}
Alarm(0);
}
} else if (sock->stream.dtype == DATA_RECV) {
if (how >= 1) {
if (Close(sock->stream.fd) < 0) {
Warn2("close(%d): %s",
sock->stream.fd, strerror(errno));
}
sock->stream.eof = 1;
sock->stream.fd = -1;
}
#endif /* WITH_SOCKET */
#if 0
} else {
Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
return -1;
#endif
}
#if 0
else if (sock->stream.howtoend == END_CLOSE &&
sock->stream.dtype == DATA_STREAM) {
return result;
}
#if WITH_TERMIOS
if (sock->stream.ttyvalid) {
if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
Warn2("cannot restore terminal settings on fd %d: %s",
sock->stream.fd, strerror(errno));
}
}
#endif /* WITH_TERMIOS */
#endif
return result;
}
|