aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFerass El Hafidi <vitali64pmemail@protonmail.com>2023-02-27 13:22:12 +0100
committerFerass El Hafidi <vitali64pmemail@protonmail.com>2023-02-27 17:08:38 +0100
commite45c3091e61b79e6596674715b394af0dd20f87f (patch)
tree645780728a3dd49cbbe917640d03ea802b13308f
parent0306823bba2967b78462f221315a802f92ff0aaa (diff)
downloadfases-e45c3091e61b79e6596674715b394af0dd20f87f.tar.gz
fases-e45c3091e61b79e6596674715b394af0dd20f87f.zip
core/: tee
Signed-off-by: Ferass El Hafidi <vitali64pmemail@protonmail.com>
-rw-r--r--config.mk1
-rw-r--r--core/tee.c53
2 files changed, 54 insertions, 0 deletions
diff --git a/config.mk b/config.mk
index 3d3a4aa..4c263e7 100644
--- a/config.mk
+++ b/config.mk
@@ -31,6 +31,7 @@ CORE=\
rm\
sleep\
tail\
+ tee\
test\
true\
tty\
diff --git a/core/tee.c b/core/tee.c
new file mode 100644
index 0000000..f84f316
--- /dev/null
+++ b/core/tee.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+
+/* Requirements in common.h */
+#define REQ_PRINT_USAGE
+#define REQ_ERRPRINT
+#include "../common/common.h"
+
+#define DESCRIPTION "Duplicate standard input."
+#define OPERANDS "[-ai] [file...]"
+
+int main(int argc, char *argv[]) {
+ int argument, length, i = 0, fildes[13], append_or_truncate = O_TRUNC;
+ int ret = 0; /* Used for write errors. */
+ char *argv0 = strdup(argv[0]), buffer[4096];
+
+ while ((argument = getopt(argc, argv, "ai")) != -1) {
+ if (argument == '?')
+ return print_usage(argv0, DESCRIPTION, OPERANDS, VERSION);
+ else if (argument == 'i') {
+ struct sigaction signal_action;
+ signal_action.sa_handler = SIG_IGN;
+ sigemptyset(&signal_action.sa_mask);
+ sigaction(SIGINT, &signal_action, NULL);
+ } else if (argument == 'a')
+ append_or_truncate = O_APPEND;
+ } argc -= optind; argv += optind;
+ /* Open all files */
+ for (i = 0; i < argc && argc != 0 && i <= 13; i++) { /* TODO: No file limit */
+ fildes[i] = open(argv[i], O_WRONLY | O_CREAT | append_or_truncate, 0666);
+ if (errno) return errprint(argv0, argv[i], errno);
+ }
+ while ((length = read(STDIN_FILENO, buffer, 4096)) > 0) {
+ write(STDOUT_FILENO, buffer, length); /* Write to stdout. */
+ /* ...And to all other files */
+ for (i = 0; i < argc && argc != 0 && i <= 13; i++) {
+ write(fildes[i], buffer, length);
+ if (errno) ret = errprint(argv0, argv[i], length);
+ }
+ }
+ for (i = 0; i < argc && argc != 0 && i <= 13; i++) {
+ close(fildes[i]);
+ if (errno) return errprint(argv0, argv[i], errno);
+ }
+
+ return ret;
+}