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