summaryrefslogtreecommitdiffstats
path: root/src/logtee/logtee.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/logtee/logtee.c')
-rw-r--r--src/logtee/logtee.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/logtee/logtee.c b/src/logtee/logtee.c
new file mode 100644
index 0000000..55520db
--- /dev/null
+++ b/src/logtee/logtee.c
@@ -0,0 +1,71 @@
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+
+#define BUFLEN 4096
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ int len, slen;
+ int ret;
+ int timeout;
+ char *timeout_env;
+ struct pollfd fds[] = { {
+ .fd = STDIN_FILENO,
+ .events = POLLIN | POLLERR,
+ }
+ };
+
+ timeout_env = getenv("LOGTEE_TIMEOUT_MS");
+ if (timeout_env)
+ timeout = atoi(timeout_env);
+ else
+ timeout = -1;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file>\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0644);
+ if (fd == -1) {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "Logging to %s: ", argv[1]);
+
+ slen = 0;
+
+ do {
+ ret = poll(fds, sizeof(fds) / sizeof(fds[0]), timeout);
+ if (ret == 0) {
+ fprintf(stderr, "Timed out after %d milliseconds of no output.\n", timeout);
+ exit(EXIT_FAILURE);
+ }
+ len = splice(STDIN_FILENO, NULL, fd, NULL, BUFLEN, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
+
+ if (len < 0) {
+ if (errno == EAGAIN)
+ continue;
+ perror("tee");
+ exit(EXIT_FAILURE);
+ } else if (len == 0)
+ break;
+ slen += len;
+ if ((slen / BUFLEN) > 0) {
+ fprintf(stderr, ".");
+ }
+ slen = slen % BUFLEN;
+
+ } while (1);
+ close(fd);
+ fprintf(stderr, "\n");
+ exit(EXIT_SUCCESS);
+}