Fix various compile warnings
[splice.git] / splice-fromnet.c
CommitLineData
beeecb44 1/*
27e4ade6 2 * Splice from network to stdout
beeecb44
JA
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>
27e4ade6 16#include <sys/poll.h>
beeecb44
JA
17
18#include "splice.h"
19
0b7e440c 20static unsigned int splice_size = SPLICE_SIZE;
17d773bd 21static unsigned int splice_flags;
0b7e440c
JA
22static int wait_for_poll;
23
beeecb44
JA
24static int usage(char *name)
25{
17d773bd 26 fprintf(stderr, "%s: [-s splice size] [-w wait for poll] [-n non-blocking] port\n", name);
beeecb44
JA
27 return 1;
28}
29
27e4ade6 30static int splice_from_net(int fd)
beeecb44 31{
27e4ade6 32 while (1) {
27e4ade6 33 int ret;
beeecb44 34
0b7e440c
JA
35 if (wait_for_poll) {
36 struct pollfd pfd = {
37 .fd = fd,
38 .events = POLLIN,
39 };
beeecb44 40
0b7e440c
JA
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 }
beeecb44 50
0b7e440c 51 ret = ssplice(fd, NULL, STDOUT_FILENO, NULL, splice_size, 0);
beeecb44 52
27e4ade6
JA
53 if (ret < 0)
54 return error("splice");
55 else if (!ret)
beeecb44 56 break;
27e4ade6 57 }
beeecb44
JA
58
59 return 0;
60}
61
27e4ade6 62static int get_connect(int fd, struct sockaddr_in *addr)
beeecb44 63{
27e4ade6
JA
64 socklen_t socklen = sizeof(*addr);
65 int ret, connfd;
beeecb44 66
27e4ade6
JA
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;
beeecb44
JA
86}
87
0b7e440c
JA
88static int parse_options(int argc, char *argv[])
89{
90 int c, index = 1;
91
17d773bd 92 while ((c = getopt(argc, argv, "s:w:n")) != -1) {
0b7e440c
JA
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;
17d773bd
JA
102 case 'n':
103 splice_flags |= SPLICE_F_NONBLOCK;
104 index++;
105 break;
0b7e440c
JA
106 default:
107 return -1;
108 }
109 }
110
111 return index;
112}
113
114
beeecb44
JA
115int main(int argc, char *argv[])
116{
117 struct sockaddr_in addr;
118 unsigned short port;
0b7e440c 119 int connfd, opt, fd, index;
beeecb44 120
27e4ade6 121 if (argc < 2)
beeecb44
JA
122 return usage(argv[0]);
123
27e4ade6 124 if (check_output_pipe())
beeecb44
JA
125 return usage(argv[0]);
126
0b7e440c
JA
127 index = parse_options(argc, argv);
128 if (index == -1 || index + 1 > argc)
129 return usage(argv[0]);
130
131 port = atoi(argv[index]);
beeecb44 132
27e4ade6 133 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
beeecb44
JA
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));
27e4ade6 142 addr.sin_family = AF_INET;
beeecb44
JA
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");
beeecb44
JA
148 if (listen(fd, 1) < 0)
149 return error("listen");
150
27e4ade6
JA
151 connfd = get_connect(fd, &addr);
152 if (connfd < 0)
153 return connfd;
beeecb44 154
27e4ade6 155 return splice_from_net(connfd);
beeecb44 156}