diff options
author | Peter <petershh@disroot.org> | 2022-07-18 14:09:31 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-18 14:09:31 +0300 |
commit | a56e9b74a901d5497425411f7f70db5f0d47baf0 (patch) | |
tree | 870c148deff21f76f105533721cf8e8f652951d8 | |
parent | 0a8f1761529bbac4d3fd3d737ba08620cca4713d (diff) | |
download | shh-portable-utils-a56e9b74a901d5497425411f7f70db5f0d47baf0.tar.xz |
Add tee
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | package/deps.mak | 3 | ||||
-rw-r--r-- | package/modes | 1 | ||||
-rw-r--r-- | package/targets.mak | 1 | ||||
-rw-r--r-- | src/shh-portable-utils/deps-exe/tee | 1 | ||||
-rw-r--r-- | src/shh-portable-utils/tee.c | 84 |
6 files changed, 91 insertions, 0 deletions
@@ -13,5 +13,6 @@ src/include/shh-portable-utils/config.h /cut /dirname /false +/tee /true /uniq diff --git a/package/deps.mak b/package/deps.mak index 9e88c08..a42736e 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -12,6 +12,7 @@ src/shh-portable-utils/cut.o src/shh-portable-utils/cut.lo: src/shh-portable-uti src/shh-portable-utils/dirname.o src/shh-portable-utils/dirname.lo: src/shh-portable-utils/dirname.c src/shh-portable-utils/false.o src/shh-portable-utils/false.lo: src/shh-portable-utils/false.c src/shh-portable-utils/shhgetln.o src/shh-portable-utils/shhgetln.lo: src/shh-portable-utils/shhgetln.c src/shh-portable-utils/shhfuncs.h +src/shh-portable-utils/tee.o src/shh-portable-utils/tee.lo: src/shh-portable-utils/tee.c src/shh-portable-utils/true.o src/shh-portable-utils/true.lo: src/shh-portable-utils/true.c src/shh-portable-utils/uniq.o src/shh-portable-utils/uniq.lo: src/shh-portable-utils/uniq.c src/shh-portable-utils/shhfuncs.h @@ -31,6 +32,8 @@ dirname: EXTRA_LIBS := -lskarnet dirname: src/shh-portable-utils/dirname.o false: EXTRA_LIBS := false: src/shh-portable-utils/false.o +tee: EXTRA_LIBS := -lskarnet +tee: src/shh-portable-utils/tee.o true: EXTRA_LIBS := true: src/shh-portable-utils/true.o uniq: EXTRA_LIBS := -lskarnet diff --git a/package/modes b/package/modes index 2a2e5fe..cb27b3b 100644 --- a/package/modes +++ b/package/modes @@ -6,5 +6,6 @@ chown 0755 cut 0755 dirname 0755 false 0755 +tee 0755 true 0755 uniq 0755 diff --git a/package/targets.mak b/package/targets.mak index cff022d..ed47a8a 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -7,6 +7,7 @@ chown \ cut \ dirname \ false \ +tee \ true \ uniq diff --git a/src/shh-portable-utils/deps-exe/tee b/src/shh-portable-utils/deps-exe/tee new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/shh-portable-utils/deps-exe/tee @@ -0,0 +1 @@ +-lskarnet diff --git a/src/shh-portable-utils/tee.c b/src/shh-portable-utils/tee.c new file mode 100644 index 0000000..6680dab --- /dev/null +++ b/src/shh-portable-utils/tee.c @@ -0,0 +1,84 @@ +#include <stdlib.h> + +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> + +#include <skalibs/strerr2.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> +#include <skalibs/sgetopt.h> + +#define BUFSIZ 8192 + +#define USAGE "tee [-ai] [file...]" + +int main(int argc, char const *const *argv) +{ + char buf[BUFSIZ]; + ssize_t nbytes; + int failure = 0; + int *fds = NULL; + int write_mode = O_TRUNC; + int ignore_sigint = 0; + subgetopt l = SUBGETOPT_ZERO; + PROG = "tee"; + for (;;) { + int opt = subgetopt_r(argc, argv, "ai", &l); + if (opt == -1) + break; + switch (opt) { + case 'a': + write_mode = O_APPEND; + break; + case 'i': + ignore_sigint = 1; + break; + default: + strerr_dieusage(100, USAGE); + } + } + argc -= l.ind; + argv += l.ind; + + if (ignore_sigint) + if (signal(SIGINT, SIG_IGN) == SIG_ERR) + strerr_diefu1sys(111, "set SIGINT handler"); + + if (argc > 0) { + fds = (int*)malloc(argc * sizeof(int)); + if (!fds) + strerr_diefu1sys(111, "allocate memory"); + } + + for (size_t i = 0; i < argc; i++) { + fds[i] = open3(argv[i], O_WRONLY | O_CREAT | write_mode, 0666); + if (fds[i] == -1) { + strerr_warnwu3sys("open ", argv[i], " for reading"); + failure = 1; + } + } + + for (;;) { + nbytes = read(0, buf, BUFSIZ); + if (nbytes == -1) + strerr_diefu1sys(111, "read from stdin "); + if (nbytes == 0) + break; + for (size_t i = 0; i < argc; i++) { + if (fds[i] == -1) + continue; + if (allwrite(fds[i], buf, nbytes) < 0) { + strerr_warnwu2sys("write to ", argv[i]); + fd_close(fds[i]); + fds[i] = -1; + failure = 1; + } + } + if (allwrite(1, buf, nbytes) < 0) { + strerr_warnwu1sys("write to stdout"); + failure = 1; + } + } + return failure ? 111: 0; +} |