socat/xio-fdnum.c

133 lines
4.1 KiB
C
Raw Normal View History

2008-01-28 21:37:16 +00:00
/* source: xio-fdnum.c */
2008-02-17 13:59:16 +00:00
/* Copyright Gerhard Rieger 2001-2007 */
2008-01-27 12:00:08 +00:00
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for opening addresses of fdnum type */
#include "xiosysincludes.h"
#include "xioopen.h"
#include "xio-fdnum.h"
#if WITH_FDNUM
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
const struct xioaddr_endpoint_desc xioaddr_fdnum1 = { XIOADDR_ENDPOINT, "fd", 1, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_CLOSE, xioopen_fdnum, 0, 0, 0 HELP(":<num>") };
const struct xioaddr_endpoint_desc xioaddr_fdnum2 = { XIOADDR_ENDPOINT, "fd", 2, XIOBIT_RDWR, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_UNSPEC, XIOCLOSE_CLOSE, xioopen_fdnum, 0, 0, 0 HELP(":<numout>:<numin>") };
2008-01-27 12:00:08 +00:00
2008-02-17 13:59:16 +00:00
const union xioaddr_desc *xioaddrs_fdnum[] = {
(union xioaddr_desc *)&xioaddr_fdnum1,
(union xioaddr_desc *)&xioaddr_fdnum2,
NULL };
2008-01-27 12:00:08 +00:00
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xfd, unsigned groups,
int dummy1, int dummy2, int dummy3) {
char *a1;
int rw = (xioflags&XIO_ACCMODE);
2008-02-17 13:59:16 +00:00
int numfd1, numfd2 = -1;
int numrfd, numwfd;
2008-01-27 12:00:08 +00:00
int result;
2008-02-17 13:59:16 +00:00
if (argc < 2 || argc > 3) {
Error3("%s:%s: wrong number of parameters (%d instead of 1 or 2)", argv[0], argv[1], argc-1);
2008-01-27 12:00:08 +00:00
}
2008-02-17 13:59:16 +00:00
numfd1 = strtoul(argv[1], &a1, 0);
2008-01-27 12:00:08 +00:00
if (*a1 != '\0') {
Error1("error in FD number \"%s\"", argv[1]);
}
/* we dont want to see these fds in child processes */
2008-02-17 13:59:16 +00:00
if (Fcntl_l(numfd1, F_SETFD, FD_CLOEXEC) < 0) {
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd1, strerror(errno));
2008-01-27 12:00:08 +00:00
}
2008-02-17 13:59:16 +00:00
if (argv[2]) {
if (rw != XIO_RDWR) {
Warn("two file descriptors given for unidirectional transfer");
}
numwfd = numfd1;
numrfd = strtoul(argv[2], &a1, 0);
2008-02-17 13:59:16 +00:00
if (*a1 != '\0') {
Error1("error in FD number \"%s\"", argv[2]);
}
/* we dont want to see these fds in child processes */
if (Fcntl_l(numrfd, F_SETFD, FD_CLOEXEC) < 0) {
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numrfd, strerror(errno));
}
} else {
if (XIOWITHWR(rw)) {
numwfd = numfd1;
numrfd = -1;
} else {
numrfd = numfd1;
numwfd = -1;
2008-02-17 13:59:16 +00:00
}
}
if (argv[2] == NULL) {
Notice2("using file descriptor %d for %s",
numrfd>=0?numrfd:numwfd, ddirection[rw]);
2008-02-17 13:59:16 +00:00
} else {
Notice4("using file descriptors %d for %s and %d for %s", numrfd, ddirection[((rw+1)&1)-1], numwfd, ddirection[((rw+1)&2)-1]);
2008-02-17 13:59:16 +00:00
}
if ((result = xioopen_fd(opts, rw, xfd, numrfd, numwfd, dummy2, dummy3)) < 0) {
2008-01-27 12:00:08 +00:00
return result;
}
return 0;
}
#endif /* WITH_FDNUM */
#if WITH_FD
/* retrieve and apply options to a standard file descriptor.
Do not set FD_CLOEXEC flag. */
int xioopen_fd(struct opt *opts, int rw, xiofile_t *xfd, int numrfd, int numwfd, int dummy2, int dummy3) {
int fd;
struct stat buf;
2008-02-17 13:59:16 +00:00
if (numwfd >= 0) {
if (Fstat(numwfd, &buf) < 0) {
Warn2("fstat(%d, ): %s", numwfd, strerror(errno));
}
if ((buf.st_mode&S_IFMT) == S_IFSOCK &&
xfd->stream.howtoshut == XIOSHUT_UNSPEC) {
xfd->stream.howtoshut = XIOSHUT_DOWN;
}
}
if (xfd->stream.howtoshut == XIOSHUT_UNSPEC)
xfd->stream.howtoshut = XIOSHUT_CLOSE;
xfd->stream.rfd = numrfd;
xfd->stream.wfd = numwfd;
if (numrfd >= 0) {
fd = numrfd;
2008-02-17 13:59:16 +00:00
} else {
fd = numwfd;
2008-02-17 13:59:16 +00:00
}
2008-01-27 12:00:08 +00:00
#if WITH_TERMIOS
if (Isatty(fd)) {
if (Tcgetattr(fd, &xfd->stream.savetty) < 0) {
2008-01-27 12:00:08 +00:00
Warn2("cannot query current terminal settings on fd %d: %s",
fd, strerror(errno));
2008-01-27 12:00:08 +00:00
} else {
2008-02-17 13:59:16 +00:00
xfd->stream.ttyvalid = true;
2008-01-27 12:00:08 +00:00
}
}
#endif /* WITH_TERMIOS */
2008-02-17 13:59:16 +00:00
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
2008-01-27 12:00:08 +00:00
applyopts(-1, opts, PH_INIT);
applyopts2(fd, opts, PH_INIT, PH_FD);
2008-01-27 12:00:08 +00:00
2008-02-17 13:59:16 +00:00
return _xio_openlate(&xfd->stream, opts);
2008-01-27 12:00:08 +00:00
}
#endif /* WITH_FD */