1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
/* Licensed under the GPL
* Copyright (c) Miek Gieben, 2006
*/
/* like tee(1), but then connect to other programs using
* pipes _and_ output to standard output
*/
int
close_pipes(FILE **p, size_t i)
{
int ret=EXIT_SUCCESS;
size_t j;
for (j = 0; j < i; j++) {
int r = pclose(p[j]);
if (WIFEXITED(r))
ret |= WEXITSTATUS(r);
else
ret |= 1;
}
return ret;
}
int
main(int argc, char **argv) {
int ignore_write_error = 1;
int ignore_sigpipe = 1;
size_t i, r;
FILE **pipes;
int *inactive_pipe;
int inactive_pipes = 0;
char buf[BUFSIZ];
while(argc > 1) {
if (!strcmp(argv[1], "--no-ignore-sigpipe")) {
argc--, argv++;
ignore_sigpipe = 0;
continue;
} else if (!strcmp(argv[1], "--ignore-sigpipe")) {
argc--, argv++;
ignore_sigpipe = 1;
continue;
} else if (!strcmp(argv[1], "--no-ignore-write-errors")) {
argc--, argv++;
ignore_write_error = 0;
continue;
} else if (!strcmp(argv[1], "--ignore-write-errors")) {
argc--, argv++;
ignore_write_error = 1;
continue;
}
break;
}
if (ignore_sigpipe && (signal(SIGPIPE, SIG_IGN) == SIG_ERR)) {
fprintf(stderr, "Unable to ignore SIGPIPE\n");
exit(EXIT_FAILURE);
}
pipes = malloc(((argc - 1) * sizeof *pipes));
inactive_pipe = calloc((argc - 1), (sizeof *inactive_pipe));
if (!pipes || !inactive_pipe)
exit(EXIT_FAILURE);
for (i = 1; i < argc; i++) {
pipes[i - 1] = popen(argv[i], "w");
if (!pipes[i - 1]) {
fprintf(stderr, "Can not open pipe to '%s\'\n", argv[i]);
close_pipes(pipes, argc);
exit(EXIT_FAILURE);
}
setbuf(pipes[i - 1], NULL);
}
argc--;
for (;;) {
r = read(STDIN_FILENO, buf, BUFSIZ);
/* Interrupted by signal? Try again. */
if (r == -1 && errno == EINTR)
continue;
/* Other error or EOF. */
if (r < 1)
break;
for(i = 0; i < argc; i++) {
if (inactive_pipe[i])
continue;
if (fwrite(buf, sizeof(char), r, pipes[i]) == r)
continue;
inactive_pipes++;
if (!ignore_write_error)
fprintf(stderr, "Write error to `%s\'\n",
argv[i + 1]);
if (!ignore_write_error || (inactive_pipes == argc)) {
close_pipes(pipes, argc);
exit(EXIT_FAILURE);
}
inactive_pipe[i] = 1;
}
}
exit(close_pipes(pipes, argc));
}
|