1 /* source: xioopen.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this is the source file of the extended open function */
7 #include "xiosysincludes.h"
14 static xiofile_t
*xioallocfd(void);
16 static xiosingle_t
*xioparse_single(const char **addr
);
17 static xiofile_t
*xioparse_dual(const char **addr
);
18 static int xioopen_dual(xiofile_t
*xfd
, int xioflags
);
20 const struct addrname addressnames
[] = {
23 { "-", &xioaddr_stdio
},
25 #if defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET)
26 { "ABSTRACT", &xioaddr_abstract_client
},
27 { "ABSTRACT-CLIENT", &xioaddr_abstract_client
},
28 { "ABSTRACT-CONNECT", &xioaddr_abstract_connect
},
30 { "ABSTRACT-LISTEN", &xioaddr_abstract_listen
},
32 { "ABSTRACT-RECV", &xioaddr_abstract_recv
},
33 { "ABSTRACT-RECVFROM", &xioaddr_abstract_recvfrom
},
34 { "ABSTRACT-SENDTO", &xioaddr_abstract_sendto
},
35 #endif /* defined(WITH_UNIX) && defined(WITH_ABSTRACT_UNIXSOCKET) */
36 #if WITH_LISTEN && WITH_FDNUM
37 { "ACCEPT", &xioaddr_accept_fd
},
38 { "ACCEPT-FD", &xioaddr_accept_fd
},
41 { "CREAT", &xioaddr_creat
},
42 { "CREATE", &xioaddr_creat
},
44 #if WITH_GENERICSOCKET
45 { "DATAGRAM", &xioaddr_socket_datagram
},
47 #if (WITH_IP4 || WITH_IP6) && WITH_DCCP
48 { "DCCP", &xioaddr_dccp_connect
},
49 { "DCCP-CONNECT", &xioaddr_dccp_connect
},
51 { "DCCP-L", &xioaddr_dccp_listen
},
52 { "DCCP-LISTEN", &xioaddr_dccp_listen
},
55 { "DCCP4", &xioaddr_dccp4_connect
},
56 { "DCCP4-CONNECT", &xioaddr_dccp4_connect
},
58 { "DCCP4-L", &xioaddr_dccp4_listen
},
59 { "DCCP4-LISTEN", &xioaddr_dccp4_listen
},
63 { "DCCP6", &xioaddr_dccp6_connect
},
64 { "DCCP6-CONNECT", &xioaddr_dccp6_connect
},
66 { "DCCP6-L", &xioaddr_dccp6_listen
},
67 { "DCCP6-LISTEN", &xioaddr_dccp6_listen
},
70 #endif /* (WITH_IP4 || WITH_IP6) && WITH_DCCP */
71 #if WITH_GENERICSOCKET
72 { "DGRAM", &xioaddr_socket_datagram
},
75 { "DTLS", &xioaddr_openssl_dtls_client
},
76 { "DTLS-C", &xioaddr_openssl_dtls_client
},
77 { "DTLS-CLIENT", &xioaddr_openssl_dtls_client
},
78 { "DTLS-CONNECT", &xioaddr_openssl_dtls_client
},
80 { "DTLS-L", &xioaddr_openssl_dtls_server
},
81 { "DTLS-LISTEN", &xioaddr_openssl_dtls_server
},
82 { "DTLS-SERVER", &xioaddr_openssl_dtls_server
},
86 { "ECHO", &xioaddr_pipe
},
89 { "EXEC", &xioaddr_exec
},
92 { "FD", &xioaddr_fd
},
95 { "FIFO", &xioaddr_pipe
},
98 { "FILE", &xioaddr_open
},
101 { "GOPEN", &xioaddr_gopen
},
104 { "IF", &xioaddr_interface
},
106 #if (WITH_IP4 || WITH_IP6) && WITH_TCP
107 { "INET", &xioaddr_tcp_connect
},
109 #if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN
110 { "INET-L", &xioaddr_tcp_listen
},
111 { "INET-LISTEN", &xioaddr_tcp_listen
},
113 #if WITH_IP4 && WITH_TCP
114 { "INET4", &xioaddr_tcp4_connect
},
116 #if WITH_IP4 && WITH_TCP && WITH_LISTEN
117 { "INET4-L", &xioaddr_tcp4_listen
},
118 { "INET4-LISTEN", &xioaddr_tcp4_listen
},
120 #if WITH_IP6 && WITH_TCP
121 { "INET6", &xioaddr_tcp6_connect
},
123 #if WITH_IP6 && WITH_TCP && WITH_LISTEN
124 { "INET6-L", &xioaddr_tcp6_listen
},
125 { "INET6-LISTEN", &xioaddr_tcp6_listen
},
128 { "INTERFACE", &xioaddr_interface
},
131 #if (WITH_IP4 || WITH_IP6)
132 { "IP", &xioaddr_rawip_sendto
},
133 { "IP-DATAGRAM", &xioaddr_rawip_datagram
},
134 { "IP-DGRAM", &xioaddr_rawip_datagram
},
135 { "IP-RECV", &xioaddr_rawip_recv
},
136 { "IP-RECVFROM", &xioaddr_rawip_recvfrom
},
137 { "IP-SEND", &xioaddr_rawip_sendto
},
138 { "IP-SENDTO", &xioaddr_rawip_sendto
},
141 { "IP4", &xioaddr_rawip4_sendto
},
142 { "IP4-DATAGRAM", &xioaddr_rawip4_datagram
},
143 { "IP4-DGRAM", &xioaddr_rawip4_datagram
},
144 { "IP4-RECV", &xioaddr_rawip4_recv
},
145 { "IP4-RECVFROM", &xioaddr_rawip4_recvfrom
},
146 { "IP4-SEND", &xioaddr_rawip4_sendto
},
147 { "IP4-SENDTO", &xioaddr_rawip4_sendto
},
150 { "IP6", &xioaddr_rawip6_sendto
},
151 { "IP6-DATAGRAM", &xioaddr_rawip6_datagram
},
152 { "IP6-DGRAM", &xioaddr_rawip6_datagram
},
153 { "IP6-RECV", &xioaddr_rawip6_recv
},
154 { "IP6-RECVFROM", &xioaddr_rawip6_recvfrom
},
155 { "IP6-SEND", &xioaddr_rawip6_sendto
},
156 { "IP6-SENDTO", &xioaddr_rawip6_sendto
},
158 #endif /* WITH_RAWIP */
160 { "LOCAL", &xioaddr_unix_connect
},
163 { "OPEN", &xioaddr_open
},
166 { "OPENSSL", &xioaddr_openssl
},
167 { "OPENSSL-CONNECT", &xioaddr_openssl
},
168 { "OPENSSL-DTLS-CLIENT", &xioaddr_openssl_dtls_client
},
169 { "OPENSSL-DTLS-CONNECT", &xioaddr_openssl_dtls_client
},
171 { "OPENSSL-DTLS-LISTEN", &xioaddr_openssl_dtls_server
},
172 { "OPENSSL-DTLS-SERVER", &xioaddr_openssl_dtls_server
},
173 { "OPENSSL-LISTEN", &xioaddr_openssl_listen
},
177 { "PIPE", &xioaddr_pipe
},
180 { "POSIXMQ-BIDIRECTIONAL", &xioaddr_posixmq_bidir
},
181 { "POSIXMQ-READ", &xioaddr_posixmq_read
},
182 { "POSIXMQ-RECEIVE", &xioaddr_posixmq_receive
},
183 { "POSIXMQ-RECV", &xioaddr_posixmq_receive
},
184 { "POSIXMQ-SEND", &xioaddr_posixmq_send
},
187 { "PROXY", &xioaddr_proxy_connect
},
188 { "PROXY-CONNECT", &xioaddr_proxy_connect
},
191 { "PTY", &xioaddr_pty
},
194 { "READLINE", &xioaddr_readline
},
196 #if (WITH_IP4 || WITH_IP6) && WITH_SCTP
197 { "SCTP", &xioaddr_sctp_connect
},
198 { "SCTP-CONNECT", &xioaddr_sctp_connect
},
200 { "SCTP-L", &xioaddr_sctp_listen
},
201 { "SCTP-LISTEN", &xioaddr_sctp_listen
},
204 { "SCTP4", &xioaddr_sctp4_connect
},
205 { "SCTP4-CONNECT", &xioaddr_sctp4_connect
},
207 { "SCTP4-L", &xioaddr_sctp4_listen
},
208 { "SCTP4-LISTEN", &xioaddr_sctp4_listen
},
210 #endif /* WITH_IP4 */
212 { "SCTP6", &xioaddr_sctp6_connect
},
213 { "SCTP6-CONNECT", &xioaddr_sctp6_connect
},
215 { "SCTP6-L", &xioaddr_sctp6_listen
},
216 { "SCTP6-LISTEN", &xioaddr_sctp6_listen
},
218 #endif /* WITH_IP6 */
219 #endif /* (WITH_IP4 || WITH_IP6) && WITH_SCTP */
220 #if WITH_GENERICSOCKET
221 { "SENDTO", &xioaddr_socket_sendto
},
224 { "SHELL", &xioaddr_shell
},
226 #if WITH_GENERICSOCKET
227 { "SOCKET-CONNECT", &xioaddr_socket_connect
},
228 { "SOCKET-DATAGRAM", &xioaddr_socket_datagram
},
230 { "SOCKET-LISTEN", &xioaddr_socket_listen
},
231 #endif /* WITH_LISTEN */
232 { "SOCKET-RECV", &xioaddr_socket_recv
},
233 { "SOCKET-RECVFROM", &xioaddr_socket_recvfrom
},
234 { "SOCKET-SENDTO", &xioaddr_socket_sendto
},
237 { "SOCKETPAIR", &xioaddr_socketpair
},
240 { "SOCKS", &xioaddr_socks4_connect
},
241 { "SOCKS4", &xioaddr_socks4_connect
},
244 { "SOCKS4A", &xioaddr_socks4a_connect
},
247 { "SOCKS5", &xioaddr_socks5_connect
},
248 { "SOCKS5-BIND", &xioaddr_socks5_listen
},
249 { "SOCKS5-CONNECT", &xioaddr_socks5_connect
},
250 { "SOCKS5-LISTEN", &xioaddr_socks5_listen
},
253 { "SSL", &xioaddr_openssl
},
255 { "SSL-L", &xioaddr_openssl_listen
},
259 { "STDERR", &xioaddr_stderr
},
260 { "STDIN", &xioaddr_stdin
},
261 { "STDIO", &xioaddr_stdio
},
262 { "STDOUT", &xioaddr_stdout
},
265 { "SYSTEM", &xioaddr_system
},
267 #if (WITH_IP4 || WITH_IP6) && WITH_TCP
268 { "TCP", &xioaddr_tcp_connect
},
269 { "TCP-CONNECT", &xioaddr_tcp_connect
},
271 #if (WITH_IP4 || WITH_IP6) && WITH_TCP && WITH_LISTEN
272 { "TCP-L", &xioaddr_tcp_listen
},
273 { "TCP-LISTEN", &xioaddr_tcp_listen
},
275 #if WITH_IP4 && WITH_TCP
276 { "TCP4", &xioaddr_tcp4_connect
},
277 { "TCP4-CONNECT", &xioaddr_tcp4_connect
},
279 #if WITH_IP4 && WITH_TCP && WITH_LISTEN
280 { "TCP4-L", &xioaddr_tcp4_listen
},
281 { "TCP4-LISTEN", &xioaddr_tcp4_listen
},
283 #if WITH_IP6 && WITH_TCP
284 { "TCP6", &xioaddr_tcp6_connect
},
285 { "TCP6-CONNECT", &xioaddr_tcp6_connect
},
287 #if WITH_IP6 && WITH_TCP && WITH_LISTEN
288 { "TCP6-L", &xioaddr_tcp6_listen
},
289 { "TCP6-LISTEN", &xioaddr_tcp6_listen
},
292 { "TUN", &xioaddr_tun
},
294 #if (WITH_IP4 || WITH_IP6) && WITH_UDP
295 { "UDP", &xioaddr_udp_connect
},
297 #if (WITH_IP4 || WITH_IP6) && WITH_UDP
298 { "UDP-CONNECT", &xioaddr_udp_connect
},
299 { "UDP-DATAGRAM", &xioaddr_udp_datagram
},
300 { "UDP-DGRAM", &xioaddr_udp_datagram
},
302 #if (WITH_IP4 || WITH_IP6) && WITH_UDP && WITH_LISTEN
303 { "UDP-L", &xioaddr_udp_listen
},
304 { "UDP-LISTEN", &xioaddr_udp_listen
},
306 #if (WITH_IP4 || WITH_IP6) && WITH_UDP
307 { "UDP-RECV", &xioaddr_udp_recv
},
308 { "UDP-RECVFROM", &xioaddr_udp_recvfrom
},
309 { "UDP-SEND", &xioaddr_udp_sendto
},
310 { "UDP-SENDTO", &xioaddr_udp_sendto
},
312 #if WITH_IP4 && WITH_UDP
313 { "UDP4", &xioaddr_udp4_connect
},
314 { "UDP4-CONNECT", &xioaddr_udp4_connect
},
315 { "UDP4-DATAGRAM", &xioaddr_udp4_datagram
},
316 { "UDP4-DGRAM", &xioaddr_udp4_datagram
},
318 #if WITH_IP4 && WITH_UDP && WITH_LISTEN
319 { "UDP4-L", &xioaddr_udp4_listen
},
320 { "UDP4-LISTEN", &xioaddr_udp4_listen
},
322 #if WITH_IP4 && WITH_UDP
323 { "UDP4-RECV", &xioaddr_udp4_recv
},
324 { "UDP4-RECVFROM", &xioaddr_udp4_recvfrom
},
325 { "UDP4-SEND", &xioaddr_udp4_sendto
},
326 { "UDP4-SENDTO", &xioaddr_udp4_sendto
},
328 #if WITH_IP6 && WITH_UDP
329 { "UDP6", &xioaddr_udp6_connect
},
330 { "UDP6-CONNECT", &xioaddr_udp6_connect
},
331 { "UDP6-DATAGRAM", &xioaddr_udp6_datagram
},
332 { "UDP6-DGRAM", &xioaddr_udp6_datagram
},
334 #if WITH_IP6 && WITH_UDP && WITH_LISTEN
335 { "UDP6-L", &xioaddr_udp6_listen
},
336 { "UDP6-LISTEN", &xioaddr_udp6_listen
},
338 #if WITH_IP6 && WITH_UDP
339 { "UDP6-RECV", &xioaddr_udp6_recv
},
340 { "UDP6-RECVFROM", &xioaddr_udp6_recvfrom
},
341 { "UDP6-SEND", &xioaddr_udp6_sendto
},
342 { "UDP6-SENDTO", &xioaddr_udp6_sendto
},
344 #if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE
345 { "UDPLITE", &xioaddr_udplite_connect
},
346 { "UDPLITE-CONNECT", &xioaddr_udplite_connect
},
347 { "UDPLITE-DATAGRAM", &xioaddr_udplite_datagram
},
348 { "UDPLITE-DGRAM", &xioaddr_udplite_datagram
},
350 #if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE && WITH_LISTEN
351 { "UDPLITE-L", &xioaddr_udplite_listen
},
352 { "UDPLITE-LISTEN", &xioaddr_udplite_listen
},
354 #if (WITH_IP4 || WITH_IP6) && WITH_UDPLITE
355 { "UDPLITE-RECV", &xioaddr_udplite_recv
},
356 { "UDPLITE-RECVFROM", &xioaddr_udplite_recvfrom
},
357 { "UDPLITE-SEND", &xioaddr_udplite_sendto
},
358 { "UDPLITE-SENDTO", &xioaddr_udplite_sendto
},
360 #if WITH_IP4 && WITH_UDPLITE
361 { "UDPLITE4", &xioaddr_udplite4_connect
},
362 { "UDPLITE4-CONNECT", &xioaddr_udplite4_connect
},
363 { "UDPLITE4-DATAGRAM", &xioaddr_udplite4_datagram
},
364 { "UDPLITE4-DGRAM", &xioaddr_udplite4_datagram
},
366 #if WITH_IP4 && WITH_UDPLITE && WITH_LISTEN
367 { "UDPLITE4-L", &xioaddr_udplite4_listen
},
368 { "UDPLITE4-LISTEN", &xioaddr_udplite4_listen
},
370 #if WITH_IP4 && WITH_UDPLITE
371 { "UDPLITE4-RECV", &xioaddr_udplite4_recv
},
372 { "UDPLITE4-RECVFROM", &xioaddr_udplite4_recvfrom
},
373 { "UDPLITE4-SEND", &xioaddr_udplite4_sendto
},
374 { "UDPLITE4-SENDTO", &xioaddr_udplite4_sendto
},
376 #if WITH_IP6 && WITH_UDPLITE
377 { "UDPLITE6", &xioaddr_udplite6_connect
},
378 { "UDPLITE6-CONNECT", &xioaddr_udplite6_connect
},
379 { "UDPLITE6-DATAGRAM", &xioaddr_udplite6_datagram
},
380 { "UDPLITE6-DGRAM", &xioaddr_udplite6_datagram
},
382 #if WITH_IP6 && WITH_UDPLITE && WITH_LISTEN
383 { "UDPLITE6-L", &xioaddr_udplite6_listen
},
384 { "UDPLITE6-LISTEN", &xioaddr_udplite6_listen
},
386 #if WITH_IP6 && WITH_UDPLITE
387 { "UDPLITE6-RECV", &xioaddr_udplite6_recv
},
388 { "UDPLITE6-RECVFROM", &xioaddr_udplite6_recvfrom
},
389 { "UDPLITE6-SEND", &xioaddr_udplite6_sendto
},
390 { "UDPLITE6-SENDTO", &xioaddr_udplite6_sendto
},
393 { "UNIX", &xioaddr_unix_client
},
394 { "UNIX-CLIENT", &xioaddr_unix_client
},
395 { "UNIX-CONNECT", &xioaddr_unix_connect
},
397 #if WITH_UNIX && WITH_LISTEN
398 { "UNIX-L", &xioaddr_unix_listen
},
399 { "UNIX-LISTEN", &xioaddr_unix_listen
},
402 { "UNIX-RECV", &xioaddr_unix_recv
},
403 { "UNIX-RECVFROM", &xioaddr_unix_recvfrom
},
404 { "UNIX-SEND", &xioaddr_unix_sendto
},
405 { "UNIX-SENDTO", &xioaddr_unix_sendto
},
408 { "VSOCK", &xioaddr_vsock_connect
},
409 { "VSOCK-CONNECT", &xioaddr_vsock_connect
},
411 #if WITH_VSOCK && WITH_LISTEN
412 { "VSOCK-L", &xioaddr_vsock_listen
},
413 { "VSOCK-LISTEN", &xioaddr_vsock_listen
},
417 # include "xiointegrate.c"
419 # include "xioaddrtab.c"
422 { NULL
} /* end marker */
425 int xioopen_single(xiofile_t
*xfd
, int xioflags
);
428 /* prepares a xiofile_t record for dual address type:
429 sets the tag and allocates memory for the substreams.
430 returns 0 on success, or <0 if an error occurred.
432 int xioopen_makedual(xiofile_t
*file
) {
433 file
->tag
= XIO_TAG_DUAL
;
434 file
->common
.flags
= XIO_RDWR
;
435 if ((file
->dual
.stream
[0] = (xiosingle_t
*)xioallocfd()) == NULL
)
437 file
->dual
.stream
[0]->flags
= XIO_RDONLY
;
438 if ((file
->dual
.stream
[1] = (xiosingle_t
*)xioallocfd()) == NULL
)
440 file
->dual
.stream
[1]->flags
= XIO_WRONLY
;
444 static xiofile_t
*xioallocfd(void) {
447 if ((fd
= Calloc(1, sizeof(xiofile_t
))) == NULL
) {
450 /* some default values; 0's and NULL's need not be applied (calloc'ed) */
451 fd
->common
.tag
= XIO_TAG_INVALID
;
452 /* fd->common.addr = NULL; */
453 fd
->common
.flags
= XIO_RDWR
;
456 /* fd->stream.retry = 0; */
457 /* fd->stream.forever = false; */
458 fd
->stream
.intervall
.tv_sec
= 1;
459 /* fd->stream.intervall.tv_nsec = 0; */
460 #endif /* WITH_RETRY */
461 /* fd->common.ignoreeof = false; */
462 /* fd->common.eof = 0; */
463 fd
->stream
.triggerfd
= -1;
465 fd
->stream
.dtype
= XIODATA_STREAM
;
467 /* fd->stream.salen = 0; */
468 #endif /* _WITH_SOCKET */
469 fd
->stream
.howtoend
= END_UNSPEC
;
470 /* fd->stream.name = NULL; */
471 fd
->stream
.escape
= -1;
472 /* fd->stream.para.exec.pid = 0; */
473 fd
->stream
.lineterm
= LINETERM_RAW
;
476 fd
->stream
.para
.socket
.ip
.res
.retrans
= -1;
479 fd
->stream
.para
.socket
.ip
.res
.retry
= -1;
481 #endif /* WITH_RESOLVE */
486 /* parse the argument that specifies a two-directional data stream
487 and open the resulting address
489 xiofile_t
*xioopen(const char *addr
, /* address specification */
493 Debug1("xioopen(\"%s\")", addr
);
495 if ((xfd
= xioparse_dual(&addr
)) == NULL
) {
498 /*!! support n socks */
504 if (xioopen_dual(xfd
, xioflags
) < 0) {
505 /*!!! free something? */
512 /* parse an address string that might contain !!
513 return NULL on error */
514 static xiofile_t
*xioparse_dual(const char **addr
) {
518 /* we parse a single address */
519 if ((sfd1
= xioparse_single(addr
)) == NULL
) {
523 /* and now we see if we reached a dual-address separator */
524 if (!strncmp(*addr
, xioparms
.pipesep
, strlen(xioparms
.pipesep
))) {
525 /* yes we reached it, so we parse the second single address */
526 *addr
+= strlen(xioparms
.pipesep
);
528 if ((xfd
= xioallocfd()) == NULL
) {
529 free(sfd1
); /*! and maybe have free some if its contents */
532 xfd
->tag
= XIO_TAG_DUAL
;
533 xfd
->dual
.stream
[0] = sfd1
;
534 if ((xfd
->dual
.stream
[1] = xioparse_single(addr
)) == NULL
) {
541 /* a truly single address */
542 xfd
= (xiofile_t
*)sfd1
; sfd1
= NULL
;
547 static int xioopen_dual(xiofile_t
*xfd
, int xioflags
) {
549 if (xfd
->tag
== XIO_TAG_DUAL
) {
550 /* a really dual address */
551 if ((xioflags
&XIO_ACCMODE
) != XIO_RDWR
) {
552 Warn("unidirectional open of dual address");
554 if (((xioflags
&XIO_ACCMODE
)+1) & (XIO_RDONLY
+1)) {
555 if (xioopen_single((xiofile_t
*)xfd
->dual
.stream
[0], XIO_RDONLY
|(xioflags
&~XIO_ACCMODE
&~XIO_MAYEXEC
))
560 if (((xioflags
&XIO_ACCMODE
)+1) & (XIO_WRONLY
+1)) {
561 if (xioopen_single((xiofile_t
*)xfd
->dual
.stream
[1], XIO_WRONLY
|(xioflags
&~XIO_ACCMODE
&~XIO_MAYEXEC
))
563 xioclose((xiofile_t
*)xfd
->dual
.stream
[0]);
570 return xioopen_single(xfd
, xioflags
);
574 static xiosingle_t
*xioparse_single(const char **addr
) {
575 const char *addr0
= *addr
; /* save for error messages */
579 const struct addrdesc
*addrdesc
= NULL
;
580 const char *ends
[4+1];
581 const char *hquotes
[] = {
585 const char *squotes
[] = {
589 const char *nests
[] = {
596 char token
[512], *tokp
;
603 /*ends[i++] = xioparms.chainsep;*/ /* default: "|" */
604 ends
[i
++] = xioparms
.pipesep
; /* default: "!!" */
605 ends
[i
++] = ","/*xioparms.comma*/; /* default: "," */
606 ends
[i
++] = ":"/*xioparms.colon*/; /* default: ":" */
609 if ((xfd
= xioallocfd()) == NULL
) {
615 len
= sizeof(token
); tokp
= token
;
616 result
= nestlex(addr
, &tokp
, &len
, ends
, hquotes
, squotes
, nests
,
619 Error2("keyword too long, in address \"%s%s\"", token
, *addr
);
620 } else if (result
> 0){
621 Error1("unexpected end of address \"%s\"", *addr
);
623 *tokp
= '\0'; /*! len? */
624 ae
= (struct addrname
*)
625 keyw((struct wordent
*)&addressnames
, token
,
626 sizeof(addressnames
)/sizeof(struct addrname
)-1);
631 if ((sfd
->argv
[sfd
->argc
++] = strdup(token
)) == NULL
) {
632 Error1("strdup(\"%s\"): out of memory", token
);
638 } else if (isdigit(token
[0]&0xff) && token
[1] == '\0') {
639 Info1("interpreting address \"%s\" as file descriptor", token
);
640 addrdesc
= &xioaddr_fd
;
641 if ((sfd
->argv
[sfd
->argc
++] = strdup("FD")) == NULL
) {
642 Error("strdup(\"FD\"): out of memory");
644 if ((sfd
->argv
[sfd
->argc
++] = strdup(token
)) == NULL
) {
645 Error1("strdup(\"%s\"): out of memory", token
);
647 /*! check argc overflow */
648 #endif /* WITH_FDNUM */
650 } else if (strchr(token
, '/')) {
651 Info1("interpreting address \"%s\" as file name", token
);
652 addrdesc
= &xioaddr_gopen
;
653 if ((sfd
->argv
[sfd
->argc
++] = strdup("GOPEN")) == NULL
) {
654 Error("strdup(\"GOPEN\"): out of memory");
656 if ((sfd
->argv
[sfd
->argc
++] = strdup(token
)) == NULL
) {
657 Error1("strdup(\"%s\"): out of memory", token
);
659 /*! check argc overflow */
660 #endif /* WITH_GOPEN */
662 Error1("unknown device/address \"%s\"", token
);
663 /*!!! free something*/ return NULL
;
667 sfd
->tag
= XIO_TAG_RDWR
;
668 sfd
->addr
= addrdesc
;
670 while (!strncmp(*addr
, xioparms
.paramsep
, strlen(xioparms
.paramsep
))) {
671 *addr
+= strlen(xioparms
.paramsep
);
672 len
= sizeof(token
); tokp
= token
;
673 result
= nestlex(addr
, &tokp
, &len
, ends
, hquotes
, squotes
, nests
,
676 Error1("address \"%s\" too long", addr0
);
677 } else if (result
> 0){
678 Error1("unexpected end of address \"%s\"", addr0
);
681 if ((sfd
->argv
[sfd
->argc
++] = strdup(token
)) == NULL
) {
682 Error1("strdup(\"%s\"): out of memory", token
);
686 if (parseopts(addr
, addrdesc
->groups
, &sfd
->opts
) < 0) {
694 int xioopen_single(xiofile_t
*xfd
, int xioflags
) {
695 struct single
*sfd
= &xfd
->stream
;
696 const struct addrdesc
*addrdesc
;
697 const char *modetext
[4] = { "none", "read-only", "write-only", "read-write" } ;
698 /* Values to be saved until xioopen() is finished */
699 char *orig_dir
= NULL
;
700 bool have_umask
= false;
701 mode_t orig_umask
, tmp_umask
;
703 /* Values to be saved until xioopen() is finished */
704 #if WITH_RESOLVE && HAVE_RESOLV_H
706 struct __res_state save_res
;
707 #endif /* WITH_RESOLVE && HAVE_RESOLV_H */
712 addrdesc
= xfd
->stream
.addr
;
713 if (((xioflags
+1)&XIO_ACCMODE
) & ~(addrdesc
->directions
)) {
714 Warn2("address is opened in %s mode but only supports %s", modetext
[(xioflags
+1)&XIO_ACCMODE
], modetext
[addrdesc
->directions
]);
716 if ((xioflags
&XIO_ACCMODE
) == XIO_RDONLY
) {
717 xfd
->tag
= XIO_TAG_RDONLY
;
718 } else if ((xioflags
&XIO_ACCMODE
) == XIO_WRONLY
) {
719 xfd
->tag
= XIO_TAG_WRONLY
;
720 } else if ((xioflags
&XIO_ACCMODE
) == XIO_RDWR
) {
721 xfd
->tag
= XIO_TAG_RDWR
;
723 Error1("invalid mode for address \"%s\"", xfd
->stream
.argv
[0]);
725 xfd
->stream
.flags
&= (~XIO_ACCMODE
);
726 xfd
->stream
.flags
|= (xioflags
& XIO_ACCMODE
);
728 /* Apply "temporary" process properties, save value for later restore */
730 if (applyopts_single(sfd
, sfd
->opts
, PH_OFFSET
) < 0)
734 if ((save_netfd
= xio_apply_namespace(sfd
->opts
)) < 0)
736 #endif /* WITH_NAMESPACES */
738 #if WITH_RESOLVE && HAVE_RESOLV_H
739 if ((do_res
= xio_res_init(sfd
, &save_res
)) < 0)
741 #endif /* WITH_RESOLVE && HAVE_RESOLV_H */
743 if (xio_chdir(sfd
->opts
, &orig_dir
) < 0)
746 if (retropt_mode(xfd
->stream
.opts
, OPT_UMASK
, &tmp_umask
) >= 0) {
747 Info1("changing umask to 0%3o", tmp_umask
);
748 orig_umask
= Umask(tmp_umask
);
752 /* Call the specific xioopen function */
753 result
= (*addrdesc
->func
)(xfd
->stream
.argc
, xfd
->stream
.argv
,
754 xfd
->stream
.opts
, xioflags
, xfd
,
757 /* Restore process properties */
759 Info1("restoring umask to 0%3o", orig_umask
);
763 if (orig_dir
!= NULL
) {
764 if (Chdir(orig_dir
) < 0) {
765 Error2("chdir(\"%s\"): %s", orig_dir
, strerror(errno
));
772 #if WITH_RESOLVE && HAVE_RESOLV_H
774 xio_res_restore(&save_res
);
775 #endif /* WITH_RESOLVE && HAVE_RESOLV_H */
778 if (save_netfd
> 0) {
779 xio_reset_namespace(save_netfd
);
781 #endif /* WITH_NAMESPACES */
792 return xiohelp_syntax(addr
, expectnum
, isnum
, syntax
);