| /* source: xiowrite.c */ |
| /* Copyright Gerhard Rieger and contributors (see file CHANGES) */ |
| /* 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" |
| |
| #include "xio-posixmq.h" |
| #include "xio-readline.h" |
| #include "xio-openssl.h" |
| |
| |
| /* ... |
| note that the write() call can block even if the select()/poll() 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; |
| int _errno; |
| |
| if (file->tag == XIO_TAG_INVALID || file->tag & XIO_TAG_CLOSED) { |
| 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 || file->tag & XIO_TAG_CLOSED) { |
| 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 */ |
| |
| switch (pipe->dtype & XIODATA_WRITEMASK) { |
| |
| case XIOWRITE_STREAM: |
| writt = writefull(pipe->fd, buff, bytes); |
| if (writt < 0) { |
| _errno = errno; |
| switch (_errno) { |
| case EPIPE: |
| case ECONNRESET: |
| if (pipe->cool_write) { |
| Notice4("write(%d, %p, "F_Zu"): %s", |
| pipe->fd, buff, bytes, strerror(_errno)); |
| break; |
| } |
| /*PASSTRHOUGH*/ |
| default: |
| Error4("write(%d, %p, "F_Zu"): %s", |
| pipe->fd, buff, bytes, strerror(_errno)); |
| } |
| errno = _errno; |
| return -1; |
| } |
| break; |
| |
| #if _WITH_SOCKET |
| case XIOWRITE_SENDTO: |
| /*union { |
| char space[sizeof(struct sockaddr_un)]; |
| struct sockaddr sa; |
| } from;*/ |
| /*socklen_t fromlen;*/ |
| |
| do { |
| writt = Sendto(pipe->fd, buff, bytes, 0, |
| &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", |
| pipe->fd, buff, bytes, |
| 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 sent "F_Zu" of "F_Zu" bytes", |
| pipe->fd, buff, bytes, |
| sockaddr_info(&pipe->peersa.soa, pipe->salen, |
| infobuff, sizeof(infobuff)), |
| pipe->salen, writt, bytes); |
| } |
| { |
| char infobuff[256]; |
| union sockaddr_union us; |
| socklen_t uslen = sizeof(us); |
| Getsockname(pipe->fd, &us.soa, &uslen); |
| Notice1("local address: %s", |
| sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff))); |
| } |
| break; |
| #endif /* _WITH_SOCKET */ |
| |
| case XIOWRITE_PIPE: |
| if (pipe->para.bipipe.socktype == SOCK_STREAM) { |
| writt = Write(pipe->para.bipipe.fdout, buff, bytes); |
| } else { |
| writt = Send(pipe->para.bipipe.fdout, buff, bytes, 0); |
| } |
| _errno = errno; |
| if (writt < 0) { |
| Error4("write(%d, %p, "F_Zu"): %s", |
| pipe->para.bipipe.fdout, buff, bytes, strerror(_errno)); |
| errno = _errno; |
| return -1; |
| } |
| break; |
| |
| case XIOWRITE_2PIPE: |
| writt = Write(pipe->para.exec.fdout, buff, bytes); |
| _errno = errno; |
| if (writt < 0) { |
| Error4("write(%d, %p, "F_Zu"): %s", |
| pipe->para.exec.fdout, buff, bytes, strerror(_errno)); |
| errno = _errno; |
| return -1; |
| } |
| break; |
| |
| #if WITH_POSIXMQ |
| case XIOWRITE_POSIXMQ: |
| if ((writt = xiowrite_posixmq(pipe, buff, bytes)) < 0) { |
| return -1; |
| } |
| break; |
| #endif /* WITH_POSIXMQ */ |
| |
| #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; |
| } |