socat/xiowrite.c

166 lines
4.2 KiB
C
Raw Permalink Normal View History

2008-01-27 12:00:08 +00:00
/* $Id: xiowrite.c,v 1.29 2007/02/08 18:27:00 gerhard Exp $ */
/* Copyright Gerhard Rieger 2001-2007 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this is the source of the extended write function */
#include "xiosysincludes.h"
#include "xioopen.h"
2008-02-24 10:09:01 +00:00
#include "xio-test.h"
2008-01-27 12:00:08 +00:00
#include "xio-readline.h"
#include "xio-openssl.h"
/* ...
note that the write() call can block even if the select() call reported the
FD writeable: in case the FD is not nonblocking and a lock defers the
operation.
on return value < 0: errno reflects the value from write() */
ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
ssize_t writt;
struct single *pipe;
2008-02-24 10:09:01 +00:00
int fd;
2008-01-27 12:00:08 +00:00
int _errno;
if (file->tag == XIO_TAG_INVALID) {
Error1("xiowrite(): invalid xiofile descriptor %p", file);
errno = EINVAL;
return -1;
}
if (file->tag == XIO_TAG_DUAL) {
pipe = file->dual.stream[1];
if (pipe->tag == XIO_TAG_INVALID) {
Error1("xiowrite(): invalid xiofile sub descriptor %p[1]", file);
errno = EINVAL;
return -1;
}
} else {
pipe = &file->stream;
}
#if WITH_READLINE
/* try to extract a prompt from the write data */
if ((pipe->dtype & XIODATA_READMASK) == XIOREAD_READLINE) {
xioscan_readline(pipe, buff, bytes);
}
#endif /* WITH_READLINE */
2008-02-24 10:09:01 +00:00
fd = XIO_GETWRFD(file);
2008-01-27 12:00:08 +00:00
switch (pipe->dtype & XIODATA_WRITEMASK) {
case XIOWRITE_STREAM:
do {
2008-02-24 10:09:01 +00:00
writt = Write(fd, buff, bytes);
2008-01-27 12:00:08 +00:00
} while (writt < 0 && errno == EINTR);
if (writt < 0) {
_errno = errno;
switch (_errno) {
case EPIPE:
case ECONNRESET:
if (pipe->cool_write) {
Notice4("write(%d, %p, "F_Zu"): %s",
2008-02-24 10:09:01 +00:00
fd, buff, bytes, strerror(_errno));
2008-01-27 12:00:08 +00:00
break;
}
/*PASSTRHOUGH*/
default:
Error4("write(%d, %p, "F_Zu"): %s",
2008-02-24 10:09:01 +00:00
fd, buff, bytes, strerror(_errno));
2008-01-27 12:00:08 +00:00
}
errno = _errno;
return -1;
}
if ((size_t)writt < bytes) {
Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
writt, bytes);
}
break;
#if WITH_SOCKET
case XIOWRITE_SENDTO:
/*union {
char space[sizeof(struct sockaddr_un)];
struct sockaddr sa;
} from;*/
/*socklen_t fromlen;*/
do {
2008-02-24 10:09:01 +00:00
writt = Sendto(fd, buff, bytes, 0,
2008-01-27 12:00:08 +00:00
&pipe->peersa.soa, pipe->salen);
} while (writt < 0 && errno == EINTR);
if (writt < 0) {
char infobuff[256];
_errno = errno;
Error6("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
2008-02-24 10:09:01 +00:00
fd, buff, bytes,
2008-01-27 12:00:08 +00:00
sockaddr_info(&pipe->peersa.soa, pipe->salen,
infobuff, sizeof(infobuff)),
pipe->salen, strerror(_errno));
errno = _errno;
return -1;
}
if ((size_t)writt < bytes) {
char infobuff[256];
Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only wrote "F_Zu" of "F_Zu" bytes",
2008-02-24 10:09:01 +00:00
fd, buff, bytes,
2008-01-27 12:00:08 +00:00
sockaddr_info(&pipe->peersa.soa, pipe->salen,
infobuff, sizeof(infobuff)),
pipe->salen, writt, bytes);
} else {
}
{
char infobuff[256];
union sockaddr_union us;
socklen_t uslen = sizeof(us);
2008-02-24 10:09:01 +00:00
Getsockname(fd, &us.soa, &uslen);
2008-01-27 12:00:08 +00:00
Notice1("local address: %s",
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
}
break;
#endif /* WITH_SOCKET */
case XIOWRITE_PIPE:
2008-02-24 10:09:01 +00:00
case XIOWRITE_2PIPE:
2008-01-27 12:00:08 +00:00
do {
2008-02-24 10:09:01 +00:00
writt = Write(fd, buff, bytes);
2008-01-27 12:00:08 +00:00
} while (writt < 0 && errno == EINTR);
_errno = errno;
if (writt < 0) {
Error4("write(%d, %p, "F_Zu"): %s",
2008-02-24 10:09:01 +00:00
fd, buff, bytes, strerror(_errno));
2008-01-27 12:00:08 +00:00
errno = _errno;
return -1;
}
if ((size_t)writt < bytes) {
Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
writt, bytes);
}
break;
2008-02-24 10:09:01 +00:00
#if WITH_TEST
case XIOWRITE_TEST:
/* this function prints its own error messages */
return xiowrite_test(pipe, buff, bytes);
case XIOWRITE_TESTREV:
/* this function prints its own error messages */
return xiowrite_testrev(pipe, buff, bytes);
#endif /* WITH_TEST */
2008-01-27 12:00:08 +00:00
#if WITH_OPENSSL
case XIOWRITE_OPENSSL:
/* this function prints its own error messages */
return xiowrite_openssl(pipe, buff, bytes);
#endif /* WITH_OPENSSL */
default:
Error1("xiowrite(): bad data type specification %d", pipe->dtype);
errno = EINVAL;
return -1;
}
return writt;
}