Fix various compile warnings
[splice.git] / splice-fromnet.c
1 /*
2  * Splice from network to stdout
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <netdb.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <signal.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <string.h>
14 #include <sys/time.h>
15 #include <errno.h>
16 #include <sys/poll.h>
17
18 #include "splice.h"
19
20 static unsigned int splice_size = SPLICE_SIZE;
21 static unsigned int splice_flags;
22 static int wait_for_poll;
23
24 static int usage(char *name)
25 {
26         fprintf(stderr, "%s: [-s splice size] [-w wait for poll] [-n non-blocking] port\n", name);
27         return 1;
28 }
29
30 static int splice_from_net(int fd)
31 {
32         while (1) {
33                 int ret;
34
35                 if (wait_for_poll) {
36                         struct pollfd pfd = {
37                                 .fd = fd,
38                                 .events = POLLIN,
39                         };
40
41                         ret = poll(&pfd, 1, -1);
42                         if (ret < 0)
43                                 return error("poll");
44                         else if (!ret)
45                                 continue;
46
47                         if (!(pfd.revents & POLLIN))
48                                 continue;
49                 }
50
51                 ret = ssplice(fd, NULL, STDOUT_FILENO, NULL, splice_size, 0);
52
53                 if (ret < 0)
54                         return error("splice");
55                 else if (!ret)
56                         break;
57         }
58
59         return 0;
60 }
61
62 static int get_connect(int fd, struct sockaddr_in *addr)
63 {
64         socklen_t socklen = sizeof(*addr);
65         int ret, connfd;
66
67         do {
68                 struct pollfd pfd = {
69                         .fd = fd,
70                         .events = POLLIN,
71                 };
72
73                 ret = poll(&pfd, 1, -1);
74                 if (ret < 0)
75                         return error("poll");
76                 else if (!ret)
77                         continue;
78
79                 connfd = accept(fd, (struct sockaddr *) addr, &socklen);
80                 if (connfd < 0)
81                         return error("accept");
82                 break;
83         } while (1);
84                         
85         return connfd;
86 }
87
88 static int parse_options(int argc, char *argv[])
89 {
90         int c, index = 1;
91
92         while ((c = getopt(argc, argv, "s:w:n")) != -1) {
93                 switch (c) {
94                 case 's':
95                         splice_size = atoi(optarg);
96                         index++;
97                         break;
98                 case 'w':
99                         wait_for_poll = atoi(optarg);
100                         index++;
101                         break;
102                 case 'n':
103                         splice_flags |= SPLICE_F_NONBLOCK;
104                         index++;
105                         break;
106                 default:
107                         return -1;
108                 }
109         }
110
111         return index;
112 }
113
114
115 int main(int argc, char *argv[])
116 {
117         struct sockaddr_in addr;
118         unsigned short port;
119         int connfd, opt, fd, index;
120
121         if (argc < 2)
122                 return usage(argv[0]);
123
124         if (check_output_pipe())
125                 return usage(argv[0]);
126
127         index = parse_options(argc, argv);
128         if (index == -1 || index + 1 > argc)
129                 return usage(argv[0]);
130
131         port = atoi(argv[index]);
132
133         fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
134         if (fd < 0)
135                 return error("socket");
136
137         opt = 1;
138         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
139                 return error("setsockopt");
140
141         memset(&addr, 0, sizeof(addr));
142         addr.sin_family = AF_INET;
143         addr.sin_addr.s_addr = htonl(INADDR_ANY);
144         addr.sin_port = htons(port);
145
146         if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0)
147                 return error("bind");
148         if (listen(fd, 1) < 0)
149                 return error("listen");
150
151         connfd = get_connect(fd, &addr);
152         if (connfd < 0)
153                 return connfd;
154
155         return splice_from_net(connfd);
156 }