]> pd.if.org Git - pdutils/blob - utils/tee/tee.c
implemented pwd
[pdutils] / utils / tee / tee.c
1 /*
2  * tee.c - duplicate standard input
3  *
4  * Version: 2008-1.01
5  * Build:   c89 -o tee tee.c
6  * Source:  <http://pdcore.sourceforge.net/>
7  * Spec:    <http://www.opengroup.org/onlinepubs/9699919799/utilities/tee.html>
8  *
9  * This is free and unencumbered software released into the public domain,
10  * provided "as is", without warranty of any kind, express or implied. See the
11  * file UNLICENSE and the website <http://unlicense.org> for further details.
12  */
13
14
15 #define _POSIX_SOURCE
16
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <locale.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #define USAGE    "usage: tee [-ai] [file ...]\n"
27 #define AMBIGOPT "tee: Ambiguous [-]; operand or bad option?\n"
28 #define FLIMIT   "tee: Maximum of %d output files exceeded\n"
29 #define BUFSIZE  4096
30 #define MAXFILES 13
31
32 static void error(char *s);
33
34 static int exitstatus;
35
36
37 int main(int argc, char **argv)
38 {
39     extern int opterr, optind;
40     int c, i;
41     unsigned char buf[BUFSIZE];
42     ssize_t n;
43     int slot, fdfn[MAXFILES + 1][2], mode = O_WRONLY | O_CREAT | O_TRUNC;
44
45     setlocale(LC_ALL, "");
46     opterr = 0;
47
48     while ((c = getopt(argc, argv, "ai")) != -1)
49         switch (c)
50         {
51         case 'a':   /* append to rather than overwrite file(s) */
52             mode = O_WRONLY | O_CREAT | O_APPEND;
53             break;
54
55         case 'i':   /* ignore the SIGINT signal */
56             signal(SIGINT, SIG_IGN);
57             break;
58
59         default:
60             fprintf(stderr, USAGE);
61             return(1);
62         }
63
64     i = optind;
65     fdfn[0][0] = STDOUT_FILENO;
66
67     for (slot = 1; i < argc ; i++)
68     {
69         if (slot > MAXFILES)
70             fprintf(stderr, FLIMIT, MAXFILES);
71         else
72         {
73             if ((fdfn[slot][0] = open(argv[i], mode, 0666)) == -1)
74                 error(argv[i]);
75             else
76                 fdfn[slot++][1] = i;
77         }
78     }
79
80     while ((n = read(STDIN_FILENO, buf, BUFSIZE)) > 0)
81     {
82         for (i = 0; i < slot; i++)
83             if (write(fdfn[i][0], buf, (size_t)n) != n)
84                 error(argv[fdfn[i][1]]);
85     }
86
87     if (n < 0)
88         error("stdin");
89
90     for (i = 1; i < slot; i++)
91         if (close(fdfn[i][0]) == -1)
92             error(argv[fdfn[i][1]]);
93
94     return(exitstatus);
95 }
96
97
98 void error(char *s)
99 {
100     fprintf(stderr, "tee: %s: %s\n", s, strerror(errno));
101     exitstatus = 1;
102 }