nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* source: xioopen.c */ |
2 | /* Copyright Gerhard Rieger */ |
||
3 | /* Published under the GNU General Public License V.2, see file COPYING */ |
||
4 | |||
5 | /* this is the source file of the extended open function */ |
||
6 | |||
7 | #include "xiosysincludes.h" |
||
8 | |||
9 | #include "xioopen.h" |
||
10 | #include "xiomodes.h" |
||
11 | #include "nestlex.h" |
||
12 | |||
13 | #include "xiosigchld.h" |
||
14 | |||
15 | void *xioopenleftthenengine(void *thread_void); |
||
16 | static xiosingle_t *xioparse_single(const char **addr); |
||
17 | |||
18 | static int |
||
19 | xioopen_inter_single(xiofile_t *xfd, int xioflags); |
||
20 | static int |
||
21 | xioopen_endpoint_single(xiofile_t *xfd, int xioflags); |
||
22 | static int |
||
23 | xioopen_unoverload(xiosingle_t *sfd, |
||
24 | int mayleft, /* what may be on left side: or'd |
||
25 | XIOBIT_RDWR, XIOBIT_RDONLY, |
||
26 | XIOBIT_WRONLY */ |
||
27 | int *isleft, /* what the selected address desc |
||
28 | provides on left side: XIO_RDWR, |
||
29 | XIO_RDONLY, or XIO_WRONLY */ |
||
30 | int mayright, /* what may be on right side: or'd |
||
31 | XIOBIT_RDWR, XIOBIT_RDONLY, |
||
32 | XIOBIT_WRONLY */ |
||
33 | int *isright); /* what the selected address desc |
||
34 | provides on right side: XIO_RDWR, |
||
35 | XIO_RDONLY, or XIO_WRONLY */ |
||
36 | |||
37 | |||
38 | const struct xioaddrname address_names[] = { |
||
39 | #if 1 |
||
40 | #if WITH_STDIO |
||
41 | { "-", xioaddrs_stdio }, |
||
42 | #endif |
||
43 | #if defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) |
||
44 | { "abstract", xioaddrs_abstract_client }, |
||
45 | { "abstract-client", xioaddrs_abstract_client }, |
||
46 | { "abstract-connect", xioaddrs_abstract_connect }, |
||
47 | #if WITH_LISTEN |
||
48 | { "abstract-listen", xioaddrs_abstract_listen }, |
||
49 | #endif |
||
50 | { "abstract-recv", xioaddrs_abstract_recv }, |
||
51 | { "abstract-recvfrom", xioaddrs_abstract_recvfrom }, |
||
52 | { "abstract-sendto", xioaddrs_abstract_sendto }, |
||
53 | #endif /* defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) */ |
||
54 | #if WITH_CREAT |
||
55 | { "creat", xioaddrs_creat }, |
||
56 | { "create", xioaddrs_creat }, |
||
57 | #endif |
||
58 | #if WITH_GENERICSOCKET |
||
59 | { "datagram", xioaddrs_socket_datagram }, |
||
60 | { "dgram", xioaddrs_socket_datagram }, |
||
61 | #endif |
||
62 | #if WITH_PIPE |
||
63 | { "echo", xioaddrs_pipe }, |
||
64 | #endif |
||
65 | #if WITH_EXEC |
||
66 | { "exec", xioaddrs_exec }, |
||
67 | { "exec1", xioaddrs_exec1 }, |
||
68 | { "exec2", xioaddrs_exec }, |
||
69 | #endif |
||
70 | #if WITH_FDNUM |
||
71 | { "fd", xioaddrs_fdnum }, |
||
72 | #endif |
||
73 | #if WITH_PIPE |
||
74 | { "fifo", xioaddrs_pipe }, |
||
75 | #endif |
||
76 | #if WITH_FILE |
||
77 | { "file", xioaddrs_open }, |
||
78 | #endif |
||
79 | #if WITH_GOPEN |
||
80 | { "gopen", xioaddrs_gopen }, |
||
81 | #endif |
||
82 | #if WITH_INTERFACE |
||
83 | { "if", xioaddrs_interface }, |
||
84 | #endif |
||
85 | #if (WITH_IP4 || WITH_IP6) && WITH_TCP |
||
86 | { "inet", xioaddrs_tcp_connect }, |
||
87 | #endif |
||
88 | #if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN |
||
89 | { "inet-l", xioaddrs_tcp_listen }, |
||
90 | { "inet-listen", xioaddrs_tcp_listen }, |
||
91 | #endif |
||
92 | #if WITH_IP4 && WITH_TCP |
||
93 | { "inet4", xioaddrs_tcp4_connect }, |
||
94 | #endif |
||
95 | #if WITH_IP4 && WITH_TCP && WITH_LISTEN |
||
96 | { "inet4-l", xioaddrs_tcp4_listen }, |
||
97 | { "inet4-listen", xioaddrs_tcp4_listen }, |
||
98 | #endif |
||
99 | #if WITH_IP6 && WITH_TCP |
||
100 | { "inet6", xioaddrs_tcp6_connect }, |
||
101 | #endif |
||
102 | #if WITH_IP6 && WITH_TCP && WITH_LISTEN |
||
103 | { "inet6-l", xioaddrs_tcp6_listen }, |
||
104 | { "inet6-listen", xioaddrs_tcp6_listen }, |
||
105 | #endif |
||
106 | #if WITH_INTERFACE |
||
107 | { "interface", xioaddrs_interface }, |
||
108 | #endif |
||
109 | #if WITH_RAWIP |
||
110 | #if (WITH_IP4 || WITH_IP6) |
||
111 | { "ip", xioaddrs_rawip_sendto }, |
||
112 | { "ip-datagram", xioaddrs_rawip_datagram }, |
||
113 | { "ip-dgram", xioaddrs_rawip_datagram }, |
||
114 | { "ip-recv", xioaddrs_rawip_recv }, |
||
115 | { "ip-recvfrom", xioaddrs_rawip_recvfrom }, |
||
116 | { "ip-send", xioaddrs_rawip_sendto }, |
||
117 | { "ip-sendto", xioaddrs_rawip_sendto }, |
||
118 | #endif |
||
119 | #if WITH_IP4 |
||
120 | { "ip4", xioaddrs_rawip4_sendto }, |
||
121 | { "ip4-datagram", xioaddrs_rawip4_datagram }, |
||
122 | { "ip4-dgram", xioaddrs_rawip4_datagram }, |
||
123 | { "ip4-recv", xioaddrs_rawip4_recv }, |
||
124 | { "ip4-recvfrom", xioaddrs_rawip4_recvfrom }, |
||
125 | { "ip4-send", xioaddrs_rawip4_sendto }, |
||
126 | { "ip4-sendto", xioaddrs_rawip4_sendto }, |
||
127 | #endif |
||
128 | #if WITH_IP6 |
||
129 | { "ip6", xioaddrs_rawip6_sendto }, |
||
130 | { "ip6-datagram", xioaddrs_rawip6_datagram }, |
||
131 | { "ip6-dgram", xioaddrs_rawip6_datagram }, |
||
132 | { "ip6-recv", xioaddrs_rawip6_recv }, |
||
133 | { "ip6-recvfrom", xioaddrs_rawip6_recvfrom }, |
||
134 | { "ip6-send", xioaddrs_rawip6_sendto }, |
||
135 | { "ip6-sendto", xioaddrs_rawip6_sendto }, |
||
136 | #endif |
||
137 | #endif /* WITH_RAWIP */ |
||
138 | #if WITH_UNIX |
||
139 | { "local", xioaddrs_unix_connect }, |
||
140 | #endif |
||
141 | #if WITH_NOP |
||
142 | { "nop", xioaddrs_nop }, |
||
143 | #endif |
||
144 | #if WITH_FILE |
||
145 | { "open", xioaddrs_open }, |
||
146 | #endif |
||
147 | #if WITH_OPENSSL |
||
148 | { "openssl", xioaddrs_openssl_connect }, |
||
149 | { "openssl-client", xioaddrs_openssl_connect }, |
||
150 | { "openssl-connect", xioaddrs_openssl_connect }, |
||
151 | #if WITH_LISTEN |
||
152 | { "openssl-listen", xioaddrs_openssl_listen }, |
||
153 | { "openssl-server", xioaddrs_openssl_listen }, |
||
154 | #endif |
||
155 | #endif |
||
156 | #if WITH_PIPE |
||
157 | { "pipe", xioaddrs_pipe }, |
||
158 | #endif |
||
159 | #if WITH_PROXY |
||
160 | { "proxy", xioaddrs_proxy_connect }, |
||
161 | { "proxy-connect", xioaddrs_proxy_connect }, |
||
162 | #endif |
||
163 | #if WITH_PTY |
||
164 | { "pty", xioaddrs_pty }, |
||
165 | #endif |
||
166 | #if WITH_READLINE |
||
167 | { "readline", xioaddrs_readline }, |
||
168 | #endif |
||
169 | #if (WITH_IP4 || WITH_IP6) && WITH_SCTP |
||
170 | { "sctp", xioaddrs_sctp_connect }, |
||
171 | { "sctp-connect", xioaddrs_sctp_connect }, |
||
172 | #if WITH_LISTEN |
||
173 | { "sctp-l", xioaddrs_sctp_listen }, |
||
174 | { "sctp-listen", xioaddrs_sctp_listen }, |
||
175 | #endif |
||
176 | #if WITH_IP4 |
||
177 | { "sctp4", xioaddrs_sctp4_connect }, |
||
178 | { "sctp4-connect", xioaddrs_sctp4_connect }, |
||
179 | #if WITH_LISTEN |
||
180 | { "sctp4-l", xioaddrs_sctp4_listen }, |
||
181 | { "sctp4-listen", xioaddrs_sctp4_listen }, |
||
182 | #endif |
||
183 | #endif /* WITH_IP4 */ |
||
184 | #if WITH_IP6 |
||
185 | { "sctp6", xioaddrs_sctp6_connect }, |
||
186 | { "sctp6-connect", xioaddrs_sctp6_connect }, |
||
187 | #if WITH_LISTEN |
||
188 | { "sctp6-l", xioaddrs_sctp6_listen }, |
||
189 | { "sctp6-listen", xioaddrs_sctp6_listen }, |
||
190 | #endif |
||
191 | #endif /* WITH_IP6 */ |
||
192 | #endif /* (WITH_IP4 || WITH_IP6) && WITH_SCTP */ |
||
193 | #if WITH_GENERICSOCKET |
||
194 | { "sendto", xioaddrs_socket_sendto }, |
||
195 | #endif |
||
196 | #if WITH_GENERICSOCKET |
||
197 | { "socket-connect", xioaddrs_socket_connect }, |
||
198 | { "socket-datagram", xioaddrs_socket_datagram }, |
||
199 | #if WITH_LISTEN |
||
200 | { "socket-listen", xioaddrs_socket_listen }, |
||
201 | #endif /* WITH_LISTEN */ |
||
202 | { "socket-recv", xioaddrs_socket_recv }, |
||
203 | { "socket-recvfrom", xioaddrs_socket_recvfrom }, |
||
204 | { "socket-sendto", xioaddrs_socket_sendto }, |
||
205 | #endif |
||
206 | #if WITH_SOCKS4 |
||
207 | { "socks", xioaddrs_socks4_connect }, |
||
208 | { "socks-client", xioaddrs_socks4_connect }, |
||
209 | { "socks4", xioaddrs_socks4_connect }, |
||
210 | { "socks4-client", xioaddrs_socks4_connect }, |
||
211 | #endif |
||
212 | #if WITH_SOCKS4A |
||
213 | { "socks4a", xioaddrs_socks4a_connect }, |
||
214 | { "socks4a-client", xioaddrs_socks4a_connect }, |
||
215 | #endif |
||
216 | #if WITH_SOCKS5 |
||
217 | { "socks5", xioaddrs_socks5_client }, |
||
218 | { "socks5-client", xioaddrs_socks5_client }, |
||
219 | #endif |
||
220 | #if WITH_OPENSSL |
||
221 | { "ssl", xioaddrs_openssl_connect }, |
||
222 | #if WITH_LISTEN |
||
223 | { "ssl-l", xioaddrs_openssl_listen }, |
||
224 | { "ssl-s", xioaddrs_openssl_listen }, |
||
225 | #endif |
||
226 | #endif |
||
227 | #if WITH_STDIO |
||
228 | { "stderr", xioaddrs_stderr }, |
||
229 | { "stdin", xioaddrs_stdin }, |
||
230 | { "stdio", xioaddrs_stdio }, |
||
231 | { "stdout", xioaddrs_stdout }, |
||
232 | #endif |
||
233 | #if WITH_SYSTEM |
||
234 | { "system", xioaddrs_system }, |
||
235 | { "system1", xioaddrs_system1 }, |
||
236 | { "system2", xioaddrs_system }, |
||
237 | #endif |
||
238 | #if (WITH_IP4 || WITH_IP6) && WITH_TCP |
||
239 | { "tcp", xioaddrs_tcp_connect }, |
||
240 | { "tcp-connect", xioaddrs_tcp_connect }, |
||
241 | #endif |
||
242 | #if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN |
||
243 | { "tcp-l", xioaddrs_tcp_listen }, |
||
244 | { "tcp-listen", xioaddrs_tcp_listen }, |
||
245 | #endif |
||
246 | #if WITH_IP4 && WITH_TCP |
||
247 | { "tcp4", xioaddrs_tcp4_connect }, |
||
248 | { "tcp4-connect", xioaddrs_tcp4_connect }, |
||
249 | #endif |
||
250 | #if WITH_IP4 && WITH_TCP && WITH_LISTEN |
||
251 | { "tcp4-l", xioaddrs_tcp4_listen }, |
||
252 | { "tcp4-listen", xioaddrs_tcp4_listen }, |
||
253 | #endif |
||
254 | #if WITH_IP6 && WITH_TCP |
||
255 | { "tcp6", xioaddrs_tcp6_connect }, |
||
256 | { "tcp6-connect", xioaddrs_tcp6_connect }, |
||
257 | #endif |
||
258 | #if WITH_IP6 && WITH_TCP && WITH_LISTEN |
||
259 | { "tcp6-l", xioaddrs_tcp6_listen }, |
||
260 | { "tcp6-listen", xioaddrs_tcp6_listen }, |
||
261 | #endif |
||
262 | #if WITH_TEST |
||
263 | { "test", xioaddrs_test }, |
||
264 | { "testrev", xioaddrs_testrev }, |
||
265 | { "testuni", xioaddrs_testuni }, |
||
266 | #endif |
||
267 | #if WITH_TUN |
||
268 | { "tun", xioaddrs_tun }, |
||
269 | #endif |
||
270 | #if (WITH_IP4 || WITH_IP6) && WITH_UDP |
||
271 | { "udp", xioaddrs_udp_connect }, |
||
272 | { "udp-connect", xioaddrs_udp_connect }, |
||
273 | { "udp-datagram", xioaddrs_udp_datagram }, |
||
274 | { "udp-dgram", xioaddrs_udp_datagram }, |
||
275 | #endif |
||
276 | #if (WITH_IP4 || WITH_IP6) && WITH_UDP && WITH_LISTEN |
||
277 | { "udp-l", xioaddrs_udp_listen }, |
||
278 | { "udp-listen", xioaddrs_udp_listen }, |
||
279 | #endif |
||
280 | #if (WITH_IP4 || WITH_IP6) && WITH_UDP |
||
281 | { "udp-recv", xioaddrs_udp_recv }, |
||
282 | { "udp-recvfrom", xioaddrs_udp_recvfrom }, |
||
283 | { "udp-send", xioaddrs_udp_sendto }, |
||
284 | { "udp-sendto", xioaddrs_udp_sendto }, |
||
285 | #endif |
||
286 | #if WITH_IP4 && WITH_UDP |
||
287 | { "udp4", xioaddrs_udp4_connect }, |
||
288 | { "udp4-connect", xioaddrs_udp4_connect }, |
||
289 | { "udp4-datagram", xioaddrs_udp4_datagram }, |
||
290 | { "udp4-dgram", xioaddrs_udp4_datagram }, |
||
291 | #endif |
||
292 | #if WITH_IP4 && WITH_UDP && WITH_LISTEN |
||
293 | { "udp4-l", xioaddrs_udp4_listen }, |
||
294 | { "udp4-listen", xioaddrs_udp4_listen }, |
||
295 | #endif |
||
296 | #if WITH_IP4 && WITH_UDP |
||
297 | { "udp4-recv", xioaddrs_udp4_recv }, |
||
298 | { "udp4-recvfrom", xioaddrs_udp4_recvfrom }, |
||
299 | { "udp4-send", xioaddrs_udp4_sendto }, |
||
300 | { "udp4-sendto", xioaddrs_udp4_sendto }, |
||
301 | #endif |
||
302 | #if WITH_IP6 && WITH_UDP |
||
303 | { "udp6", xioaddrs_udp6_connect }, |
||
304 | { "udp6-connect", xioaddrs_udp6_connect }, |
||
305 | { "udp6-datagram", xioaddrs_udp6_datagram }, |
||
306 | { "udp6-dgram", xioaddrs_udp6_datagram }, |
||
307 | #endif |
||
308 | #if WITH_IP6 && WITH_UDP && WITH_LISTEN |
||
309 | { "udp6-l", xioaddrs_udp6_listen }, |
||
310 | { "udp6-listen", xioaddrs_udp6_listen }, |
||
311 | #endif |
||
312 | #if WITH_IP6 && WITH_UDP |
||
313 | { "udp6-recv", xioaddrs_udp6_recv }, |
||
314 | { "udp6-recvfrom", xioaddrs_udp6_recvfrom }, |
||
315 | { "udp6-send", xioaddrs_udp6_sendto }, |
||
316 | { "udp6-sendto", xioaddrs_udp6_sendto }, |
||
317 | #endif |
||
318 | #if WITH_UNIX |
||
319 | { "unix", xioaddrs_unix_client }, |
||
320 | { "unix-client", xioaddrs_unix_client }, |
||
321 | { "unix-connect", xioaddrs_unix_connect }, |
||
322 | #endif |
||
323 | #if WITH_UNIX && WITH_LISTEN |
||
324 | { "unix-l", xioaddrs_unix_listen }, |
||
325 | { "unix-listen", xioaddrs_unix_listen }, |
||
326 | #endif |
||
327 | #if WITH_UNIX |
||
328 | { "unix-recv", xioaddrs_unix_recv }, |
||
329 | { "unix-recvfrom", xioaddrs_unix_recvfrom }, |
||
330 | { "unix-send", xioaddrs_unix_sendto }, |
||
331 | { "unix-sendto", xioaddrs_unix_sendto }, |
||
332 | #endif |
||
333 | #else /* !0 */ |
||
334 | # if WITH_INTEGRATE |
||
335 | # include "xiointegrate.c" |
||
336 | # else |
||
337 | # include "xioaddrtab.c" |
||
338 | # endif |
||
339 | #endif /* !0 */ |
||
340 | { NULL } /* end marker */ |
||
341 | } ; |
||
342 | |||
343 | |||
344 | /* prepares a xiofile_t record for dual address type: |
||
345 | sets the tag and allocates memory for the substreams. |
||
346 | returns 0 on success, or <0 if an error occurred. |
||
347 | */ |
||
348 | int xioopen_makedual(xiofile_t *file) { |
||
349 | file->tag = XIO_TAG_DUAL; |
||
350 | file->common.flags = XIO_RDWR; |
||
351 | if ((file->dual.stream[0] = (xiosingle_t *)xioallocfd()) == NULL) |
||
352 | return -1; |
||
353 | file->dual.stream[0]->flags = XIO_RDONLY; |
||
354 | if ((file->dual.stream[1] = (xiosingle_t *)xioallocfd()) == NULL) |
||
355 | return -1; |
||
356 | file->dual.stream[1]->flags = XIO_WRONLY; |
||
357 | return 0; |
||
358 | } |
||
359 | |||
360 | /* returns NULL if an error occurred */ |
||
361 | xiofile_t *xioallocfd(void) { |
||
362 | xiofile_t *fd; |
||
363 | |||
364 | if ((fd = Calloc(1, sizeof(xiofile_t))) == NULL) { |
||
365 | return NULL; |
||
366 | } |
||
367 | /* some default values; 0's and NULL's need not be applied (calloc'ed) */ |
||
368 | fd->common.tag = XIO_TAG_INVALID; |
||
369 | /* fd->common.addr = NULL; */ |
||
370 | fd->common.flags = XIO_RDWR; |
||
371 | |||
372 | #if WITH_RETRY |
||
373 | /* fd->stream.retry = 0; */ |
||
374 | /* fd->stream.forever = false; */ |
||
375 | fd->stream.intervall.tv_sec = 1; |
||
376 | /* fd->stream.intervall.tv_nsec = 0; */ |
||
377 | #endif /* WITH_RETRY */ |
||
378 | /* fd->common.ignoreeof = false; */ |
||
379 | /* fd->common.eof = 0; */ |
||
380 | |||
381 | fd->stream.rfd = -1; |
||
382 | fd->stream.wfd = -1; |
||
383 | fd->stream.dtype = XIODATA_STREAM; |
||
384 | #if _WITH_SOCKET |
||
385 | /* fd->stream.salen = 0; */ |
||
386 | #endif /* _WITH_SOCKET */ |
||
387 | /* fd->stream.howtoshut = XIOSHUT_UNSPEC;*/ |
||
388 | /* fd->stream.howtoclose = XIOCLOSE_UNSPEC;*/ |
||
389 | /* fd->stream.name = NULL; */ |
||
390 | fd->stream.escape = -1; |
||
391 | /* fd->stream.para.exec.pid = 0; */ |
||
392 | fd->stream.lineterm = LINETERM_RAW; |
||
393 | |||
394 | /*!! support n socks */ |
||
395 | if (!sock[0]) { |
||
396 | sock[0] = fd; |
||
397 | } else { |
||
398 | sock[1] = fd; |
||
399 | } |
||
400 | return fd; |
||
401 | } |
||
402 | |||
403 | void xiofreefd(xiofile_t *xfd) { |
||
404 | if (xfd->stream.opts != NULL) { |
||
405 | dropopts(xfd->stream.opts, PH_ALL); |
||
406 | } |
||
407 | free(xfd); |
||
408 | } |
||
409 | |||
410 | |||
411 | /* handle one chain of addresses |
||
412 | rw is one of XIO_RDWR, XIO_RDONLY, or XIO_WRONLY |
||
413 | when finished with this and the following sub addresses we return an xfd |
||
414 | that can be used by the _socat() loop |
||
415 | */ |
||
416 | xiofile_t *socat_open(const char *addrs0, int rw, int flags) { |
||
417 | const char *addrs; |
||
418 | xiosingle_t *sfdA; /* what we just parse(d) */ |
||
419 | xiosingle_t *sfdB; /* what we just parse(d) - second part of dual */ |
||
420 | int newpipesep = 1; /* dual address: 1%0 instead of 0!!1 */ |
||
421 | int reverseA, reverseB=0; |
||
422 | bool currentisendpoint = false; |
||
423 | int mayleftA, mayrightA, mayleftB, mayrightB; |
||
424 | int isleftA, isrightA, isleftB, isrightB; |
||
425 | int srchleftA, srchrightA, srchleftB=0, srchrightB=0; |
||
426 | xiofile_t *xfd0; /* what we return */ |
||
427 | xiofile_t *xfd1; /* left hand of engine */ |
||
428 | xiofile_t *xfd2; /* returned by sub address */ |
||
429 | int rw0, rw1, rw2; /* the data directions for respective xfd |
||
430 | directions are sepcified as seen by transfer |
||
431 | engine */ |
||
432 | xiofd_t left, right; |
||
433 | struct threadarg_struct *thread_arg; |
||
434 | /*0 pthread_t thread = 0;*/ |
||
435 | /*pthread_attr_t attr;*/ |
||
436 | int _errno = 0; |
||
437 | |||
438 | Info3("opening address \"%s\", rw=%d, flags=0x%x", addrs0, rw, flags); |
||
439 | |||
440 | /* loop over retries, contains nearly the complete function */ |
||
441 | while (true) { |
||
442 | |||
443 | addrs = addrs0; |
||
444 | skipsp(&addrs); |
||
445 | rw0 = rw; |
||
446 | |||
447 | /* here we do not know much: will the next sub address be inter or |
||
448 | endpoint, single or dual, reverse? */ |
||
449 | |||
450 | /* check the logical direction of the current subaddress */ |
||
451 | reverseA = !(strncmp(addrs, xioparams->reversechar, |
||
452 | strlen(xioparams->reversechar))); |
||
453 | if (reverseA) { |
||
454 | addrs += strlen(xioparams->reversechar); /* consume "reverse" */ |
||
455 | skipsp(&addrs); |
||
456 | } |
||
457 | |||
458 | if ((sfdA = xioparse_single(&addrs)) == NULL) { |
||
459 | Error1("syntax error in \"%s\"", addrs); |
||
460 | return NULL; |
||
461 | } |
||
462 | skipsp(&addrs); |
||
463 | |||
464 | /* is it a dual sub address? */ |
||
465 | if (!strncmp(addrs, xioparams->pipesep, strlen(xioparams->pipesep))) { |
||
466 | /* yes, found dual-address operator */ |
||
467 | if (rw != XIO_RDWR) { |
||
468 | Error("dual address cannot handle single direction data stream"); |
||
469 | } |
||
470 | skipsp(&addrs); |
||
471 | addrs += strlen(xioparams->pipesep); /* consume "%" */ |
||
472 | /* check the logical direction of the current subaddress */ |
||
473 | skipsp(&addrs); |
||
474 | reverseB = !(strncmp(addrs, xioparams->reversechar, |
||
475 | strlen(xioparams->reversechar))); |
||
476 | if (reverseB) { |
||
477 | addrs += strlen(xioparams->reversechar); /* consume "reverse" */ |
||
478 | skipsp(&addrs); |
||
479 | } |
||
480 | |||
481 | if ((sfdB = xioparse_single(&addrs)) == NULL) { |
||
482 | Error1("syntax error in \"%s\"", addrs); |
||
483 | return NULL; |
||
484 | } |
||
485 | skipsp(&addrs); |
||
486 | } else { |
||
487 | sfdB = NULL; |
||
488 | } |
||
489 | |||
490 | /* is it the final sub address? */ |
||
491 | if (*addrs == '\0') { |
||
492 | currentisendpoint = true; |
||
493 | } else if (!strncmp(addrs, xioparams->chainsep, |
||
494 | strlen(xioparams->chainsep))) { |
||
495 | addrs += strlen(xioparams->chainsep); |
||
496 | skipsp(&addrs); |
||
497 | currentisendpoint = false; |
||
498 | } else { |
||
499 | Error2("syntax error on \"%s\": expected eol or \"%s\"", |
||
500 | addrs, xioparams->chainsep); |
||
501 | xiofreefd((xiofile_t *)sfdA); |
||
502 | if (sfdB != NULL) xiofreefd((xiofile_t *)sfdB); |
||
503 | return NULL; |
||
504 | } |
||
505 | |||
506 | /* now we know the context of the current sub address: |
||
507 | currentisendpoint...it is an endpoint, not an inter address |
||
508 | sfdB.......if not null, we have a dual type address |
||
509 | reverseA...sfdA is reverse |
||
510 | reverseB...if dual address then sfdB is reverse |
||
511 | rw0......the data direction of xfd0 */ |
||
512 | /* note: with dual inter, sfdB is implicitely reverse */ |
||
513 | |||
514 | /* calculate context parameters that are easier to handle */ |
||
515 | if (sfdB == NULL) { |
||
516 | srchleftA = mayleftA = (1 << rw0); |
||
517 | srchrightA = mayrightA = (currentisendpoint ? 0 : XIOBIT_ALL); |
||
518 | if (reverseA) { |
||
519 | srchrightA = srchleftA; |
||
520 | /*srchrightA = XIOBIT_REVERSE(srchleftA); no, see what right means*/ |
||
521 | srchleftA = XIOBIT_ALL; |
||
522 | } |
||
523 | } else { /* A is only part of dual */ |
||
524 | srchleftA = mayleftA = XIOBIT_WRONLY; |
||
525 | srchrightA = mayrightA = (currentisendpoint ? 0 : XIOBIT_RDONLY); |
||
526 | if (reverseA) { |
||
527 | srchleftA = XIOBIT_RDONLY; |
||
528 | srchrightA = XIOBIT_WRONLY; |
||
529 | } |
||
530 | srchleftB = mayleftB = (currentisendpoint ? XIOBIT_RDONLY : XIOBIT_WRONLY); |
||
531 | srchrightB = mayrightB = (currentisendpoint ? 0 : XIOBIT_RDONLY); |
||
532 | if (reverseB) { |
||
533 | srchleftB = XIOBIT_RDONLY; |
||
534 | srchrightB = XIOBIT_WRONLY; |
||
535 | } |
||
536 | } |
||
537 | |||
538 | if ((true /*0 || ((rw0+1) & (XIO_WRONLY+1))*/) || currentisendpoint) { |
||
539 | if (xioopen_unoverload(sfdA, srchleftA, &isleftA, srchrightA, &isrightA) |
||
540 | < 0) { |
||
541 | Error1("address \"%s\" can not be used in this context", |
||
542 | sfdA->addrdescs[0]->inter_desc.defname); |
||
543 | } |
||
544 | } else { |
||
545 | if (xioopen_unoverload(sfdA, srchrightA, &isrightA, srchleftA, &isleftA) |
||
546 | < 0) { |
||
547 | Error1("address \"%s\" can not be used in this context", |
||
548 | sfdA->addrdescs[0]->inter_desc.defname); |
||
549 | } |
||
550 | } |
||
551 | if (reverseA) { |
||
552 | int tmp; |
||
553 | tmp = isleftA; isrightA = isleftA; isleftA = tmp; |
||
554 | } |
||
555 | |||
556 | if (sfdB != NULL) { |
||
557 | if (xioopen_unoverload(sfdB, srchleftB, &isleftB, srchrightB, &isrightB) |
||
558 | < 0) { |
||
559 | Error1("address \"%s\" can not be used in this context", |
||
560 | sfdB->addrdescs[0]->inter_desc.defname); |
||
561 | } |
||
562 | if (reverseB) { isleftB = XIOBIT_REVERSE(srchrightB); } |
||
563 | if (!currentisendpoint && ((isrightA+1) & (isleftB+1))) { |
||
564 | /* conflict in directions on right side (xfd1) */ |
||
565 | Error("conflict in data directions");/*!!*/ |
||
566 | } |
||
567 | rw1 = ((isrightA+1) | (isleftB+1)) - 1; |
||
568 | } else { |
||
569 | rw1 = isrightA; |
||
570 | } |
||
571 | rw2 = (rw1==XIO_RDWR) ? XIO_RDWR : (rw1==XIO_RDONLY) ? XIO_WRONLY : |
||
572 | XIO_RDONLY; |
||
573 | |||
574 | /* now we know exactly what to do with the current sub address */ |
||
575 | |||
576 | /* we need the values for retry, forever, and intervall */ |
||
577 | applyopts_offset(sfdA, sfdA->opts); |
||
578 | if (sfdB != NULL) { |
||
579 | applyopts_offset(sfdB, sfdB->opts); |
||
580 | } |
||
581 | |||
582 | /* if we found the endpoint address we are almost finished here */ |
||
583 | |||
584 | if (currentisendpoint) { |
||
585 | if (sfdB != NULL) { |
||
586 | if ((xfd0 = xioallocfd()) == NULL) { |
||
587 | xiofreefd((xiofile_t *)sfdA); xiofreefd((xiofile_t *)sfdB); |
||
588 | return NULL; |
||
589 | } |
||
590 | xioopen_makedual(xfd0); |
||
591 | xfd0->dual.stream[0] = sfdB; |
||
592 | xfd0->dual.stream[1] = sfdA; |
||
593 | } else { |
||
594 | xfd0 = (xiofile_t *)sfdA; |
||
595 | } |
||
596 | /* open it and be ready in this thread */ |
||
597 | if (xioopen_endpoint_dual(xfd0, rw0|flags) < 0) { |
||
598 | xiofreefd(xfd0); |
||
599 | return NULL; |
||
600 | } |
||
601 | return xfd0; |
||
602 | } |
||
603 | |||
604 | /* the current addr is not the final sub address */ |
||
605 | |||
606 | /* recursively open the following addresses of chain */ |
||
607 | /* loop over retries if appropriate */ |
||
608 | do { |
||
609 | xfd2 = socat_open(addrs, rw2, flags); |
||
610 | if (xfd2 != NULL) { |
||
611 | break; /* succeeded */ |
||
612 | } |
||
613 | if (sfdA->retry == 0 && !sfdA->forever) { |
||
614 | xiofreefd((xiofile_t *)sfdA); |
||
615 | if (sfdB != NULL) xiofreefd((xiofile_t *)sfdB); |
||
616 | /*! close()? */ |
||
617 | return NULL; |
||
618 | } |
||
619 | Nanosleep(&sfdA->intervall, NULL); |
||
620 | if (sfdA->retry) --sfdA->retry; |
||
621 | } while (true); |
||
622 | |||
623 | /* only xfd2 is valid here, contains a handle for the rest of the chain |
||
624 | */ |
||
625 | /* yupp, and the single addresses sfdA and ev.sfdB are valid too, but |
||
626 | not yet opened */ |
||
627 | |||
628 | /* what are xfd0, xfd1, and xfd2? |
||
629 | consider chain: addr1|addr2 |
||
630 | with no reverse address, this will run like: |
||
631 | _socat(<upstream>,addr1) --- _socat(-, addr2) |
||
632 | _socat(???, xfd0) --- _socat(xfd1,xfd2) |
||
633 | xfd0 will be opened in this routine |
||
634 | xfd1 will be assembled now, just using FDs |
||
635 | xfd2 comes from recursive open call |
||
636 | */ |
||
637 | /* but, with reverse, it looks so: |
||
638 | consider chain: ^addr1|addr2 |
||
639 | _socat(<upstream>,-) --- _socat(addr1,addr2) |
||
640 | _socat(??? ,xfd0) --- _socat(xfd1, xfd2) |
||
641 | xfd0 will be assembled now, just using FDs |
||
642 | xfd1 was just initialized in this routine |
||
643 | xfd2 comes from recursive open call |
||
644 | */ |
||
645 | /* even worse, with mixed forward/reverse dual address: |
||
646 | consider chain: addr1a%^addr1b|addr2 |
||
647 | _socat(<upstream, addr1a%nop) --- _socat(nop%addr1b, addr2) |
||
648 | _socat(???, xfd0) --- _socat(xfd1, xfd2) |
||
649 | */ |
||
650 | |||
651 | /* prepare FD based communication of current addr with its right neighbor |
||
652 | (xfd0-xfd1) */ |
||
653 | { |
||
654 | switch (xioopts.pipetype) { |
||
655 | case XIOCOMM_SOCKETPAIR: |
||
656 | case XIOCOMM_SOCKETPAIRS: |
||
657 | if (xiocommpair(xioopts.pipetype, |
||
658 | (rw2+1)&(XIO_WRONLY+1), (rw1+1)&(XIO_WRONLY+1), |
||
659 | sfdB!=0, &left, &right, |
||
660 | PF_UNIX, SOCK_STREAM, 0) != 0) { |
||
661 | return NULL; |
||
662 | } |
||
663 | break; |
||
664 | case XIOCOMM_PTY: |
||
665 | case XIOCOMM_PTYS: |
||
666 | if (xiocommpair(xioopts.pipetype, |
||
667 | (rw2+1)&(XIO_WRONLY+1), (rw1+1)&(XIO_WRONLY+1), |
||
668 | sfdB!=0, &left, &right, |
||
669 | 1 /* useptmx */) != 0) { |
||
670 | return NULL; |
||
671 | } |
||
672 | break; |
||
673 | default: |
||
674 | if (xiocommpair(xioopts.pipetype, |
||
675 | (rw2+1)&(XIO_WRONLY+1), (rw1+1)&(XIO_WRONLY+1), |
||
676 | sfdB!=0, &left, &right) != 0) { |
||
677 | return NULL; |
||
678 | } |
||
679 | break; |
||
680 | } |
||
681 | } |
||
682 | |||
683 | /* now assemble xfd0 and xfd1 */ |
||
684 | |||
685 | if (sfdB != NULL && reverseA == reverseB) { |
||
686 | /* dual address, differing orientation (B is impl.reverse) */ |
||
687 | /* dual implies (rw0==rw1==XIO_RDWR) */ |
||
688 | if (!reverseA) { |
||
689 | /* A is not reverse, but B */ |
||
690 | # define MAXADDR 45 |
||
691 | char addr[MAXADDR]; |
||
692 | |||
693 | xfd0 = xioallocfd(); |
||
694 | xioopen_makedual(xfd0); |
||
695 | xfd0->dual.stream[1] = sfdA; |
||
696 | snprintf(addr, MAXADDR, "FD:%u", /*0 righttoleft[0]*/left.rfd); |
||
697 | if ((xfd0->dual.stream[0] = |
||
698 | (xiosingle_t *)socat_open(addr, XIO_WRONLY, 0)) |
||
699 | == NULL) { |
||
700 | xiofreefd(xfd0); xiofreefd(xfd2); return NULL; |
||
701 | } |
||
702 | /* address type FD keeps the FDs open per default, but ... */ |
||
703 | |||
704 | xfd1 = xioallocfd(); |
||
705 | xioopen_makedual(xfd1); |
||
706 | xfd1->dual.stream[1] = sfdB; |
||
707 | snprintf(addr, MAXADDR, "FD:%u", /*0 lefttoright[0]*/right.rfd); |
||
708 | if ((xfd1->dual.stream[0] = |
||
709 | (xiosingle_t *)socat_open(addr, XIO_RDONLY, 0)) |
||
710 | == NULL) { |
||
711 | xiofreefd(xfd0); xiofreefd(xfd1); xiofreefd(xfd2); |
||
712 | return NULL; |
||
713 | } |
||
714 | } else { |
||
715 | /* A is reverse, but B is not */ |
||
716 | char addr[MAXADDR]; |
||
717 | |||
718 | xfd0 = xioallocfd(); |
||
719 | xioopen_makedual(xfd0); |
||
720 | xfd0->dual.stream[0] = sfdB; |
||
721 | snprintf(addr, MAXADDR, "FD:%u", /*0 lefttoright[1]*/left.wfd); |
||
722 | if ((xfd0->dual.stream[1] = |
||
723 | (xiosingle_t *)socat_open(addr, XIO_RDONLY, 0)) |
||
724 | == NULL) { |
||
725 | xiofreefd(xfd0); xiofreefd(xfd2); return NULL; |
||
726 | } |
||
727 | |||
728 | xfd1 = xioallocfd(); |
||
729 | xioopen_makedual(xfd1); |
||
730 | xfd1->dual.stream[0] = sfdA; |
||
731 | snprintf(addr, MAXADDR, "FD:%u", /*0 righttoleft[1]*/right.wfd); |
||
732 | if ((xfd1->dual.stream[1] = |
||
733 | (xiosingle_t *)socat_open(addr, XIO_RDONLY, 0)) |
||
734 | == NULL) { |
||
735 | xiofreefd(xfd0); xiofreefd(xfd1); xiofreefd(xfd2); |
||
736 | return NULL; |
||
737 | } |
||
738 | } |
||
739 | xfd0->dual.stream[0]->rfd = left.rfd; |
||
740 | xfd0->dual.stream[1]->wfd = left.wfd; |
||
741 | xfd1->dual.stream[0]->rfd = right.rfd; |
||
742 | xfd1->dual.stream[1]->wfd = right.wfd; |
||
743 | |||
744 | } else { |
||
745 | /* either dual with equal directions, or non-dual */ |
||
746 | xiofile_t *tfd; /* temp xfd */ |
||
747 | char addr[MAXADDR]; |
||
748 | if (sfdB != NULL) { |
||
749 | /* dual, none or both are reverse */ |
||
750 | tfd = xioallocfd(); |
||
751 | xioopen_makedual(tfd); |
||
752 | tfd->dual.stream[1] = sfdA; |
||
753 | tfd->dual.stream[0] = sfdB; |
||
754 | } else { |
||
755 | /* non-dual */ |
||
756 | tfd = (xiofile_t *)sfdA; |
||
757 | } |
||
758 | |||
759 | /* now take care of orientation */ |
||
760 | if (!reverseA) { |
||
761 | /* forward */ |
||
762 | xfd0 = tfd; |
||
763 | if (rw1 == XIO_RDWR) { |
||
764 | snprintf(addr, MAXADDR, "FD:%u:%u", /*0 righttoleft[1]*/right.wfd, /*0 lefttoright[0]*/right.rfd); |
||
765 | } else if (rw1 == XIO_RDONLY) { |
||
766 | snprintf(addr, MAXADDR, "FD:%u", /*0 lefttoright[0]*/right.rfd); |
||
767 | } else { |
||
768 | snprintf(addr, MAXADDR, "FD:%u", /*0 righttoleft[1]*/right.wfd); |
||
769 | } |
||
770 | if ((xfd1 = socat_open(addr, rw1, 0)) == NULL) { |
||
771 | xiofreefd(xfd0); xiofreefd(xfd2); |
||
772 | return NULL; |
||
773 | } |
||
774 | } else { |
||
775 | /* reverse */ |
||
776 | xfd1 = tfd; |
||
777 | if (rw0 == XIO_RDWR) { |
||
778 | snprintf(addr, MAXADDR, "FD:%u:%u", /*0 lefttoright[1]*/left.wfd, /*0 righttoleft[0]*/left.rfd); |
||
779 | } else if (rw0 == XIO_RDONLY) { |
||
780 | snprintf(addr, MAXADDR, "FD:%u", /*0 righttoleft[0]*/left.rfd); |
||
781 | } else { |
||
782 | snprintf(addr, MAXADDR, "FD:%u", /*0 lefttoright[1]*/left.wfd); |
||
783 | } |
||
784 | if ((xfd0 = socat_open(addr, rw0/*0 XIO_RDWR*/, 0)) == NULL) { |
||
785 | xiofreefd(xfd1); xiofreefd(xfd2); |
||
786 | return NULL; |
||
787 | } |
||
788 | /* address type FD keeps the FDs open per default, but ... */ |
||
789 | } |
||
790 | if (xfd0->tag == XIO_TAG_DUAL) { |
||
791 | xfd0->dual.stream[0]->rfd = /*0 righttoleft[0]*/left.rfd; |
||
792 | xfd0->dual.stream[1]->wfd = /*0 lefttoright[1]*/left.wfd; |
||
793 | } else { |
||
794 | xfd0->stream.rfd = /*0 righttoleft[0]*/left.rfd; |
||
795 | xfd0->stream.wfd = /*0 lefttoright[1]*/left.wfd; |
||
796 | } |
||
797 | if (xfd1->tag == XIO_TAG_DUAL) { |
||
798 | xfd1->dual.stream[0]->rfd = /*0 righttoleft[0]*/left.rfd; |
||
799 | xfd1->dual.stream[1]->rfd = /*0 lefttoright[1]*/left.wfd; |
||
800 | } else { |
||
801 | xfd1->stream.rfd = /*0 lefttoright[0]*/right.rfd; |
||
802 | xfd1->stream.wfd = /*0 righttoleft[1]*/right.wfd; |
||
803 | } |
||
804 | } |
||
805 | |||
806 | /* address type FD keeps the FDs open per default, but ... */ |
||
807 | if (xfd0->tag == XIO_TAG_DUAL) { |
||
808 | xfd0->dual.stream[0]->howtoshut = left.howtoshut; |
||
809 | xfd0->dual.stream[0]->howtoclose = left.howtoclose; |
||
810 | xfd0->dual.stream[0]->dtype = left.dtype; |
||
811 | xfd0->dual.stream[1]->howtoshut = right.howtoshut; |
||
812 | xfd0->dual.stream[1]->howtoclose = right.howtoclose; |
||
813 | xfd0->dual.stream[1]->dtype = right.dtype; |
||
814 | } else { |
||
815 | xfd0->stream.howtoshut = left.howtoshut; |
||
816 | xfd0->stream.howtoclose = left.howtoclose; |
||
817 | xfd0->stream.dtype = left.dtype; |
||
818 | } |
||
819 | if (xfd1->tag == XIO_TAG_DUAL) { |
||
820 | xfd1->dual.stream[0]->howtoshut = left.howtoshut; |
||
821 | xfd1->dual.stream[0]->howtoclose = left.howtoclose; |
||
822 | xfd1->dual.stream[0]->dtype = left.dtype; |
||
823 | xfd1->dual.stream[1]->howtoshut = right.howtoshut; |
||
824 | xfd1->dual.stream[1]->howtoclose = right.howtoclose; |
||
825 | xfd1->dual.stream[1]->dtype = right.dtype; |
||
826 | } else { |
||
827 | xfd1->stream.howtoshut = right.howtoshut; |
||
828 | xfd1->stream.howtoclose = right.howtoclose; |
||
829 | xfd1->stream.dtype = right.dtype; |
||
830 | } |
||
831 | |||
832 | /* here xfd2 is valid and ready for transfer; |
||
833 | and xfd0 and xfd1 are valid and ready for opening */ |
||
834 | |||
835 | /* create a new thread that do the xioopen() of xfd1 and xfd2, and then |
||
836 | drive the transfer engine between them */ |
||
837 | if ((thread_arg = Malloc(sizeof(struct threadarg_struct))) == NULL) { |
||
838 | /*! free something */ |
||
839 | xiofreefd(xfd0); xiofreefd(xfd1); xiofreefd(xfd2); |
||
840 | return NULL; |
||
841 | } |
||
842 | thread_arg->rw = (reverseA ? rw1 : rw0); |
||
843 | thread_arg->xfd1 = xfd1; |
||
844 | thread_arg->xfd2 = xfd2; |
||
845 | Notice5("starting thread: dir=%d, reverseA=%d, reverseB=%d, xfd1->tag=%d, xfd2->tag=%d", |
||
846 | rw0, reverseA, reverseB, xfd1->tag, xfd2->tag); |
||
847 | if (xfd1->tag==XIO_TAG_DUAL) { |
||
848 | Notice4("xfd1: [%s, wfd=%d] %% [%s, rfd=%d]", |
||
849 | xfd1->dual.stream[1]->addrdesc->common_desc.defname, |
||
850 | xfd1->dual.stream[1]->wfd, |
||
851 | xfd1->dual.stream[0]->addrdesc->common_desc.defname, |
||
852 | xfd1->dual.stream[0]->rfd); |
||
853 | } else { |
||
854 | Notice3("xfd1: %s, wfd=%d, rfd=%d", |
||
855 | xfd1->stream.addrdesc->common_desc.defname, |
||
856 | xfd1->stream.wfd, xfd1->stream.rfd); |
||
857 | } |
||
858 | if (xfd2->tag==XIO_TAG_DUAL) { |
||
859 | Notice4("xfd2: [%s, wfd=%d] %% [%s, rfd=%d]", |
||
860 | xfd2->dual.stream[1]->addrdesc->common_desc.defname, |
||
861 | xfd2->dual.stream[1]->wfd, |
||
862 | xfd2->dual.stream[0]->addrdesc->common_desc.defname, |
||
863 | xfd2->dual.stream[0]->rfd); |
||
864 | } else { |
||
865 | Notice3("xfd2: %s, wfd=%d, rfd=%d", |
||
866 | xfd2->stream.addrdesc->common_desc.defname, |
||
867 | xfd2->stream.wfd, xfd2->stream.rfd); |
||
868 | } |
||
869 | Info5("pthread_create(%p, NULL, %s, {%d,%p,%p})", |
||
870 | &xfd0->stream.subthread, |
||
871 | (reverseA||(sfdB!=NULL)&&!reverseB)?"xioopenleftthenengine":"xioengine", |
||
872 | thread_arg->rw, thread_arg->xfd1, thread_arg->xfd2); |
||
873 | if ((_errno = |
||
874 | Pthread_create(&xfd0->stream.subthread, NULL, |
||
875 | (reverseA||(sfdB!=NULL)&&!reverseB)?xioopenleftthenengine:xioengine, |
||
876 | thread_arg)) |
||
877 | != 0) { |
||
878 | Error3("pthread_create(%p, {}, xioengine, %p): %s", |
||
879 | &xfd0->stream.subthread, thread_arg, |
||
880 | strerror(_errno)); |
||
881 | xiofreefd(xfd0); xiofreefd(xfd1); xiofreefd(xfd2); |
||
882 | free(thread_arg); return NULL; |
||
883 | } |
||
884 | Info1("started thread "F_thread, xfd0->stream.subthread); |
||
885 | xfd1 = NULL; |
||
886 | xfd2 = NULL; |
||
887 | |||
888 | /* open protocol part */ |
||
889 | if (xioopen_inter_dual(xfd0, rw|flags) |
||
890 | < 0) { |
||
891 | /*! close sub chain */ |
||
892 | if (xfd0->stream.retry == 0 && !xfd0->stream.forever) { |
||
893 | xiofreefd(xfd0); /*! close()? */ return NULL; |
||
894 | } |
||
895 | Nanosleep(&xfd0->stream.intervall, NULL); |
||
896 | if (xfd0->stream.retry) --xfd0->stream.retry; |
||
897 | continue; |
||
898 | } |
||
899 | break; |
||
900 | } |
||
901 | /*!!!?*/ |
||
902 | #if 0 |
||
903 | xfd0->stream.howtoshut = XIOSHUT_CLOSE; |
||
904 | #endif |
||
905 | return xfd0; |
||
906 | } |
||
907 | |||
908 | void *xioopenleftthenengine(void *thread_void) { |
||
909 | struct threadarg_struct *thread_arg = thread_void; |
||
910 | int rw = thread_arg->rw; |
||
911 | xiofile_t *xfd1 = thread_arg->xfd1; |
||
912 | xiofile_t *xfd2 = thread_arg->xfd2; |
||
913 | |||
914 | /*! design a function with better interface */ |
||
915 | if (xioopen_inter_dual(xfd1, rw|XIO_MAYCONVERT|XIO_MAYCHILD) < 0) { |
||
916 | xioclose(xfd2); |
||
917 | xiofreefd(xfd1); |
||
918 | xiofreefd(xfd2); |
||
919 | return NULL; |
||
920 | } |
||
921 | xioengine(thread_void); |
||
922 | return NULL; |
||
923 | } |
||
924 | |||
925 | |||
926 | xiofile_t *xioparse_dual(const char **addr) { |
||
927 | xiofile_t *xfd; |
||
928 | xiosingle_t *sfd1; |
||
929 | int reverse; |
||
930 | |||
931 | /* check the logical direction of the current subaddress */ |
||
932 | reverse = !(strncmp(*addr, xioparams->reversechar, |
||
933 | strlen(xioparams->reversechar))); |
||
934 | if (reverse) { |
||
935 | /* skip "reverse" token */ |
||
936 | *addr += strlen(xioparams->reversechar); |
||
937 | } |
||
938 | |||
939 | /* we parse a single address */ |
||
940 | if ((sfd1 = xioparse_single(addr)) == NULL) { |
||
941 | return NULL; |
||
942 | } |
||
943 | sfd1->reverse = reverse; |
||
944 | |||
945 | /* and now we see if we reached a dual-address separator */ |
||
946 | if (strncmp(*addr, xioopts.pipesep, strlen(xioopts.pipesep))) { |
||
947 | /* no, finish */ |
||
948 | return (xiofile_t *)sfd1; |
||
949 | } |
||
950 | |||
951 | /* we found the dual-address operator, so we parse the second single address |
||
952 | */ |
||
953 | *addr += strlen(xioparams->pipesep); |
||
954 | |||
955 | if ((xfd = xioallocfd()) == NULL) { |
||
956 | xiofreefd((xiofile_t *)sfd1); |
||
957 | return NULL; |
||
958 | } |
||
959 | xfd->tag = XIO_TAG_DUAL; |
||
960 | xfd->dual.stream[0] = sfd1; |
||
961 | if ((xfd->dual.stream[1] = xioparse_single(addr)) == NULL) { |
||
962 | xiofreefd(xfd); /*! and maybe have free some if its contents */ |
||
963 | return NULL; |
||
964 | } |
||
965 | |||
966 | return xfd; |
||
967 | } |
||
968 | |||
969 | int xioopen_inter_dual(xiofile_t *xfd, int xioflags) { |
||
970 | |||
971 | if (xfd->tag == XIO_TAG_DUAL) { |
||
972 | /* a really dual address */ |
||
973 | if ((xioflags&XIO_ACCMODE) != XIO_RDWR) { |
||
974 | Warn("unidirectional open of dual address"); |
||
975 | } |
||
976 | |||
977 | /* a "usual" bidirectional stream specification, one address */ |
||
978 | if (((xioflags&XIO_ACCMODE)+1) & (XIO_RDONLY+1)) { |
||
979 | if (xioopen_inter_single((xiofile_t *)xfd->dual.stream[0], XIO_RDONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC)) |
||
980 | < 0) { |
||
981 | return -1; |
||
982 | } |
||
983 | } |
||
984 | /*! should come before xioopensingle? */ |
||
985 | if (((xioflags&XIO_ACCMODE)+1) & (XIO_WRONLY+1)) { |
||
986 | if (xioopen_inter_single((xiofile_t *)xfd->dual.stream[1], XIO_WRONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC)) |
||
987 | < 0) { |
||
988 | xioclose((xiofile_t *)xfd->dual.stream[0]); |
||
989 | return -1; |
||
990 | } |
||
991 | } |
||
992 | return 0; |
||
993 | } |
||
994 | |||
995 | return xioopen_inter_single(xfd, xioflags); |
||
996 | } |
||
997 | |||
998 | int xioopen_endpoint_dual(xiofile_t *xfd, int xioflags) { |
||
999 | |||
1000 | if (xfd->tag == XIO_TAG_DUAL) { |
||
1001 | /* a really dual address */ |
||
1002 | if ((xioflags&XIO_ACCMODE) != XIO_RDWR) { |
||
1003 | Warn("unidirectional open of dual address"); |
||
1004 | } |
||
1005 | |||
1006 | /* a "usual" bidirectional stream specification, one address */ |
||
1007 | if (((xioflags&XIO_ACCMODE)+1) & (XIO_WRONLY+1)) { |
||
1008 | if (xioopen_endpoint_single((xiofile_t *)xfd->dual.stream[1], XIO_WRONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC)) |
||
1009 | < 0) { |
||
1010 | return -1; |
||
1011 | } |
||
1012 | } |
||
1013 | /*! should come before xioopensingle? */ |
||
1014 | if (((xioflags&XIO_ACCMODE)+1) & (XIO_RDONLY+1)) { |
||
1015 | if (xioopen_endpoint_single((xiofile_t *)xfd->dual.stream[0], XIO_RDONLY|(xioflags&~XIO_ACCMODE&~XIO_MAYEXEC)) |
||
1016 | < 0) { |
||
1017 | xioclose((xiofile_t *)xfd->dual.stream[1]); |
||
1018 | return -1; |
||
1019 | } |
||
1020 | } |
||
1021 | return 0; |
||
1022 | } |
||
1023 | |||
1024 | return xioopen_endpoint_single(xfd, xioflags); |
||
1025 | } |
||
1026 | |||
1027 | |||
1028 | /* parses the parameters and options of a single (sub)address. |
||
1029 | returns 0 on success or -1 if an error occurred. */ |
||
1030 | static xiosingle_t * |
||
1031 | xioparse_single(const char **addr /* input string; afterwards points to |
||
1032 | first char not belonging to this |
||
1033 | sub address */ |
||
1034 | ) { |
||
1035 | char addr0[20]; |
||
1036 | xiofile_t *xfd; |
||
1037 | xiosingle_t *sfd; |
||
1038 | struct xioaddrname *ae; |
||
1039 | /*int maxparams;*/ /* max number of parameters */ |
||
1040 | const char *ends[4+1]; |
||
1041 | const char *hquotes[] = { |
||
1042 | "'", |
||
1043 | NULL |
||
1044 | } ; |
||
1045 | const char *squotes[] = { |
||
1046 | "\"", |
||
1047 | NULL |
||
1048 | } ; |
||
1049 | const char *nests[] = { |
||
1050 | "'", "'", |
||
1051 | "(", ")", |
||
1052 | "[", "]", |
||
1053 | "{", "}", |
||
1054 | NULL |
||
1055 | } ; |
||
1056 | char token[512], *tokp; |
||
1057 | size_t len; |
||
1058 | int i; |
||
1059 | |||
1060 | /* init */ |
||
1061 | i = 0; |
||
1062 | ends[i++] = xioopts.chainsep; /* default: "|" */ |
||
1063 | ends[i++] = xioopts.pipesep; /* default: "%" */ |
||
1064 | ends[i++] = ","/*xioopts.comma*/; /* default: "," */ |
||
1065 | ends[i++] = ":"/*xioopts.colon*/; /* default: ":" */ |
||
1066 | ends[i++] = NULL; |
||
1067 | |||
1068 | if ((xfd = xioallocfd()) == NULL) { |
||
1069 | return NULL; |
||
1070 | } |
||
1071 | sfd = &xfd->stream; |
||
1072 | sfd->argc = 0; |
||
1073 | |||
1074 | /* for error messages */ |
||
1075 | addr0[0] = '\0'; strncat(addr0, *addr, sizeof(addr0)-1); |
||
1076 | |||
1077 | len = sizeof(token); tokp = token; |
||
1078 | if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests, |
||
1079 | true, true, true, false) < 0) { |
||
1080 | Error2("keyword too long, in address \"%s%s\"", token, *addr); |
||
1081 | } |
||
1082 | *tokp = '\0'; /*! len? */ |
||
1083 | ae = (struct xioaddrname *) |
||
1084 | keyw((struct wordent *)&address_names, token, |
||
1085 | sizeof(address_names)/sizeof(struct xioaddrname)-1); |
||
1086 | if (ae != NULL) { |
||
1087 | /* found keyword */ |
||
1088 | sfd->addrdescs = ae->desc; |
||
1089 | if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) { |
||
1090 | Error1("strdup(\"%s\"): out of memory", token); |
||
1091 | } |
||
1092 | } else { |
||
1093 | if (false) { /* for canonical reasons */ |
||
1094 | ; |
||
1095 | #if WITH_FDNUM |
||
1096 | } else if (isdigit(token[0]&0xff) && token[1] == '\0') { |
||
1097 | Info1("interpreting address \"%s\" as file descriptor", token); |
||
1098 | sfd->addrdescs = xioaddrs_fdnum; |
||
1099 | if ((sfd->argv[sfd->argc++] = strdup("FD")) == NULL) { |
||
1100 | Error("strdup(\"FD\"): out of memory"); |
||
1101 | } |
||
1102 | if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) { |
||
1103 | Error1("strdup(\"%s\"): out of memory", token); |
||
1104 | } |
||
1105 | /*! check argc overflow */ |
||
1106 | #endif /* WITH_FDNUM */ |
||
1107 | #if WITH_GOPEN |
||
1108 | } else if (strchr(token, '/')) { |
||
1109 | Info1("interpreting address \"%s\" as file name", token); |
||
1110 | sfd->addrdescs = xioaddrs_gopen; |
||
1111 | if ((sfd->argv[sfd->argc++] = strdup("GOPEN")) == NULL) { |
||
1112 | Error("strdup(\"GOPEN\"): out of memory"); |
||
1113 | } |
||
1114 | if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) { |
||
1115 | Error1("strdup(\"%s\"): out of memory", token); |
||
1116 | } |
||
1117 | /*! check argc overflow */ |
||
1118 | #endif /* WITH_GOPEN */ |
||
1119 | } else { |
||
1120 | Error1("unknown device/address \"%s\"", token); |
||
1121 | xiofreefd(xfd); |
||
1122 | return NULL; |
||
1123 | } |
||
1124 | } |
||
1125 | |||
1126 | while (!strncmp(*addr, xioopts.paramsep, strlen(xioopts.paramsep))) { |
||
1127 | if (sfd->argc >= MAXARGV) { |
||
1128 | Error1("address \"%s\": succeeds max number of parameters", |
||
1129 | sfd->argv[0]); |
||
1130 | } |
||
1131 | *addr += strlen(xioopts.paramsep); |
||
1132 | len = sizeof(token); tokp = token; |
||
1133 | if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests, |
||
1134 | true, true, true, false) != 0) { |
||
1135 | Error2("syntax error in address \"%s%s\"", token, *addr); |
||
1136 | } |
||
1137 | *tokp = '\0'; |
||
1138 | if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) { |
||
1139 | Error1("strdup(\"%s\"): out of memory", token); |
||
1140 | } |
||
1141 | } |
||
1142 | |||
1143 | if (parseopts(addr, &sfd->opts) < 0) { |
||
1144 | xiofreefd(xfd); |
||
1145 | return NULL; |
||
1146 | } |
||
1147 | |||
1148 | return sfd; |
||
1149 | } |
||
1150 | |||
1151 | /* during parsing the sub address, we did not know if it is used as inter |
||
1152 | address or endpoint; therefore we could not select the appropriate address |
||
1153 | descriptor. Here we already know the context and thus select the address |
||
1154 | descriptor and check the option groups. |
||
1155 | returns 0 on success or -1 if an error occurred */ |
||
1156 | static int |
||
1157 | xioopen_unoverload(xiosingle_t *sfd, |
||
1158 | int mayleft, /* what may be on left side: or'd |
||
1159 | XIOBIT_RDWR, XIOBIT_RDONLY, |
||
1160 | XIOBIT_WRONLY */ |
||
1161 | int *isleft, /* what the selected address desc |
||
1162 | provides on left side: XIO_RDWR, |
||
1163 | XIO_RDONLY, or XIO_WRONLY */ |
||
1164 | int mayright, /* what may be on right side: or'd |
||
1165 | XIOBIT_RDWR, XIOBIT_RDONLY, |
||
1166 | XIOBIT_WRONLY */ |
||
1167 | int *isright) /* what the selected address desc |
||
1168 | provides on right side: XIO_RDWR, |
||
1169 | XIO_RDONLY, or XIO_WRONLY */ |
||
1170 | { |
||
1171 | const union xioaddr_desc **addrdescs; |
||
1172 | int tag; |
||
1173 | int i; |
||
1174 | |||
1175 | addrdescs = sfd->addrdescs; |
||
1176 | tag = (mayright ? XIOADDR_INTER : XIOADDR_ENDPOINT); |
||
1177 | |||
1178 | /* look for a matching entry in the list of address descriptions */ |
||
1179 | Debug5("searching record for \"%s\" with tag=%d, numparams=%d, leftdir %d, rightdir %d", |
||
1180 | addrdescs[0]->common_desc.defname, |
||
1181 | tag, sfd->argc-1, mayleft, mayright); |
||
1182 | while ((*addrdescs) != NULL) { |
||
1183 | if ((*addrdescs)->tag == tag && |
||
1184 | addrdescs[0]->common_desc.numparams == sfd->argc-1 && |
||
1185 | (addrdescs[0]->common_desc.leftdirs & mayleft) != 0 && |
||
1186 | (mayright ? (addrdescs[0]->inter_desc.rightdirs & mayright) : 1)) { |
||
1187 | break; |
||
1188 | } |
||
1189 | ++addrdescs; |
||
1190 | } |
||
1191 | |||
1192 | if (addrdescs[0] == NULL) { |
||
1193 | if (tag == XIOADDR_ENDPOINT) { |
||
1194 | Error3("address \"%s...\" in endpoint context, leftdirs=%d, with %d parameter(s) is not available", |
||
1195 | sfd->argv[0], mayleft, sfd->argc-1); |
||
1196 | } else { |
||
1197 | Error4("address \"%s...\" in intermediate context, leftdirs=%d, rightdirs=%d, with %d parameter(s) is not available", |
||
1198 | sfd->argv[0], mayleft, mayright, sfd->argc-1); |
||
1199 | } |
||
1200 | xiofreefd((xiofile_t *)sfd); return -1; |
||
1201 | } |
||
1202 | |||
1203 | i = (addrdescs[0]->common_desc.leftdirs & mayleft); |
||
1204 | *isleft = 0; |
||
1205 | while (i>>=1) { |
||
1206 | ++*isleft; |
||
1207 | } |
||
1208 | if (true /*0 mayright*/) { |
||
1209 | i = (addrdescs[0]->inter_desc.rightdirs & mayright); |
||
1210 | *isright = 0; |
||
1211 | while (i>>=1) { |
||
1212 | ++*isright; |
||
1213 | } |
||
1214 | } |
||
1215 | sfd->tag = (*isleft + 1); |
||
1216 | sfd->addrdesc = addrdescs[0]; |
||
1217 | if (addrdescs[0]->common_desc.howtoshut != XIOSHUT_UNSPEC) |
||
1218 | sfd->howtoshut = addrdescs[0]->common_desc.howtoshut; |
||
1219 | if (addrdescs[0]->common_desc.howtoclose != XIOCLOSE_UNSPEC) |
||
1220 | sfd->howtoclose = addrdescs[0]->common_desc.howtoclose; |
||
1221 | |||
1222 | if (tag == XIOADDR_ENDPOINT) { |
||
1223 | Debug1("selected record with leftdirs %d", |
||
1224 | addrdescs[0]->common_desc.leftdirs); |
||
1225 | } else { |
||
1226 | Debug2("selected record with leftdirs %d, rightdirs %d", |
||
1227 | addrdescs[0]->common_desc.leftdirs, |
||
1228 | addrdescs[0]->inter_desc.rightdirs); |
||
1229 | } |
||
1230 | return 0; |
||
1231 | } |
||
1232 | |||
1233 | |||
1234 | static int |
||
1235 | xioopen_inter_single(xiofile_t *xfd, int xioflags) { |
||
1236 | const struct xioaddr_inter_desc *addrdesc; |
||
1237 | int result; |
||
1238 | |||
1239 | addrdesc = &xfd->stream.addrdesc->inter_desc; |
||
1240 | |||
1241 | if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) { |
||
1242 | xfd->tag = XIO_TAG_RDONLY; |
||
1243 | } else if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) { |
||
1244 | xfd->tag = XIO_TAG_WRONLY; |
||
1245 | } else if ((xioflags&XIO_ACCMODE) == XIO_RDWR) { |
||
1246 | xfd->tag = XIO_TAG_RDWR; |
||
1247 | } else { |
||
1248 | Error1("invalid mode for address \"%s\"", xfd->stream.argv[0]); |
||
1249 | } |
||
1250 | xfd->stream.flags &= (~XIO_ACCMODE); |
||
1251 | xfd->stream.flags |= (xioflags & XIO_ACCMODE); |
||
1252 | result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv, |
||
1253 | xfd->stream.opts, xioflags, xfd, |
||
1254 | addrdesc->groups, addrdesc->arg1, |
||
1255 | addrdesc->arg2, addrdesc->arg3); |
||
1256 | return result; |
||
1257 | } |
||
1258 | |||
1259 | static int |
||
1260 | xioopen_endpoint_single(xiofile_t *xfd, int xioflags) { |
||
1261 | const struct xioaddr_endpoint_desc *addrdesc; |
||
1262 | int result; |
||
1263 | |||
1264 | addrdesc = &xfd->stream.addrdesc->endpoint_desc; |
||
1265 | if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) { |
||
1266 | xfd->tag = XIO_TAG_RDONLY; |
||
1267 | } else if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) { |
||
1268 | xfd->tag = XIO_TAG_WRONLY; |
||
1269 | } else if ((xioflags&XIO_ACCMODE) == XIO_RDWR) { |
||
1270 | xfd->tag = XIO_TAG_RDWR; |
||
1271 | } else { |
||
1272 | Error1("invalid mode for address \"%s\"", xfd->stream.argv[0]); |
||
1273 | } |
||
1274 | xfd->stream.flags &= (~XIO_ACCMODE); |
||
1275 | xfd->stream.flags |= (xioflags & XIO_ACCMODE); |
||
1276 | result = (*addrdesc->func)(xfd->stream.argc, xfd->stream.argv, |
||
1277 | xfd->stream.opts, xioflags, xfd, |
||
1278 | addrdesc->groups, addrdesc->arg1, |
||
1279 | addrdesc->arg2, addrdesc->arg3); |
||
1280 | return result; |
||
1281 | } |