- }
-
- /* init FILE pointers */
- FL_init();
- for ( ; i < argc; i++) {
- FL_add(argv[i], opt_fopen);
- }
-
- /* read and redirect */
- while ((c = (char) getchar()) && (!feof(stdin))) {
- FL_apply(tee_fwrite, c);
- }
-
- /* clean up */
- FL_apply(tee_fclose, 0);
- exit(0);
+ 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);
+
+ /* Allocate an array of FILE *'s, with one extra for a sentinel. */
+ fp = files = xzalloc(sizeof(FILE *) * (argc + 2));
+ np = names = argv - 1;
+
+ files[0] = stdout;
+ goto GOT_NEW_FILE;
+ do {
+ *fp = stdout;
+ if (NOT_LONE_DASH(*argv)) {
+ *fp = fopen_or_warn(*argv, mode);
+ if (*fp == NULL) {
+ retval = EXIT_FAILURE;
+ argv++;
+ continue;
+ }
+ }
+ *np = *argv++;
+ GOT_NEW_FILE:
+ setbuf(*fp, NULL); /* tee must not buffer output. */
+ fp++;
+ np++;
+ } while (*argv);
+ /* names[0] will be filled later */
+
+#if ENABLE_FEATURE_TEE_USE_BLOCK_IO
+ while ((c = safe_read(STDIN_FILENO, buf, sizeof(buf))) > 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);