summaryrefslogtreecommitdiff
path: root/i/pc104/initrd/conf/busybox/coreutils/tee.c
diff options
context:
space:
mode:
Diffstat (limited to 'i/pc104/initrd/conf/busybox/coreutils/tee.c')
-rw-r--r--i/pc104/initrd/conf/busybox/coreutils/tee.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/i/pc104/initrd/conf/busybox/coreutils/tee.c b/i/pc104/initrd/conf/busybox/coreutils/tee.c
new file mode 100644
index 0000000..338232c
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/coreutils/tee.c
@@ -0,0 +1,101 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tee implementation for busybox
+ *
+ * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant */
+/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
+
+#include "busybox.h"
+#include <signal.h>
+
+int tee_main(int argc, char **argv);
+int tee_main(int argc, char **argv)
+{
+ const char *mode = "w\0a";
+ FILE **files;
+ FILE **fp;
+ char **names;
+ char **np;
+ char retval;
+#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
+ ssize_t c;
+# define buf bb_common_bufsiz1
+#else
+ int c;
+#endif
+ retval = getopt32(argc, argv, "ia"); /* 'a' must be 2nd */
+ argc -= optind;
+ argv += optind;
+
+ mode += (retval & 2); /* Since 'a' is the 2nd option... */
+
+ if (retval & 1) {
+ signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. */
+ }
+ retval = EXIT_SUCCESS;
+ /* gnu tee ignores SIGPIPE in case one of the output files is a pipe
+ * that doesn't consume all its input. Good idea... */
+ signal(SIGPIPE, SIG_IGN); /* TODO - switch to sigaction. */
+
+ /* Allocate an array of FILE *'s, with one extra for a sentinal. */
+ fp = files = xzalloc(sizeof(FILE *) * (argc + 2));
+ np = names = argv - 1;
+
+ files[0] = stdout;
+ goto GOT_NEW_FILE;
+ do {
+ *fp = fopen_or_warn(*argv, mode);
+ if (*fp == NULL) {
+ retval = EXIT_FAILURE;
+ continue;
+ }
+ *np = *argv++;
+ GOT_NEW_FILE:
+ setbuf(*fp++, NULL); /* tee must not buffer output. */
+ np++;
+ } while (*argv);
+ /* names[0] will be filled later */
+
+#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
+ while ((c = safe_read(STDIN_FILENO, buf, BUFSIZ)) > 0) {
+ fp = files;
+ do
+ fwrite(buf, 1, c, *fp++);
+ while (*fp);
+ }
+ if (c < 0) { /* Make sure read errors are signaled. */
+ retval = EXIT_FAILURE;
+ }
+#else
+ setvbuf(stdout, NULL, _IONBF, 0);
+ while ((c = getchar()) != EOF) {
+ fp = files;
+ do
+ putc(c, *fp++);
+ while (*fp);
+ }
+#endif
+
+ /* Now we need to check for i/o errors on stdin and the various
+ * output files. Since we know that the first entry in the output
+ * file table is stdout, we can save one "if ferror" test by
+ * setting the first entry to stdin and checking stdout error
+ * status with fflush_stdout_and_exit()... although fflush()ing
+ * is unnecessary here. */
+ np = names;
+ fp = files;
+ names[0] = (char *) bb_msg_standard_input;
+ files[0] = stdin;
+ do { /* Now check for input and output errors. */
+ /* Checking ferror should be sufficient, but we may want to fclose.
+ * If we do, remember not to close stdin! */
+ die_if_ferror(*fp++, *np++);
+ } while (*fp);
+
+ fflush_stdout_and_exit(retval);
+}