Introduction
Introduction Statistics Contact Development Disclaimer Help
teed.c - teed - A multiplex relay tee(1) daemon.
git clone git://bitreich.org/teed git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d…
Log
Files
Refs
Tags
README
LICENSE
---
teed.c (5223B)
---
1 /*
2 * See LICENSE file for license information.
3 *
4 * Copy me if you can.
5 * by 20h
6 */
7
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <sys/un.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include <sys/stat.h>
17 #include <sys/select.h>
18
19 volatile sig_atomic_t isrunning = 1;
20
21 void *
22 memdup(void *p, int l)
23 {
24 char *ret;
25
26 ret = calloc(1, l);
27 if (ret == NULL) {
28 perror("calloc");
29 exit(1);
30 }
31 memcpy(ret, p, l);
32
33 return (void *)ret;
34 }
35
36 typedef struct llist llist;
37 struct llist {
38 llist *prev;
39 llist *next;
40 int dlen;
41 void *data;
42 };
43
44 #define forllist(list, elem) for (elem = list;\
45 elem; elem = elem->next)
46
47 void
48 closeallfds(llist *fds)
49 {
50 llist *e;
51
52 forllist(fds, e)
53 close(*(int *)e->data);
54 }
55
56 void
57 llist_free1(llist *l)
58 {
59 if (l == NULL)
60 return;
61 free(l->data);
62 l->data = NULL;
63 l->next = NULL;
64 l->prev = NULL;
65 free(l);
66 }
67
68 void
69 llist_free(llist *l)
70 {
71 llist *tl;
72
73 while (l != NULL) {
74 tl = l->next;
75 llist_free1(l);
76 l = tl;
77 }
78 }
79
80 llist *
81 llist_new(llist *prev, llist *next, void *data, int len)
82 {
83 llist *ret;
84
85 ret = calloc(1, sizeof(llist));
86 if (ret == NULL) {
87 perror("calloc");
88 exit(1);
89 }
90 ret->prev = prev;
91 ret->next = next;
92 if (data != NULL) {
93 ret->data = memdup(data, len);
94 ret->dlen = len;
95 } else {
96 ret->data = NULL;
97 ret->dlen = 0;
98 }
99
100 return ret;
101 }
102
103 int
104 llist_len(llist *l)
105 {
106 int llistl = 0;
107 for (;l != NULL; l = l->next)
108 llistl++;
109 return llistl;
110 }
111
112 llist *
113 llist_put(llist *l, void *data, int len)
114 {
115 llist *ol;
116
117 if (l == NULL)
118 return llist_new(NULL, NULL, data, len);
119
120 ol = l;
121 for (; l->next; l = l->next);
122 l->next = llist_new(l, NULL, data, len);
123
124 return ol;
125 }
126
127 llist *
128 llist_del(llist **l, llist *e)
129 {
130 llist *enext, *eprev;
131
132 enext = e->next;
133 eprev = e->prev;
134 if (enext != NULL)
135 enext->prev = eprev;
136 if (eprev != NULL)
137 eprev->next = enext;
138 llist_free1(e);
139
140 if (*l == e)
141 *l = enext;
142
143 if (eprev != NULL)
144 return eprev;
145 if (enext != NULL)
146 return enext;
147 return NULL;
148 }
149
150 void
151 sighandler(int signo)
152 {
153 switch (signo) {
154 case SIGINT:
155 case SIGTERM:
156 isrunning = 0;
157 break;
158 }
159 }
160
161 void
162 initsignals(void)
163 {
164 signal(SIGPIPE, SIG_IGN);
165 signal(SIGINT, sighandler);
166 signal(SIGTERM, sighandler);
167 }
168
169 int
170 main(int argc, char *argv[])
171 {
172 int on, i, maxsfd, afd, rval, recvl,
173 sendl, sent, lfd;
174 struct sockaddr_un saddrs[2], clt;
175 char *bindpaths[2] = {"in", "out"},
176 recvbuf[4*1024],
177 *sendbufi;
178 llist *wfds, *rfds, *lfds, *e, *qe;
179 socklen_t saddrlen, cltlen;
180 fd_set fdset;
181 struct timespec timeout;
182
183 initsignals();
184
185 rval = 1;
186 rfds = NULL;
187 wfds = NULL;
188 lfds = NULL;
189
190 on = 1;
191 for (i = 0; i < 2; i++) {
192 lfd = socket(AF_UNIX, SOCK_STREAM, 0);
193 if (lfd < 0) {
194 perror("socket");
195 goto stop_serving;
196 }
197 if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,
198 &on, sizeof(on)) < 0) {
199 perror("setsockopt");
200 goto stop_serving;
201 }
202
203 if (access(bindpaths[i], F_OK) == 0) {
204 if (remove(bindpaths[i]) < 0) {
205 perror("remove");
206 goto stop_serving;
207 }
208 }
209
210 saddrs[i].sun_family = AF_UNIX;
211 strncpy(saddrs[i].sun_path, bindpaths[i],
212 sizeof(bindpaths[i])-1);
213 saddrlen = sizeof(saddrs[i]);
214
215 if (bind(lfd, (struct sockaddr *)&saddrs[i], saddrlen) <…
216 perror("bind");
217 goto stop_serving;
218 }
219
220 if (chmod(bindpaths[i], 0775) < 0) {
221 perror("chmod");
222 goto stop_serving;
223 }
224
225 if (listen(lfd, 255) < 0) {
226 perror("listen");
227 goto stop_serving;
228 }
229
230 lfds = llist_put(lfds, &lfd, sizeof(lfd));
231 }
232
233 timeout.tv_sec = 1;
234 timeout.tv_nsec = 0;
235 for (;isrunning;) {
236 maxsfd = 0;
237 FD_ZERO(&fdset);
238 forllist(lfds, e) {
239 FD_SET(*(int *)e->data, &fdset);
240 if (*(int *)e->data > maxsfd)
241 maxsfd = *(int *)e->data;
242 }
243 forllist(rfds, e) {
244 FD_SET(*(int *)e->data, &fdset);
245 if (*(int *)e->data > maxsfd)
246 maxsfd = *(int *)e->data;
247 }
248
249 if (pselect(maxsfd+1, &fdset, NULL, NULL, &timeout, NULL…
250 if (errno == EINTR)
251 continue;
252 perror("pselect");
253 goto stop_serving;
254 }
255
256 i = -1;
257 forllist(lfds, e) {
258 i++;
259 if (FD_ISSET(*(int *)e->data, &fdset)) {
260 cltlen = sizeof(clt);
261 afd = accept(*(int *)e->data,
262 (struct sockaddr *)&clt,
263 &cltlen);
264 if (afd < 0 && errno != ECONNABORTED
265 && errno != EINTR) {
266 perror("accept");
267 goto stop_serving;
268 }
269
270 if (i == 0) {
271 rfds = llist_put(rfds, &afd,
272 sizeof(afd));
273 } else {
274 wfds = llist_put(wfds, &afd,
275 sizeof(afd));
276 }
277 }
278 }
279
280 forllist(rfds, e) {
281 if (FD_ISSET(*(int *)e->data, &fdset)) {
282 recvl = read(*(int *)e->data, recvbuf,
283 sizeof(recvbuf));
284 if (recvl <= 0) {
285 close(*(int *)e->data);
286 e = llist_del(&rfds, e);
287 if (e == NULL)
288 break;
289 }
290
291 forllist(wfds, qe) {
292 sendbufi = recvbuf;
293 sendl = recvl;
294 while (sendl > 0) {
295 if ((sent = write(*(int …
296 close(*(int *)qe…
297 qe = llist_del(&…
298 break;
299 }
300 sendl -= sent;
301 sendbufi += sent;
302 }
303 if (qe == NULL)
304 break;
305 }
306 }
307 }
308
309 }
310
311 rval = 0;
312 stop_serving:
313 closeallfds(lfds);
314 llist_free(lfds);
315 closeallfds(rfds);
316 llist_free(rfds);
317 closeallfds(wfds);
318 llist_free(wfds);
319
320 return rval;
321 }
322
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.