Fix various compile warnings
[splice.git] / ktee-net.c
1 /*
2  * A tee implementation using sys_tee. Sends out the data received over
3  * stdin to the given host:port and over stdout.
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 #include <netdb.h>
13 #include <sys/types.h>
14 #include <errno.h>
15 #include <limits.h>
16
17 #include "splice.h"
18
19 static int do_splice(int infd, int outfd, unsigned int len, char *msg)
20 {
21         while (len) {
22                 int written = ssplice(infd, NULL, outfd, NULL, len, 0);
23
24                 if (written <= 0)
25                         return error(msg);
26
27                 len -= written;
28         }
29
30         return 0;
31 }
32
33 static int usage(char *name)
34 {
35         fprintf(stderr, "... | %s: hostname:port\n", name);
36         return 1;
37 }
38
39 int main(int argc, char *argv[])
40 {
41         struct sockaddr_in addr;
42         char *p, *hname;
43         int fd;
44
45         if (argc < 2)
46                 return usage(argv[0]);
47
48         if (check_input_pipe())
49                 return usage(argv[0]);
50
51         hname = strdup(argv[1]);
52         p = strstr(hname, ":");
53         if (!p)
54                 return usage(argv[0]);
55
56         memset(&addr, 0, sizeof(addr));
57         addr.sin_family = AF_INET;
58         addr.sin_port = htons(atoi(p + 1));
59         *p = '\0';
60
61         if (inet_aton(hname, &addr.sin_addr) != 1) {
62                 struct hostent *hent = gethostbyname(hname);
63
64                 if (!hent)
65                         return error("gethostbyname");
66
67                 memcpy(&addr.sin_addr, hent->h_addr, 4);
68         }
69
70         fd = socket(AF_INET, SOCK_STREAM, 0);
71         if (fd < 0)
72                 return error("socket");
73
74         if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
75                 return error("connect");
76
77         do {
78                 int tee_len = stee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, 0);
79
80                 if (tee_len < 0) {
81                         if (errno == EAGAIN) {
82                                 usleep(1000);
83                                 continue;
84                         }
85                         return error("tee");
86                 } else if (!tee_len)
87                         break;
88
89                 /*
90                  * Send output to file, also consumes input pipe.
91                  */
92                 if (do_splice(STDIN_FILENO, fd, tee_len, "splice-net"))
93                         break;
94         } while (1);
95
96         close(fd);
97         return 0;
98 }