Version 1.8.0.1
[socat.git] / xio-fdnum.c
blobddba325fb5907ec37908d2d52e6ce6c544efe8cc
1 /* source: xio-fdnum.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 fdnum type */
7 #include "xiosysincludes.h"
8 #include "xioopen.h"
10 #include "xio-listen.h"
12 #include "xio-fdnum.h"
15 #if WITH_FDNUM
17 static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
18 static int xioopen_accept_fd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
21 const struct addrdesc xioaddr_fd = { "FD", 1+XIO_RDWR, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<fdnum>") };
22 #if WITH_LISTEN
23 const struct addrdesc xioaddr_accept_fd = { "ACCEPT-FD", 1+XIO_RDWR, xioopen_accept_fd, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, 0, 0, 0 HELP(":<fdnum>") };
24 #endif /* WITH_LISTEN */
27 /* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
28 static int xioopen_fdnum(
29 int argc,
30 const char *argv[],
31 struct opt *opts,
32 int xioflags,
33 xiofile_t *xfd,
34 const struct addrdesc *addrdesc)
36 char *a1;
37 int rw = (xioflags&XIO_ACCMODE);
38 int numfd;
39 int result;
41 if (argc != 2) {
42 Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
45 numfd = strtoul(argv[1], &a1, 0);
46 if (*a1 != '\0') {
47 Error1("error in FD number \"%s\"", argv[1]);
49 /* we dont want to see these fds in child processes */
50 if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
51 Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
53 Notice2("using file descriptor %d for %s", numfd, ddirection[rw]);
54 if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd)) < 0) {
55 return result;
57 return 0;
60 #if WITH_LISTEN
62 /* Use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
63 static int xioopen_accept_fd(
64 int argc,
65 const char *argv[],
66 struct opt *opts,
67 int xioflags,
68 xiofile_t *xfd,
69 const struct addrdesc *addrdesc)
71 char *a1;
72 int rw = (xioflags&XIO_ACCMODE);
73 int numfd;
74 union sockaddr_union us;
75 socklen_t uslen = sizeof(union sockaddr_union);
76 int result;
78 if (argc != 2) {
79 xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
80 return STAT_NORETRY;
83 numfd = strtoul(argv[1], &a1, 0);
84 if (*a1 != '\0') {
85 Error1("error in FD number \"%s\"", argv[1]);
87 /* we dont want to see these fds in child processes */
88 if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
89 Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
92 if (Getsockname(numfd, (struct sockaddr *)&us, &uslen) < 0) {
93 Warn2("getsockname(fd=%d, ...): %s", numfd, strerror(errno));
95 Notice2("using file descriptor %d accepting a connection for %s", numfd, ddirection[rw]);
96 xfd->stream.fd = numfd;
97 if ((result = _xioopen_accept_fd(&xfd->stream, xioflags, (struct sockaddr *)&us, uslen, opts, us.soa.sa_family, 0, 0)) < 0) {
98 return result;
100 return 0;
103 #endif /* WITH_LISTEN */
104 #endif /* WITH_FDNUM */
107 #if WITH_FD
109 /* Retrieves and apply options to a standard file descriptor.
110 Does not set FD_CLOEXEC flag. */
111 int xioopen_fd(struct opt *opts, int rw, struct single *sfd, int numfd) {
113 sfd->fd = numfd;
114 if (sfd->howtoend == END_UNSPEC)
115 sfd->howtoend = END_NONE;
117 #if WITH_TERMIOS
118 if (Isatty(sfd->fd)) {
119 if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
120 Warn2("cannot query current terminal settings on fd %d: %s",
121 sfd->fd, strerror(errno));
122 } else {
123 sfd->ttyvalid = true;
126 #endif /* WITH_TERMIOS */
127 if (applyopts_single(sfd, opts, PH_INIT) < 0)
128 return -1;
130 applyopts2(sfd, -1, opts, PH_INIT, PH_FD);
132 return _xio_openlate(sfd, opts);
135 #endif /* WITH_FD */