diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2020-10-26 14:21:53 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2020-10-26 14:21:53 +0000 |
commit | 7530e8cdd506ecec1f4ad3bbd55f94de5a6d63ac (patch) | |
tree | 20917d9312d38cf57e04f17cec119d89873b57b3 /src/libunixonacid/ancil_recv_fd.c | |
parent | ad90bc1107ef9a76f4ca530cc41e86d4f352e3d9 (diff) | |
download | skalibs-7530e8cdd506ecec1f4ad3bbd55f94de5a6d63ac.tar.xz |
Separate and expose ancil_recv_fd/ancil_send_fd
The goal is to make late channel creation easy, as opposed to
textclient which always creates a new channel at start time.
This commit also moves posixishard.h inclusions as late as possible.
Diffstat (limited to 'src/libunixonacid/ancil_recv_fd.c')
-rw-r--r-- | src/libunixonacid/ancil_recv_fd.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/libunixonacid/ancil_recv_fd.c b/src/libunixonacid/ancil_recv_fd.c new file mode 100644 index 0000000..70f2c4f --- /dev/null +++ b/src/libunixonacid/ancil_recv_fd.c @@ -0,0 +1,69 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> +#include <skalibs/nonposix.h> + +#include <errno.h> +#include <sys/uio.h> +#include <sys/socket.h> + +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> +#include <skalibs/ancil.h> +#include <skalibs/posixishard.h> + +union aligner_u +{ + struct cmsghdr cmsghdr ; + int i ; +} ; + +int ancil_recv_fd (int sock, char expected_ch) +{ + static int const awesomeflags = +#ifdef SKALIBS_HASMSGDONTWAIT + MSG_DONTWAIT +#else + 0 +#endif + | +#ifdef SKALIBS_HASCMSGCLOEXEC + MSG_CMSG_CLOEXEC +#else + 0 +#endif + ; + struct cmsghdr *c ; + ssize_t r ; + char ch ; + struct iovec v = { .iov_base = &ch, .iov_len = 1 } ; + union aligner_u ancilbuf[1 + (CMSG_SPACE(sizeof(int)) - 1) / sizeof(union aligner_u)] ; + struct msghdr msghdr = + { + .msg_name = 0, + .msg_namelen = 0, + .msg_iov = &v, + .msg_iovlen = 1, + .msg_flags = 0, + .msg_control = ancilbuf, + .msg_controllen = CMSG_SPACE(sizeof(int)) + } ; + do r = recvmsg(sock, &msghdr, awesomeflags) ; + while (r < 0 && errno == EINTR) ; + if (r < 0) return r ; + if (!r) return (errno = EPIPE, -1) ; + c = CMSG_FIRSTHDR(&msghdr) ; + if (ch != expected_ch + || !c + || c->cmsg_level != SOL_SOCKET + || c->cmsg_type != SCM_RIGHTS + || (size_t)(c->cmsg_len - (CMSG_DATA(c) - (unsigned char *)c)) != sizeof(int)) return (errno = EPROTO, -1) ; +#ifndef SKALIBS_HASCMSGCLOEXEC + if (coe(*(int *)CMSG_DATA(c)) < 0) + { + fd_close(*(int *)CMSG_DATA(c)) ; + return -1 ; + } +#endif + return *(int *)CMSG_DATA(c) ; +} |