diff options
Diffstat (limited to '')
-rw-r--r-- | ingest.c | 87 |
1 files changed, 58 insertions, 29 deletions
diff --git a/ingest.c b/ingest.c index 79b0e38..52a50af 100644 --- a/ingest.c +++ b/ingest.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, Curtis McEnroe <programble@gmail.com> +/* Copyright (C) 2018 Causal Agent June <june@causal.agency> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -15,53 +15,82 @@ */ #include <err.h> +#include <errno.h> #include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> +#include <poll.h> +#include <sys/ioctl.h> #include <sys/ioctl.h> #include <sysexits.h> #include <unistd.h> -#include "stream.h" +extern int winch(void); -int main(int argc, char *argv[]) { - if (argc < 2) return EX_USAGE; - const char *path = argv[1]; +static struct { + int winch; + int local; + int remote; +} fd = { -1, -1, STDIN_FILENO }; - int remote = STDIN_FILENO; +int main(int argc, char *argv[]) { + if (argc < 2) errx(EX_USAGE, "missing private id"); + if (!isatty(STDERR_FILENO)) errx(EX_USAGE, "no terminal (use ssh -t)"); - int stream = open(path, O_WRONLY); - if (stream < 0) err(EX_NOINPUT, "%s", path); + const char *path = argv[1]; + fd.local = open(path, O_WRONLY); + if (fd.local < 0) err(EX_NOINPUT, "%s", path); struct winsize window; - ssize_t size = read(remote, &window, sizeof(window)); - if (size < 0) err(EX_IOERR, "read(%d)", remote); - if ((size_t)size < sizeof(window)) errx(EX_IOERR, "short read(%d)", remote); + int error = ioctl(STDERR_FILENO, TIOCGWINSZ, &window); + if (error) err(EX_IOERR, "TIOCGWINSZ"); + fd.winch = winch(); for (;;) { - int error = ftruncate(stream, 0); + int error = ftruncate(fd.local, 0); if (error) err(EX_IOERR, "%s", path); - off_t offset = lseek(stream, 0, SEEK_SET); - if (offset < 0) err(EX_IOERR, "%s", path); + off_t off = lseek(fd.local, 0, SEEK_SET); + if (off < 0) err(EX_IOERR, "%s", path); - ssize_t size = write(stream, &window, sizeof(window)); - if (size < 0) err(EX_IOERR, "write(%d)", stream); - if ((size_t)size < sizeof(window)) errx(EX_IOERR, "short write(%d)", stream); + ssize_t size = write(fd.local, &window, sizeof(window)); + if (size < 0) err(EX_IOERR, "write(%d)", fd.local); + if ((size_t)size < sizeof(window)) { + errx(EX_IOERR, "short write(%d)", fd.local); + } char buf[4096]; - ssize_t totalSize = 0; - while (totalSize < STREAM_SIZE) { - ssize_t readSize = read(remote, buf, sizeof(buf)); - if (readSize < 0) err(EX_IOERR, "read(%d)", remote); - if (!readSize) return EX_OK; + struct pollfd fds[2] = { + { .fd = fd.remote, .events = POLLIN }, + { .fd = fd.winch, .events = POLLIN }, + }; + for (ssize_t totalSize = 0; totalSize < 1024 * 1024;) { + int nfds = poll(fds, 2, -1); + if (nfds < 0) { + if (errno == EINTR) continue; + err(EX_IOERR, "poll"); + } + + if (fds[0].revents & POLLIN) { + ssize_t readSize = read(fd.remote, buf, sizeof(buf)); + if (readSize < 0) err(EX_IOERR, "read(%d)", fd.remote); + if (!readSize) return EX_OK; + + ssize_t writeSize = write(fd.local, buf, readSize); + if (writeSize < 0) err(EX_IOERR, "write(%d)", fd.local); + if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", fd.local); + + totalSize += readSize; + } - ssize_t writeSize = write(stream, buf, readSize); - if (writeSize < 0) err(EX_IOERR, "write(%d)", stream); - if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", stream); + if (fds[0].revents & POLLHUP) return EX_OK; - totalSize += readSize; + if (fds[1].revents & POLLIN) { + ssize_t readSize = read(fd.winch, &window, sizeof(window)); + if (readSize < 0) err(EX_IOERR, "read(%d)", fd.winch); + if ((size_t)readSize < sizeof(window)) { + errx(EX_IOERR, "short read(%d)", fd.winch); + } + break; + } } - sleep(1); } } |