7
|
1 /* vim:set ts=4 sw=4:
|
|
2 *
|
|
3 * Copyright (c) 1996, Paul Slootman
|
|
4 *
|
|
5 * Author: Paul Slootman
|
|
6 * (paul@wurtel.hobby.nl, paul@murphy.nl, paulS@toecompst.nl)
|
|
7 *
|
|
8 * This source code is released into the public domain. It is provided on an
|
|
9 * as-is basis and no responsibility is accepted for its failure to perform
|
|
10 * as expected. It is worth at least as much as you paid for it!
|
|
11 *
|
|
12 * tee.c - pipe fitting
|
|
13 *
|
|
14 * tee reads stdin, and writes what it reads to each of the specified
|
|
15 * files. The primary reason of existence for this version is a quick
|
|
16 * and dirty implementation to distribute with Vim, to make one of the
|
|
17 * most useful features of Vim possible on OS/2: quickfix.
|
|
18 *
|
|
19 * Of course, not using tee but instead redirecting make's output directly
|
|
20 * into a temp file and then processing that is possible, but if we have a
|
|
21 * system capable of correctly piping (unlike DOS, for example), why not
|
|
22 * use it as well as possible? This tee should also work on other systems,
|
|
23 * but it's not been tested there, only on OS/2.
|
|
24 *
|
|
25 * tee is also available in the GNU shellutils package, which is available
|
|
26 * precompiled for OS/2. That one probably works better.
|
|
27 */
|
|
28
|
|
29 #include <unistd.h>
|
|
30 #include <malloc.h>
|
|
31 #include <stdio.h>
|
|
32
|
|
33 void usage(void)
|
|
34 {
|
|
35 fprintf(stderr,
|
|
36 "tee usage:\n\
|
|
37 \ttee [-a] file ... file_n\n\
|
|
38 \n\
|
|
39 \t-a\tappend to files instead of truncating\n\
|
|
40 \nTee reads its input, and writes to each of the specified files,\n\
|
|
41 as well as to the standard output.\n\
|
|
42 \n\
|
|
43 This version supplied with Vim 4.2 to make ':make' possible.\n\
|
|
44 For a more complete and stable version, consider getting\n\
|
|
45 [a port of] the GNU shellutils package.\n\
|
|
46 ");
|
|
47 }
|
|
48
|
|
49 /*
|
|
50 * fread only returns when count is read or at EOF.
|
|
51 * We could use fgets, but I want to be able to handle binary blubber.
|
|
52 */
|
|
53
|
|
54 int
|
|
55 myfread(char *buf, int elsize /*ignored*/, int max, FILE *fp)
|
|
56 {
|
|
57 int c;
|
|
58 int n = 0;
|
|
59
|
|
60 while ((n < max) && ((c = getchar()) != EOF))
|
|
61 {
|
|
62 *(buf++) = c;
|
|
63 n++;
|
|
64 if (c == '\n' || c == '\r')
|
|
65 break;
|
|
66 }
|
|
67 return n;
|
|
68 }
|
|
69
|
|
70
|
|
71 void
|
|
72 main(int argc, char *argv[])
|
|
73 {
|
|
74 int append = 0;
|
|
75 int numfiles;
|
|
76 int opt;
|
|
77 int maxfiles;
|
|
78 FILE **filepointers;
|
|
79 int i;
|
|
80 char buf[BUFSIZ];
|
|
81 int n;
|
|
82 extern int optind;
|
|
83
|
|
84 while ((opt = getopt(argc, argv, "a")) != EOF)
|
|
85 {
|
|
86 switch (opt)
|
|
87 {
|
|
88 case 'a': append++;
|
|
89 break;
|
|
90 default: usage();
|
|
91 exit(2);
|
|
92 }
|
|
93 }
|
|
94
|
|
95 numfiles = argc - optind;
|
|
96
|
|
97 if (numfiles == 0)
|
|
98 {
|
|
99 fprintf(stderr, "doesn't make much sense using tee without any file name arguments...\n");
|
|
100 usage();
|
|
101 exit(2);
|
|
102 }
|
|
103
|
|
104 maxfiles = sysconf(_SC_OPEN_MAX); /* or fill in 10 or so */
|
|
105 if (maxfiles < 0)
|
|
106 maxfiles = 10;
|
|
107 if (numfiles + 3 > maxfiles) /* +3 accounts for stdin, out, err */
|
|
108 {
|
|
109 fprintf(stderr, "Sorry, there is a limit of max %d files.\n", maxfiles - 3);
|
|
110 exit(1);
|
|
111 }
|
|
112 filepointers = calloc(numfiles, sizeof(FILE *));
|
|
113 if (filepointers == NULL)
|
|
114 {
|
|
115 fprintf(stderr, "Error allocating memory for %d files\n", numfiles);
|
|
116 exit(1);
|
|
117 }
|
|
118 for (i = 0; i < numfiles; i++)
|
|
119 {
|
|
120 filepointers[i] = fopen(argv[i+optind], append ? "ab" : "wb");
|
|
121 if (filepointers[i] == NULL)
|
|
122 {
|
|
123 fprintf(stderr, "Can't open \"%s\"\n", argv[i+optind]);
|
|
124 exit(1);
|
|
125 }
|
|
126 }
|
|
127 _fsetmode(stdin, "b");
|
|
128 fflush(stdout); /* needed for _fsetmode(stdout) */
|
|
129 _fsetmode(stdout, "b");
|
|
130
|
|
131 while ((n = myfread(buf, sizeof(char), sizeof(buf), stdin)) > 0)
|
|
132 {
|
|
133 fwrite(buf, sizeof(char), n, stdout);
|
|
134 fflush(stdout);
|
|
135 for (i = 0; i < numfiles; i++)
|
|
136 {
|
|
137 if (filepointers[i] &&
|
|
138 fwrite(buf, sizeof(char), n, filepointers[i]) != n)
|
|
139 {
|
|
140 fprintf(stderr, "Error writing to file \"%s\"\n", argv[i+optind]);
|
|
141 fclose(filepointers[i]);
|
|
142 filepointers[i] = NULL;
|
|
143 }
|
|
144 }
|
|
145 }
|
|
146 for (i = 0; i < numfiles; i++)
|
|
147 {
|
|
148 if (filepointers[i])
|
|
149 fclose(filepointers[i]);
|
|
150 }
|
|
151
|
|
152 exit(0);
|
|
153 }
|