aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter <petershh@disroot.org>2022-07-18 14:09:31 +0300
committerGitHub <noreply@github.com>2022-07-18 14:09:31 +0300
commita56e9b74a901d5497425411f7f70db5f0d47baf0 (patch)
tree870c148deff21f76f105533721cf8e8f652951d8
parent0a8f1761529bbac4d3fd3d737ba08620cca4713d (diff)
downloadshh-portable-utils-a56e9b74a901d5497425411f7f70db5f0d47baf0.tar.xz
Add tee
-rw-r--r--.gitignore1
-rw-r--r--package/deps.mak3
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak1
-rw-r--r--src/shh-portable-utils/deps-exe/tee1
-rw-r--r--src/shh-portable-utils/tee.c84
6 files changed, 91 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index fb9846f..befc2ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;
+}