Commit | Line | Data |
---|---|---|
d8525fbd JA |
1 | /* |
2 | * A tee implementation using sys_tee. If only one argument is given, | |
3 | * stdin output is stored in that file and sent to stdout as well. If a | |
4 | * second argument is given, that must be in the form if host:port - in | |
5 | * that case, output is stored in file and sent over the network to the | |
6 | * given host at given port. | |
7 | */ | |
8 | #include <stdio.h> | |
9 | #include <stdlib.h> | |
10 | #include <unistd.h> | |
11 | #include <string.h> | |
12 | #include <fcntl.h> | |
13 | #include <string.h> | |
14 | #include <sys/stat.h> | |
15 | #include <sys/types.h> | |
16 | #include <errno.h> | |
17 | #include <assert.h> | |
18 | #include <limits.h> | |
19 | ||
20 | #include "splice.h" | |
21 | ||
22 | static int do_splice(int infd, int outfd, unsigned int len, char *msg) | |
23 | { | |
24 | while (len) { | |
25 | int written = splice(infd, NULL, outfd, NULL, len, 0); | |
26 | ||
27 | if (written <= 0) | |
28 | return error(msg); | |
29 | ||
30 | len -= written; | |
31 | } | |
32 | ||
33 | return 0; | |
34 | } | |
35 | ||
36 | int main(int argc, char *argv[]) | |
37 | { | |
38 | struct stat sb; | |
39 | int fd; | |
40 | ||
41 | if (argc < 2) { | |
42 | fprintf(stderr, "%s: outfile\n", argv[0]); | |
43 | return 1; | |
44 | } | |
45 | ||
46 | if (fstat(STDIN_FILENO, &sb) < 0) | |
47 | return error("stat"); | |
48 | if (!S_ISFIFO(sb.st_mode)) { | |
49 | fprintf(stderr, "stdout must be a pipe\n"); | |
50 | return 1; | |
51 | } | |
52 | ||
53 | fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
54 | if (fd < 0) | |
55 | return error("open output"); | |
56 | ||
57 | do { | |
58 | int tee_len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK); | |
59 | ||
60 | if (tee_len < 0) { | |
61 | if (errno == EAGAIN) { | |
62 | usleep(1000); | |
63 | continue; | |
64 | } | |
65 | return error("tee"); | |
66 | } else if (!tee_len) | |
67 | break; | |
68 | ||
69 | /* | |
70 | * Send output to file, also consumes input pipe. | |
71 | */ | |
72 | if (do_splice(STDIN_FILENO, fd, tee_len, "splice-file")) | |
73 | break; | |
74 | } while (1); | |
75 | ||
76 | return 0; | |
77 | } |