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));
}
|