1 /* source: xio-unix.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 file contains the source for opening addresses of UNIX socket type */
7 #include "xiosysincludes.h"
10 #include "xio-socket.h"
11 #include "xio-listen.h"
13 #include "xio-named.h"
18 /* to avoid unneccessary "live" if () conditionals when no abstract support is
19 compiled in (or at least to give optimizing compilers a good chance) we need
20 a constant that can be used in C expressions */
21 #if WITH_ABSTRACT_UNIXSOCKET
27 static int xioopen_unix_connect(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
);
28 static int xioopen_unix_listen(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
);
29 static int xioopen_unix_sendto(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
);
30 static int xioopen_unix_recvfrom(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
);
32 int xioopen_unix_recv(int argc
, const char *argv
[], struct opt
*opts
,
33 int xioflags
, xiofile_t
*xxfd
, unsigned groups
,
34 int abstract
, int dummy2
, int dummy3
);
36 int xioopen_unix_client(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
);
38 /* the first free parameter is 0 for "normal" unix domain sockets, or 1 for
39 abstract unix sockets (Linux); the second and third free parameter are
41 const struct addrdesc xioaddr_unix_connect
= { "unix-connect", 3, xioopen_unix_connect
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 0, 0, 0 HELP(":<filename>") };
43 const struct addrdesc xioaddr_unix_listen
= { "unix-listen", 3, xioopen_unix_listen
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_LISTEN
|GROUP_CHILD
|GROUP_RETRY
, 0, 0, 0 HELP(":<filename>") };
44 #endif /* WITH_LISTEN */
45 const struct addrdesc xioaddr_unix_sendto
= { "unix-sendto", 3, xioopen_unix_sendto
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 0, 0, 0 HELP(":<filename>") };
46 const struct addrdesc xioaddr_unix_recvfrom
= { "unix-recvfrom", 3, xioopen_unix_recvfrom
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
|GROUP_CHILD
, 0, 0, 0 HELP(":<filename>") };
47 const struct addrdesc xioaddr_unix_recv
= { "unix-recv", 1, xioopen_unix_recv
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 0, 0, 0 HELP(":<filename>") };
48 const struct addrdesc xioaddr_unix_client
= { "unix-client", 3, xioopen_unix_client
, GROUP_FD
|GROUP_NAMED
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 0, 0, 0 HELP(":<filename>") };
49 #if WITH_ABSTRACT_UNIXSOCKET
50 const struct addrdesc xioaddr_abstract_connect
= { "abstract-connect", 3, xioopen_unix_connect
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 1, 0, 0 HELP(":<filename>") };
52 const struct addrdesc xioaddr_abstract_listen
= { "abstract-listen", 3, xioopen_unix_listen
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_LISTEN
|GROUP_CHILD
|GROUP_RETRY
, 1, 0, 0 HELP(":<filename>") };
53 #endif /* WITH_LISTEN */
54 const struct addrdesc xioaddr_abstract_sendto
= { "abstract-sendto", 3, xioopen_unix_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 1, 0, 0 HELP(":<filename>") };
55 const struct addrdesc xioaddr_abstract_recvfrom
= { "abstract-recvfrom", 3, xioopen_unix_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
|GROUP_CHILD
, 1, 0, 0 HELP(":<filename>") };
56 const struct addrdesc xioaddr_abstract_recv
= { "abstract-recv", 1, xioopen_unix_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 1, 0, 0 HELP(":<filename>") };
57 const struct addrdesc xioaddr_abstract_client
= { "abstract-client", 3, xioopen_unix_client
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_UNIX
|GROUP_RETRY
, 1, 0, 0 HELP(":<filename>") };
58 #endif /* WITH_ABSTRACT_UNIXSOCKET */
60 const struct optdesc xioopt_unix_tightsocklen
= { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN
, GROUP_SOCK_UNIX
, PH_PREBIND
, TYPE_BOOL
, OFUNC_OFFSET
, XIO_OFFSETOF(para
.socket
.un
.tight
), XIO_SIZEOF(para
.socket
.un
.tight
) };
63 /* fills the socket address struct and returns its effective length.
64 abstract is usually 0; != 0 generates an abstract socket address on Linux.
65 tight!=0 calculates the resulting length from the path length, not from the
66 structures length; this is more common (see option unix-tightsocklen)
67 the struct need not be initialized when calling this function.
71 struct sockaddr_un
*saun
,
79 #ifdef WITH_ABSTRACT_UNIXSOCKET
81 if ((pathlen
= strlen(path
)) >= sizeof(saun
->sun_path
)) {
82 Warn2("socket address "F_Zu
" characters long, truncating to "F_Zu
"",
83 pathlen
+1, sizeof(saun
->sun_path
));
85 saun
->sun_path
[0] = '\0'; /* so it's abstract */
86 strncpy(saun
->sun_path
+1, path
, sizeof(saun
->sun_path
)-1); /* ok */
88 len
= sizeof(struct sockaddr_un
)-sizeof(saun
->sun_path
)+
89 MIN(pathlen
+1, sizeof(saun
->sun_path
));
90 #if HAVE_STRUCT_SOCKADDR_SALEN
94 len
= sizeof(struct sockaddr_un
);
98 #endif /* WITH_ABSTRACT_UNIXSOCKET */
100 if ((pathlen
= strlen(path
)) > sizeof(saun
->sun_path
)) {
101 Warn2("unix socket address "F_Zu
" characters long, truncating to "F_Zu
"",
102 pathlen
, sizeof(saun
->sun_path
));
104 strncpy(saun
->sun_path
, path
, sizeof(saun
->sun_path
)); /* ok */
106 len
= sizeof(struct sockaddr_un
)-sizeof(saun
->sun_path
)+
107 MIN(pathlen
, sizeof(saun
->sun_path
));
108 #if HAVE_STRUCT_SOCKADDR_SALEN
112 len
= sizeof(struct sockaddr_un
);
118 static int xioopen_unix_listen(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
) {
119 /* we expect the form: filename */
121 xiosingle_t
*xfd
= &xxfd
->stream
;
123 int socktype
= SOCK_STREAM
;
125 struct sockaddr_un us
;
127 struct opt
*opts0
= NULL
;
128 pid_t pid
= Getpid();
129 bool opt_unlink_early
= false;
130 bool opt_unlink_close
= true;
134 Error2("%s: wrong number of parameters (%d instead of 1)",
140 xfd
->para
.socket
.un
.tight
= true;
141 retropt_socket_pf(opts
, &pf
);
142 xfd
->howtoend
= END_SHUTDOWN
;
144 if (!(ABSTRACT
&& abstract
)) {
145 /* only for non abstract because abstract do not work in file system */
146 retropt_bool(opts
, OPT_UNLINK_EARLY
, &opt_unlink_early
);
147 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
150 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return STAT_NORETRY
;
151 applyopts(-1, opts
, PH_INIT
);
152 applyopts_named(name
, opts
, PH_EARLY
); /* umask! */
153 applyopts_offset(xfd
, opts
);
154 applyopts(-1, opts
, PH_EARLY
);
156 uslen
= xiosetunix(pf
, &us
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
158 if (!(ABSTRACT
&& abstract
)) {
159 if (opt_unlink_early
) {
160 if (Unlink(name
) < 0) {
161 if (errno
== ENOENT
) {
162 Warn2("unlink(\"%s\"): %s", name
, strerror(errno
));
164 Error2("unlink(\"%s\"): %s", name
, strerror(errno
));
169 if (Lstat(name
, &buf
) == 0) {
170 Error1("\"%s\" exists", name
);
171 return STAT_RETRYLATER
;
174 if (opt_unlink_close
) {
175 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
176 Error1("strdup(\"%s\"): out of memory", name
);
178 xfd
->opt_unlink_close
= true;
181 /* trying to set user-early, perm-early etc. here is useless because
182 file system entry is available only past bind() call. */
185 opts0
= copyopts(opts
, GROUP_ALL
);
187 /* this may fork() */
189 xioopen_listen(xfd
, xioflags
,
190 (struct sockaddr
*)&us
, uslen
,
191 opts
, opts0
, pf
, socktype
, protocol
))
195 if (!(ABSTRACT
&& abstract
)) {
196 if (opt_unlink_close
) {
197 if (pid
!= Getpid()) {
198 /* in a child process - do not unlink-close here! */
199 xfd
->opt_unlink_close
= false;
206 #endif /* WITH_LISTEN */
209 static int xioopen_unix_connect(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
) {
210 /* we expect the form: filename */
212 struct single
*xfd
= &xxfd
->stream
;
214 int socktype
= SOCK_STREAM
;
216 struct sockaddr_un them
, us
;
217 socklen_t themlen
, uslen
= sizeof(us
);
218 bool needbind
= false;
219 bool opt_unlink_close
= false;
223 Error2("%s: wrong number of parameters (%d instead of 1)",
229 xfd
->para
.socket
.un
.tight
= true;
230 retropt_socket_pf(opts
, &pf
);
231 xfd
->howtoend
= END_SHUTDOWN
;
232 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return STAT_NORETRY
;
233 applyopts(-1, opts
, PH_INIT
);
234 applyopts_offset(xfd
, opts
);
235 applyopts(-1, opts
, PH_EARLY
);
237 themlen
= xiosetunix(pf
, &them
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
238 if (!(ABSTRACT
&& abstract
)) {
239 /* only for non abstract because abstract do not work in file system */
240 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
242 if (retropt_bind(opts
, pf
, socktype
, protocol
, (struct sockaddr
*)&us
, &uslen
,
243 (abstract
<<1)|xfd
->para
.socket
.un
.tight
, 0, 0) == STAT_OK
) {
247 if (opt_unlink_close
) {
248 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
249 Error1("strdup(\"%s\"): out of memory", name
);
251 xfd
->opt_unlink_close
= true;
256 needbind
?(struct sockaddr
*)&us
:NULL
, uslen
,
257 (struct sockaddr
*)&them
, themlen
,
258 opts
, pf
, socktype
, protocol
, false)) != 0) {
261 if ((result
= _xio_openlate(xfd
, opts
)) < 0) {
268 static int xioopen_unix_sendto(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy
, int dummy3
) {
269 /* we expect the form: filename */
271 xiosingle_t
*xfd
= &xxfd
->stream
;
273 int socktype
= SOCK_DGRAM
;
275 union sockaddr_union us
;
276 socklen_t uslen
= sizeof(us
);
277 bool needbind
= false;
278 bool opt_unlink_close
= false;
281 Error2("%s: wrong number of parameters (%d instead of 1)",
287 xfd
->para
.socket
.un
.tight
= true;
288 retropt_socket_pf(opts
, &pf
);
289 xfd
->howtoend
= END_SHUTDOWN
;
290 applyopts_offset(xfd
, opts
);
292 xfd
->salen
= xiosetunix(pf
, &xfd
->peersa
.un
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
294 if (!(ABSTRACT
&& abstract
)) {
295 /* only for non abstract because abstract do not work in file system */
296 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
299 xfd
->dtype
= XIODATA_RECVFROM
;
301 if (retropt_bind(opts
, pf
, socktype
, protocol
, &us
.soa
, &uslen
,
302 (abstract
<<1)| xfd
->para
.socket
.un
.tight
, 0, 0) == STAT_OK
) {
306 if (opt_unlink_close
) {
307 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
308 Error1("strdup(\"%s\"): out of memory", name
);
310 xfd
->opt_unlink_close
= true;
313 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return -1;
314 applyopts(-1, opts
, PH_INIT
);
317 _xioopen_dgram_sendto(needbind
?&us
:NULL
, uslen
,
318 opts
, xioflags
, xfd
, groups
,
319 pf
, socktype
, protocol
);
324 int xioopen_unix_recvfrom(int argc
, const char *argv
[], struct opt
*opts
,
325 int xioflags
, xiofile_t
*xxfd
, unsigned groups
,
326 int abstract
, int dummy2
, int dummy3
) {
327 /* we expect the form: filename */
329 xiosingle_t
*xfd
= &xxfd
->stream
;
331 int socktype
= SOCK_DGRAM
;
333 struct sockaddr_un us
;
335 bool needbind
= true;
336 bool opt_unlink_early
= false;
337 bool opt_unlink_close
= true;
340 Error2("%s: wrong number of parameters (%d instead of 1)",
346 xfd
->para
.socket
.un
.tight
= true;
347 retropt_socket_pf(opts
, &pf
);
348 xfd
->howtoend
= END_NONE
;
349 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return STAT_NORETRY
;
350 applyopts(-1, opts
, PH_INIT
);
351 applyopts_named(name
, opts
, PH_EARLY
); /* umask! */
352 applyopts_offset(xfd
, opts
);
354 if (!(ABSTRACT
&& abstract
)) {
355 /* only for non abstract because abstract do not work in file system */
356 retropt_bool(opts
, OPT_UNLINK_EARLY
, &opt_unlink_early
);
357 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
359 applyopts(-1, opts
, PH_EARLY
);
361 uslen
= xiosetunix(pf
, &us
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
364 if (retropt_bind(opts
, pf
, socktype
, protocol
, (struct sockaddr
*)&us
, &uslen
,
365 (abstract
<<1)|xfd
->para
.socket
.un
.tight
, 0, 0) == STAT_OK
) {
369 if (!(ABSTRACT
&& abstract
)) {
370 if (opt_unlink_early
) {
371 if (Unlink(name
) < 0) {
372 if (errno
== ENOENT
) {
373 Warn2("unlink(\"%s\"): %s", name
, strerror(errno
));
375 Error2("unlink(\"%s\"): %s", name
, strerror(errno
));
380 if (Lstat(name
, &buf
) == 0) {
381 Error1("\"%s\" exists", name
);
382 return STAT_RETRYLATER
;
385 if (opt_unlink_close
) {
386 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
387 Error1("strdup(\"%s\"): out of memory", name
);
389 xfd
->opt_unlink_close
= true;
392 /* trying to set user-early, perm-early etc. here is useless because
393 file system entry is available only past bind() call. */
395 applyopts_named(name
, opts
, PH_EARLY
); /* umask! */
397 xfd
->para
.socket
.la
.soa
.sa_family
= pf
;
399 xfd
->dtype
= XIODATA_RECVFROM_ONE
;
403 _xioopen_dgram_recvfrom(xfd
, xioflags
,
404 needbind
?(struct sockaddr
*)&us
:NULL
, uslen
,
405 opts
, pf
, socktype
, protocol
, E_ERROR
);
410 int xioopen_unix_recv(int argc
, const char *argv
[], struct opt
*opts
,
411 int xioflags
, xiofile_t
*xxfd
, unsigned groups
,
412 int abstract
, int dummy2
, int dummy3
) {
413 /* we expect the form: filename */
415 xiosingle_t
*xfd
= &xxfd
->stream
;
417 int socktype
= SOCK_DGRAM
;
419 union sockaddr_union us
;
421 bool opt_unlink_early
= false;
422 bool opt_unlink_close
= true;
426 Error2("%s: wrong number of parameters (%d instead of 1)",
432 xfd
->para
.socket
.un
.tight
= true;
433 retropt_socket_pf(opts
, &pf
);
434 xfd
->howtoend
= END_SHUTDOWN
;
435 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return STAT_NORETRY
;
436 applyopts(-1, opts
, PH_INIT
);
437 applyopts_named(name
, opts
, PH_EARLY
); /* umask! */
438 applyopts_offset(xfd
, opts
);
440 if (!(ABSTRACT
&& abstract
)) {
441 /* only for non abstract because abstract do not work in file system */
442 retropt_bool(opts
, OPT_UNLINK_EARLY
, &opt_unlink_early
);
443 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
445 applyopts(-1, opts
, PH_EARLY
);
447 uslen
= xiosetunix(pf
, &us
.un
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
450 if (retropt_bind(opts
, pf
, socktype
, protocol
, &us
.soa
, &uslen
,
451 (abstract
<<1)|xfd
->para
.socket
.un
.tight
, 0, 0)
456 if (!(ABSTRACT
&& abstract
)) {
457 if (opt_unlink_early
) {
458 if (Unlink(name
) < 0) {
459 if (errno
== ENOENT
) {
460 Warn2("unlink(\"%s\"): %s", name
, strerror(errno
));
462 Error2("unlink(\"%s\"): %s", name
, strerror(errno
));
467 if (Lstat(name
, &buf
) == 0) {
468 Error1("\"%s\" exists", name
);
469 return STAT_RETRYLATER
;
472 if (opt_unlink_close
) {
473 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
474 Error1("strdup(\"%s\"): out of memory", name
);
476 xfd
->opt_unlink_close
= true;
479 applyopts_named(name
, opts
, PH_EARLY
); /* umask! */
481 xfd
->para
.socket
.la
.soa
.sa_family
= pf
;
483 xfd
->dtype
= XIODATA_RECV
;
484 result
= _xioopen_dgram_recv(xfd
, xioflags
, &us
.soa
, uslen
,
485 opts
, pf
, socktype
, protocol
, E_ERROR
);
490 static int xioopen_unix_client(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
, unsigned groups
, int abstract
, int dummy2
, int dummy3
) {
491 /* we expect the form: filename */
493 Error2("%s: wrong number of parameters (%d instead of 1)", argv
[0], argc
-1);
497 _xioopen_unix_client(&xxfd
->stream
, xioflags
, groups
, abstract
, opts
,
501 /* establishes communication with an existing UNIX type socket. supports stream
502 and datagram socket types: first tries to connect(), but when this fails it
503 falls back to sendto().
504 applies and consumes the following option:
505 PH_INIT, PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND,
506 PH_CONNECTED, PH_LATE, ?PH_CONNECT
508 OPT_PROTOCOL_FAMILY, OPT_UNIX_TIGHTSOCKLEN, OPT_UNLINK_CLOSE, OPT_BIND,
509 OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_CLOEXEC, OPT_USER, OPT_GROUP, ?OPT_FORK,
512 _xioopen_unix_client(xiosingle_t
*xfd
, int xioflags
, unsigned groups
,
513 int abstract
, struct opt
*opts
, const char *name
) {
515 int socktype
= 0; /* to be determined by server socket type */
517 union sockaddr_union them
, us
;
518 socklen_t themlen
, uslen
= sizeof(us
);
519 bool needbind
= false;
520 bool opt_unlink_close
= false;
524 xfd
->para
.socket
.un
.tight
= true;
525 retropt_socket_pf(opts
, &pf
);
526 xfd
->howtoend
= END_SHUTDOWN
;
527 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return STAT_NORETRY
;
528 applyopts(-1, opts
, PH_INIT
);
529 applyopts_offset(xfd
, opts
);
530 applyopts(-1, opts
, PH_EARLY
);
532 themlen
= xiosetunix(pf
, &them
.un
, name
, abstract
, xfd
->para
.socket
.un
.tight
);
533 if (!(ABSTRACT
&& abstract
)) {
534 /* only for non abstract because abstract do not work in file system */
535 retropt_bool(opts
, OPT_UNLINK_CLOSE
, &opt_unlink_close
);
537 if (retropt_bind(opts
, pf
, socktype
, protocol
, &us
.soa
, &uslen
,
538 (abstract
<<1)|xfd
->para
.socket
.un
.tight
, 0, 0)
543 if (opt_unlink_close
) {
544 if ((xfd
->unlink_close
= strdup(name
)) == NULL
) {
545 Error1("strdup(\"%s\"): out of memory", name
);
547 xfd
->opt_unlink_close
= true;
550 /* save options, because we might have to start again */
551 opts0
= copyopts(opts
, GROUP_ALL
);
553 /* xfd->dtype = DATA_STREAM; // is default */
556 needbind
?(struct sockaddr
*)&us
:NULL
, uslen
,
557 (struct sockaddr
*)&them
, themlen
,
558 opts
, pf
, socktype
?socktype
:SOCK_STREAM
, protocol
,
560 if (errno
== EPROTOTYPE
) {
562 Unlink(us
.un
.sun_path
);
565 dropopts2(opts
, PH_INIT
, PH_SPEC
); opts
= opts0
;
568 xfd
->salen
= sizeof(struct sockaddr_un
);
570 _xioopen_dgram_sendto(needbind
?&us
:NULL
, uslen
,
571 opts
, xioflags
, xfd
, groups
,
572 pf
, socktype
?socktype
:SOCK_DGRAM
, protocol
))
576 xfd
->dtype
= XIODATA_RECVFROM
;
579 if ((result
= _xio_openlate(xfd
, opts
)) < 0) {
586 /* returns information that can be used for constructing an environment
587 variable describing the socket address.
588 if idx is 0, this function writes "ADDR" into namebuff and the path into
589 valuebuff, and returns 0 (which means that no more info is there).
590 if idx is != 0, it returns -1
591 namelen and valuelen contain the max. allowed length of output chars in the
593 on error this function returns -1.
596 xiosetsockaddrenv_unix(int idx
, char *namebuff
, size_t namelen
,
597 char *valuebuff
, size_t valuelen
,
598 struct sockaddr_un
*sa
, socklen_t salen
, int ipproto
) {
602 strcpy(namebuff
, "ADDR");
603 sockaddr_unix_info(sa
, salen
, valuebuff
, valuelen
);
607 #endif /* WITH_UNIX */