diff options
| author | Mattias Andrée <maandree@kth.se> | 2017-05-25 15:30:17 +0200 |
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2017-05-25 17:47:23 +0200 |
| commit | 7b147cb0c1eaa728f244cc8390ccfcc3f4aee03a (patch) | |
| tree | 80e23538c1d8b364ec9c8c7e58e895b9a471dfef /src/blind-from-named.c | |
| parent | Fix errors and warnings and make the code cleaner (diff) | |
| download | blind-7b147cb0c1eaa728f244cc8390ccfcc3f4aee03a.tar.gz blind-7b147cb0c1eaa728f244cc8390ccfcc3f4aee03a.tar.bz2 blind-7b147cb0c1eaa728f244cc8390ccfcc3f4aee03a.tar.xz | |
Add blind-from-named and blind-to-named
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | src/blind-from-named.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/blind-from-named.c b/src/blind-from-named.c new file mode 100644 index 0000000..1ca4c7f --- /dev/null +++ b/src/blind-from-named.c @@ -0,0 +1,149 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +USAGE("[-t decisecs] [-a] ([-f fd] path [command ...] | path)") + +static int +erecv_fd(int sock) +{ + int fd; + char buf[1]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char cms[CMSG_SPACE(sizeof(fd))]; + + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = (caddr_t)cms; + msg.msg_controllen = sizeof(cms); + + switch (recvmsg(sock, &msg, 0)) { + case -1: + eprintf("recvmsg:"); + case 0: + eprintf("recvmsg: connection closed by peer"); + default: + break; + } + + cmsg = CMSG_FIRSTHDR(&msg); + memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + return fd; +} + +#if !defined(HAVE_SENDFILE) +# if !defined(PIPE_BUF) +# define PIPE_BUF BUFSIZ +# endif +static ssize_t +sendfile(int outfd, int infd, off_t *offset, size_t count) +{ + char buf[PIPE_BUF]; + ssize_t r, w, p, ret = 0; + + (void) offset; + (void) count; + + for (;;) { + r = read(infd, buf, sizeof(buf)); + if (r < 0) + eprintf("read <received file>:"); + if (!r) + break; + ret += r; + for (p = 0; p < r; p += w) { + w = write(outfd, buf + p, r - p); + if (w < 0) + eprintf("write <stdout>:"); + } + } + + return ret; +} +#endif + +int +main(int argc, char *argv[]) +{ + struct sockaddr_un addr; + int abstract = 0; + int filedes = -1; + int tries = 10; + int sockfd, fd; + + ARGBEGIN { + case 'a': + abstract = 1; + break; + case 'f': + filedes = etoi_flag('f', UARGF(), 0, INT_MAX); + break; + case 't': + tries = etoi_flag('t', UARGF(), 1, INT_MAX); + break; + default: + usage(); + } ARGEND; + if (argc < 1 || (filedes >= 0 && argc > 1)) + usage(); + if (argc > 0 && filedes < 0) + filedes = 0; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (strlen(argv[0]) + 1 + abstract > sizeof(addr.sun_path)) { + errno = ENAMETOOLONG; + eprintf("%s:", argv[0]); + } + strcpy(addr.sun_path + abstract, argv[0]); + argv++, argc--; + + sockfd = socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (sockfd < 0) + eprintf("socket PF_UNIX SOCK_SEQPACKET:"); + +retry: + if ((connect(sockfd, (const struct sockaddr *)&addr, (size_t)sizeof(addr))) < 0) { + if (--tries) { + usleep((useconds_t)100000L); + goto retry; + } else { + eprintf("bind %s%s%s:", + abstract ? "<abstract:" : "", + addr.sun_path + abstract, + abstract ? ">" : ""); + } + } + + fd = erecv_fd(sockfd); + close(sockfd); + + if (argc) { + if (fd != filedes) { + if (dup2(fd, filedes) < 0) + eprintf("dup2 %i %i:", fd, filedes); + close(fd); + } + execvp(argv[0], argv); + eprintf("execvp %s:", argv[0]); + } + + for (;;) { + switch (sendfile(STDOUT_FILENO, fd, NULL, SIZE_MAX)) { + case 0: + return 0; + case -1: + eprintf("sendfile <stdout> <received file>:"); + default: + break; + } + } +} |
