/* * tee.c - duplicate standard input * * Version: 2008-1.01 * Build: c89 -o tee tee.c * Source: * Spec: * * This is free and unencumbered software released into the public domain, * provided "as is", without warranty of any kind, express or implied. See the * file UNLICENSE and the website for further details. */ #define _POSIX_SOURCE #include #include #include #include #include #include #include #include #define USAGE "usage: tee [-ai] [file ...]\n" #define AMBIGOPT "tee: Ambiguous [-]; operand or bad option?\n" #define FLIMIT "tee: Maximum of %d output files exceeded\n" #define BUFSIZE 4096 #define MAXFILES 13 static void error(char *s); static int exitstatus; int main(int argc, char **argv) { extern int opterr, optind; int c, i; unsigned char buf[BUFSIZE]; ssize_t n; int slot, fdfn[MAXFILES + 1][2], mode = O_WRONLY | O_CREAT | O_TRUNC; setlocale(LC_ALL, ""); opterr = 0; while ((c = getopt(argc, argv, "ai")) != -1) switch (c) { case 'a': /* append to rather than overwrite file(s) */ mode = O_WRONLY | O_CREAT | O_APPEND; break; case 'i': /* ignore the SIGINT signal */ signal(SIGINT, SIG_IGN); break; default: fprintf(stderr, USAGE); return(1); } i = optind; fdfn[0][0] = STDOUT_FILENO; for (slot = 1; i < argc ; i++) { if (slot > MAXFILES) fprintf(stderr, FLIMIT, MAXFILES); else { if ((fdfn[slot][0] = open(argv[i], mode, 0666)) == -1) error(argv[i]); else fdfn[slot++][1] = i; } } while ((n = read(STDIN_FILENO, buf, BUFSIZE)) > 0) { for (i = 0; i < slot; i++) if (write(fdfn[i][0], buf, (size_t)n) != n) error(argv[fdfn[i][1]]); } if (n < 0) error("stdin"); for (i = 1; i < slot; i++) if (close(fdfn[i][0]) == -1) error(argv[fdfn[i][1]]); return(exitstatus); } void error(char *s) { fprintf(stderr, "tee: %s: %s\n", s, strerror(errno)); exitstatus = 1; }