mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 07:22:34 +00:00
Internal: Reworked xioopts
This commit is contained in:
parent
1c1a91027a
commit
5eebca3a5b
37 changed files with 1380 additions and 1199 deletions
5
test.sh
5
test.sh
|
@ -17093,11 +17093,12 @@ tf="$td/test$N.stdout"
|
|||
te="$td/test$N.stderr"
|
||||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"
|
||||
CMD0="$TRACE $SOCAT $opts -T 1 PIPE EXEC:cat,setsid,sigint"
|
||||
CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"$CAT\",pty,setsid,sigint"
|
||||
printf "test $F_n $TEST... " $N
|
||||
$CMD0 >/dev/null 2>"${te}0" &
|
||||
pid0=$!
|
||||
relsleep 2
|
||||
#echo "pid0=$pid0" >&2 #!!!
|
||||
sleep 1
|
||||
kill -INT $pid0
|
||||
wait
|
||||
if grep -q " W waitpid..: child .* exited with status 130" "${te}0" ||
|
||||
|
|
19
xio-creat.c
19
xio-creat.c
|
@ -37,7 +37,8 @@ static int _xioopen_creat(const char *path, int rw, struct opt *opts) {
|
|||
}
|
||||
|
||||
|
||||
static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *filename = argv[1];
|
||||
int rw = (xioflags&XIO_ACCMODE);
|
||||
bool exists;
|
||||
|
@ -45,32 +46,32 @@ static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xio
|
|||
int result;
|
||||
|
||||
/* remove old file, or set user/permissions on old file; parse options */
|
||||
if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) {
|
||||
if ((result = _xioopen_named_early(argc, argv, xxfd, groups, &exists, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
|
||||
if ((result = _xioopen_creat(filename, rw, opts)) < 0)
|
||||
return result;
|
||||
fd->stream.fd = result;
|
||||
sfd->fd = result;
|
||||
|
||||
applyopts_named(filename, opts, PH_PASTOPEN);
|
||||
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTOPEN, PH_LATE2)) < 0)
|
||||
if ((result = applyopts2(sfd, -1, opts, PH_PASTOPEN, PH_LATE2)) < 0)
|
||||
return result;
|
||||
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
applyopts_fchown(fd->stream.fd, opts);
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
|
||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
|
|
11
xio-exec.c
11
xio-exec.c
|
@ -26,13 +26,15 @@ const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREE
|
|||
|
||||
static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
|
||||
xiofile_t *fd,
|
||||
xiofile_t *xfd,
|
||||
groups_t groups,
|
||||
int dummy1, int dummy2, int dummy3
|
||||
) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
int status;
|
||||
bool dash = false;
|
||||
int duptostderr;
|
||||
int numleft;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
|
@ -40,8 +42,9 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
retropt_bool(opts, OPT_DASH, &dash);
|
||||
|
||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr);
|
||||
if (status < 0) return status;
|
||||
status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status == 0) { /* child */
|
||||
const char *ends[] = { " ", NULL };
|
||||
const char *hquotes[] = { "'", NULL };
|
||||
|
@ -61,7 +64,6 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||
char *tokp;
|
||||
char *path = NULL;
|
||||
char *tmp;
|
||||
int numleft;
|
||||
|
||||
/*! Close(something) */
|
||||
/* parse command line */
|
||||
|
@ -143,6 +145,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
/* parent */
|
||||
_xio_openlate(sfd, opts);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_EXEC */
|
||||
|
|
|
@ -120,10 +120,10 @@ int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2
|
|||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
|
||||
applyopts2(xfd->fd, opts, PH_INIT, PH_FD);
|
||||
applyopts2(xfd, -1, opts, PH_INIT, PH_FD);
|
||||
|
||||
return _xio_openlate(xfd, opts);
|
||||
}
|
||||
|
|
27
xio-file.c
27
xio-file.c
|
@ -72,50 +72,51 @@ const struct addrdesc xioaddr_open = { "OPEN", 3, xioopen_open, GROUP_FD|GRO
|
|||
if the filesystem entry already exists, the data is appended
|
||||
if it does not exist, a file is created and the data is appended
|
||||
*/
|
||||
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
const char *filename = argv[1];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
struct single *sfd = &xfd->stream;
|
||||
bool exists;
|
||||
bool opt_unlink_close = false;
|
||||
int result;
|
||||
|
||||
/* remove old file, or set user/permissions on old file; parse options */
|
||||
if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) {
|
||||
if ((result = _xioopen_named_early(argc, argv, xfd, groups, &exists, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice3("opening %s \"%s\" for %s",
|
||||
filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
|
||||
if ((result = _xioopen_open(filename, rw, opts)) < 0)
|
||||
return result;
|
||||
fd->stream.fd = result;
|
||||
sfd->fd = result;
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (Isatty(fd->stream.fd)) {
|
||||
if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
|
||||
if (Isatty(sfd->fd)) {
|
||||
if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
|
||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||
fd->stream.fd, strerror(errno));
|
||||
sfd->fd, strerror(errno));
|
||||
} else {
|
||||
fd->stream.ttyvalid = true;
|
||||
sfd->ttyvalid = true;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
|
||||
applyopts_named(filename, opts, PH_FD);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
applyopts_fchown(fd->stream.fd, opts);
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
|
||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
|
|
33
xio-gopen.c
33
xio-gopen.c
|
@ -19,7 +19,8 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
|
||||
const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
|
||||
|
||||
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *filename = argv[1];
|
||||
flags_t openflags = (xioflags & XIO_ACCMODE);
|
||||
mode_t st_mode;
|
||||
|
@ -28,7 +29,7 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
int result;
|
||||
|
||||
if ((result =
|
||||
_xioopen_named_early(argc, argv, fd, GROUP_NAMED|groups, &exists, opts)) < 0) {
|
||||
_xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|groups, &exists, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
st_mode = result;
|
||||
|
@ -52,15 +53,15 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
Info1("\"%s\" is a socket, connecting to it", filename);
|
||||
|
||||
result =
|
||||
_xioopen_unix_client(&fd->stream, xioflags, groups, 0, opts, filename);
|
||||
_xioopen_unix_client(sfd, xioflags, groups, 0, opts, filename);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
||||
|
||||
if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||
fd->stream.fd, &us, uslen, strerror(errno));
|
||||
sfd->fd, &us, uslen, strerror(errno));
|
||||
} else {
|
||||
Notice1("successfully connected via %s",
|
||||
sockaddr_unix_info(&us.un, uslen,
|
||||
|
@ -78,10 +79,10 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(filename)) == NULL) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice3("opening %s \"%s\" for %s",
|
||||
|
@ -95,27 +96,27 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
|||
Ioctl(result, I_PUSH, "ttcompat"); /* ... AdressSanitizer */
|
||||
}
|
||||
#endif
|
||||
fd->stream.fd = result;
|
||||
sfd->fd = result;
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (Isatty(fd->stream.fd)) {
|
||||
if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
|
||||
if (Isatty(sfd->fd)) {
|
||||
if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
|
||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||
fd->stream.fd, strerror(errno));
|
||||
sfd->fd, strerror(errno));
|
||||
} else {
|
||||
fd->stream.ttyvalid = true;
|
||||
sfd->ttyvalid = true;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
applyopts_named(filename, opts, PH_FD);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
}
|
||||
|
||||
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
|
||||
if ((result = applyopts2(sfd, -1, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
|
||||
return result;
|
||||
|
||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ int _xioopen_interface(const char *ifname,
|
|||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
xfd->salen = sizeof(xfd->peersa);
|
||||
if (pf == PF_UNSPEC) {
|
||||
|
|
2
xio-ip.c
2
xio-ip.c
|
@ -69,7 +69,7 @@ const struct optdesc opt_ip_multicast_if ={"ip-multicast-if", "multicast-if",
|
|||
const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS };
|
||||
#endif
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IP, IP_ADD_MEMBERSHIP };
|
||||
const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SPEC, SOL_IP, IP_ADD_MEMBERSHIP };
|
||||
#endif
|
||||
#if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
const struct optdesc opt_ip_add_source_membership = { "ip-add-source-membership", "source-membership",OPT_IP_ADD_SOURCE_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQ_SOURCE, OFUNC_SOCKOPT, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP };
|
||||
|
|
|
@ -48,7 +48,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
|
@ -216,7 +216,7 @@ int
|
|||
}
|
||||
}
|
||||
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(NULL, -1, opts, PH_EARLY);
|
||||
|
||||
/* 3 means: IP address AND port accepted */
|
||||
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family,
|
||||
|
@ -306,6 +306,7 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
int xioflags, xiofile_t *xfd,
|
||||
groups_t groups, int socktype,
|
||||
int ipproto, int pf) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
struct opt *opts0 = NULL;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
socklen_t uslen = sizeof(us_sa);
|
||||
|
@ -333,8 +334,8 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
|||
xfd->stream.howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
|
||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, argv[1], &pf, ipproto,
|
||||
xfd->stream.para.socket.ip.ai_flags,
|
||||
|
|
25
xio-listen.c
25
xio-listen.c
|
@ -113,16 +113,16 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd, -1, opts, PH_PASTSOCKET);
|
||||
|
||||
applyopts_offset(xfd, opts);
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
/* Phase prebind */
|
||||
xiosock_reuseaddr(xfd->fd, proto, opts);
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd, -1, opts, PH_PREBIND);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
applyopts(xfd, -1, opts, PH_BIND);
|
||||
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
||||
Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd,
|
||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||
|
@ -136,28 +136,27 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
|||
if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') {
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
|
||||
} else {
|
||||
applyopts(xfd->fd, opts, PH_FD);
|
||||
applyopts(xfd, -1, opts, PH_FD);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
applyopts(xfd, -1, opts, PH_PASTBIND);
|
||||
#if WITH_UNIX
|
||||
if (us->sa_family == AF_UNIX) {
|
||||
if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') {
|
||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
|
||||
} else {
|
||||
applyopts(xfd->fd, opts, PH_EARLY);
|
||||
applyopts(xfd->fd, opts, PH_PREOPEN);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_PREOPEN);
|
||||
}
|
||||
}
|
||||
#endif /* WITH_UNIX */
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PRELISTEN);
|
||||
applyopts(xfd, -1, opts, PH_PRELISTEN);
|
||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||
applyopts(xfd->fd, opts, PH_LISTEN);
|
||||
applyopts(xfd, -1, opts, PH_LISTEN);
|
||||
if (Listen(xfd->fd, backlog) < 0) {
|
||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
|
@ -419,9 +418,9 @@ int _xioopen_accept_fd(
|
|||
}
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_FD);
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts(xfd, -1, opts, PH_FD);
|
||||
applyopts(xfd, -1, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd, -1, opts, PH_CONNECTED);
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
|
|||
groups_t groups, bool *exists, struct opt *opts)
|
||||
{
|
||||
const char *path = argv[1];
|
||||
struct single *sfd = &xfd->stream;
|
||||
#if HAVE_STAT64
|
||||
struct stat64 statbuf;
|
||||
#else
|
||||
|
@ -127,8 +128,9 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
|
|||
*exists = true;
|
||||
}
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
if (*exists && opt_unlink_early) {
|
||||
|
@ -141,7 +143,7 @@ int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd,
|
|||
}
|
||||
|
||||
applyopts_named(path, opts, PH_EARLY);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
if (*exists) {
|
||||
applyopts_named(path, opts, PH_PREOPEN);
|
||||
} else {
|
||||
|
|
|
@ -240,6 +240,7 @@ static int
|
|||
addr_openssl */
|
||||
{
|
||||
struct single *xfd = &xxfd->stream;
|
||||
struct single *sfd = xfd;
|
||||
struct opt *opts0 = NULL;
|
||||
const char *hostname, *portname;
|
||||
int pf = PF_UNSPEC;
|
||||
|
@ -284,7 +285,7 @@ static int
|
|||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
||||
|
@ -561,6 +562,7 @@ static int
|
|||
addr_openssl */
|
||||
{
|
||||
struct single *xfd = &xxfd->stream;
|
||||
struct single *sfd = xfd;
|
||||
const char *portname;
|
||||
struct opt *opts0 = NULL;
|
||||
union sockaddr_union us_sa, *us = &us_sa;
|
||||
|
@ -604,7 +606,7 @@ static int
|
|||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
||||
if (opt_cert == NULL) {
|
||||
|
@ -613,7 +615,7 @@ static int
|
|||
|
||||
retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
|
||||
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
|
||||
result =
|
||||
_xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx, &use_dtls);
|
||||
|
|
54
xio-pipe.c
54
xio-pipe.c
|
@ -24,13 +24,14 @@ const struct addrdesc xioaddr_pipe = { "PIPE", 3, xioopen_fifo, GROUP_FD|GR
|
|||
/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
|
||||
options */
|
||||
static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||
struct single *sfd = &sock->stream;
|
||||
struct opt *opts2;
|
||||
int filedes[2];
|
||||
int numleft;
|
||||
int result;
|
||||
|
||||
if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
if (Pipe(filedes) != 0) {
|
||||
Error2("pipe(%p): %s", filedes, strerror(errno));
|
||||
|
@ -39,15 +40,15 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
|||
/*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
|
||||
|
||||
sock->common.tag = XIO_TAG_RDWR;
|
||||
sock->stream.dtype = XIODATA_PIPE;
|
||||
sock->stream.fd = filedes[0];
|
||||
sock->stream.para.bipipe.fdout = filedes[1];
|
||||
sock->stream.para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */
|
||||
applyopts_cloexec(sock->stream.fd, opts);
|
||||
applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
|
||||
sfd->dtype = XIODATA_PIPE;
|
||||
sfd->fd = filedes[0];
|
||||
sfd->para.bipipe.fdout = filedes[1];
|
||||
sfd->para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
applyopts_cloexec(sfd->para.bipipe.fdout, opts);
|
||||
|
||||
/* one-time and input-direction options, no second application */
|
||||
retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
|
||||
retropt_bool(opts, OPT_IGNOREEOF, &sfd->ignoreeof);
|
||||
|
||||
/* here we copy opts! */
|
||||
if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) {
|
||||
|
@ -55,18 +56,16 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
|||
}
|
||||
|
||||
/* apply options to first FD */
|
||||
if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) {
|
||||
if ((result = applyopts(sfd, -1, opts, PH_ALL)) < 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
|
||||
if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* apply options to second FD */
|
||||
if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (applyopts(&sock->stream, sfd->para.bipipe.fdout, opts2, PH_ALL) < 0)
|
||||
return -1;
|
||||
|
||||
if ((numleft = leftopts(opts)) > 0) {
|
||||
showleft(opts);
|
||||
|
@ -78,7 +77,8 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
|||
|
||||
|
||||
/* open a named or unnamed pipe/fifo */
|
||||
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
const char *pipename = argv[1];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
#if HAVE_STAT64
|
||||
|
@ -92,19 +92,20 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
|
|||
int result;
|
||||
|
||||
if (argc == 1) {
|
||||
return xioopen_fifo_unnamed(fd, fd->stream.opts);
|
||||
return xioopen_fifo_unnamed(xfd, sfd->opts);
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
applyopts_named(pipename, opts, PH_EARLY); /* umask! */
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
|
||||
if (opt_unlink_early) {
|
||||
if (Unlink(pipename) < 0) {
|
||||
|
@ -149,10 +150,10 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
|
|||
|
||||
}
|
||||
if (opt_unlink_close) {
|
||||
if ((fd->stream.unlink_close = strdup(pipename)) == NULL) {
|
||||
if ((sfd->unlink_close = strdup(pipename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", pipename);
|
||||
}
|
||||
fd->stream.opt_unlink_close = true;
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
} else {
|
||||
/* exists */
|
||||
|
@ -160,19 +161,18 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
|
|||
Notice3("opening %s \"%s\" for %s",
|
||||
filetypenames[(pipstat.st_mode&S_IFMT)>>12],
|
||||
pipename, ddirection[rw]);
|
||||
/*applyopts_early(pipename, opts);*/
|
||||
applyopts_named(pipename, opts, PH_EARLY);
|
||||
}
|
||||
|
||||
if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
fd->stream.fd = result;
|
||||
sfd->fd = result;
|
||||
|
||||
applyopts_named(pipename, opts, PH_FD);
|
||||
applyopts(fd->stream.fd, opts, PH_FD);
|
||||
applyopts_cloexec(fd->stream.fd, opts);
|
||||
return _xio_openlate(&fd->stream, opts);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
return _xio_openlate(sfd, opts);
|
||||
}
|
||||
|
||||
#endif /* WITH_PIPE */
|
||||
|
|
|
@ -90,7 +90,7 @@ static int xioopen_posixmq(
|
|||
}
|
||||
applyopts_offset(sfd, opts);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
if ((sfd->para.posixmq.name = strdup(name)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
|
|
219
xio-progcall.c
219
xio-progcall.c
|
@ -47,12 +47,14 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P
|
|||
return<0: error occurred, assume parent process and no child exists !!!
|
||||
*/
|
||||
int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||
struct single *fd,
|
||||
struct single *sfd,
|
||||
groups_t groups,
|
||||
struct opt **copts, /* in: opts; out: opts for child */
|
||||
struct opt **optsp, /* in: opts; out: opts for parent/child */
|
||||
int *duptostderr /* out: redirect stderr to output fd */
|
||||
) {
|
||||
struct opt *popts; /* parent process options */
|
||||
struct opt *opts; /* common options */
|
||||
struct opt *popts; /* parent options */
|
||||
struct opt *copts; /* child options */
|
||||
int numleft;
|
||||
int d, sv[2], rdpip[2], wrpip[2];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
|
@ -78,21 +80,21 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
char *tn = NULL;
|
||||
int trigger[2]; /* [0] watched by parent, [1] closed by child when ready */
|
||||
|
||||
popts = moveopts(*copts, GROUP_ALL);
|
||||
if (applyopts_single(fd, popts, PH_INIT) < 0) return -1;
|
||||
applyopts2(-1, popts, PH_INIT, PH_EARLY);
|
||||
opts = *optsp;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
|
||||
|
||||
retropt_bool(popts, OPT_NOFORK, &nofork);
|
||||
retropt_bool(opts, OPT_NOFORK, &nofork);
|
||||
withfork = !nofork;
|
||||
|
||||
retropt_bool(popts, OPT_PIPES, &usepipes);
|
||||
retropt_bool(opts, OPT_PIPES, &usepipes);
|
||||
#if HAVE_PTY
|
||||
retropt_bool(popts, OPT_PTY, &usebestpty);
|
||||
retropt_bool(opts, OPT_PTY, &usebestpty);
|
||||
#if HAVE_OPENPTY
|
||||
retropt_bool(popts, OPT_OPENPTY, &useopenpty);
|
||||
retropt_bool(opts, OPT_OPENPTY, &useopenpty);
|
||||
#endif
|
||||
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||
retropt_bool(popts, OPT_PTMX, &useptmx);
|
||||
retropt_bool(opts, OPT_PTMX, &useptmx);
|
||||
#endif
|
||||
usepty = (usebestpty
|
||||
#if HAVE_OPENPTY
|
||||
|
@ -108,12 +110,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
#endif /* HAVE_PTY */
|
||||
|
||||
if (retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi) >= 0) {
|
||||
if (retropt_ushort(opts, OPT_FDIN, (unsigned short *)&fdi) >= 0) {
|
||||
if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) {
|
||||
Error("_xioopen_foxec(): option fdin is useless in read-only mode");
|
||||
}
|
||||
}
|
||||
if (retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) {
|
||||
if (retropt_ushort(opts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) {
|
||||
if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) {
|
||||
Error("_xioopen_foxec(): option fdout is useless in write-only mode");
|
||||
}
|
||||
|
@ -125,7 +127,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
/*!! free something */
|
||||
return -1;
|
||||
}
|
||||
fd->flags |= XIO_DOESCHILD;
|
||||
sfd->flags |= XIO_DOESCHILD;
|
||||
|
||||
#if HAVE_PTY
|
||||
Notice2("forking off child, using %s for %s",
|
||||
|
@ -137,7 +139,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
ddirection[rw]);
|
||||
#endif /* HAVE_PTY */
|
||||
}
|
||||
applyopts(-1, popts, PH_PREBIGEN);
|
||||
applyopts(sfd, -1, opts, PH_PREBIGEN);
|
||||
|
||||
if (!withfork) {
|
||||
/*0 struct single *stream1, *stream2;*/
|
||||
|
@ -147,10 +149,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
/*!! free something */
|
||||
return -1;
|
||||
}
|
||||
fd->flags |= XIO_DOESEXEC;
|
||||
sfd->flags |= XIO_DOESEXEC;
|
||||
|
||||
free(*copts);
|
||||
*copts = moveopts(popts, GROUP_ALL);
|
||||
/* Only one process, no parent,child */
|
||||
if ((copts = moveopts(opts, GROUP_ALL)) == NULL) {
|
||||
/*!! free something */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0 /*!! */
|
||||
if (sock1->tag == XIO_TAG_DUAL) {
|
||||
|
@ -207,7 +212,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
/*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
|
||||
}
|
||||
}
|
||||
} else
|
||||
/* !withfork */
|
||||
} else /* withfork */
|
||||
#if HAVE_PTY
|
||||
if (usepty) {
|
||||
|
||||
|
@ -216,7 +222,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
#elif HAVE_DEV_PTC
|
||||
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
||||
#endif
|
||||
fd->dtype = XIODATA_PTY;
|
||||
sfd->dtype = XIODATA_PTY;
|
||||
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||
if (usebestpty || useptmx) {
|
||||
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||
|
@ -264,30 +270,30 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
}
|
||||
#endif /* HAVE_OPENPTY */
|
||||
free(*copts);
|
||||
if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) {
|
||||
/* withfork use_pty */
|
||||
if ((copts = moveopts(opts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
popts = opts;
|
||||
applyopts_cloexec(ptyfd, popts);/*!*/
|
||||
/* exec:...,pty did not kill child process under some circumstances */
|
||||
if (fd->howtoend == END_UNSPEC) {
|
||||
fd->howtoend = END_CLOSE_KILL;
|
||||
if (sfd->howtoend == END_UNSPEC) {
|
||||
sfd->howtoend = END_CLOSE_KILL;
|
||||
}
|
||||
|
||||
/* this for parent, was after fork */
|
||||
applyopts(ptyfd, popts, PH_FD);
|
||||
applyopts(ptyfd, popts, PH_LATE);
|
||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||
applyopts(sfd, ptyfd, popts, PH_FD);
|
||||
sfd->fd = ptyfd;
|
||||
|
||||
fd->fd = ptyfd;
|
||||
|
||||
} else
|
||||
/* end withfork, use_pty */
|
||||
} else /* end withfork, use_pty */
|
||||
#endif /* HAVE_PTY */
|
||||
|
||||
if (usepipes) {
|
||||
struct opt *popts2, *copts2;
|
||||
/* withfork usepipes */
|
||||
|
||||
if (rw == XIO_RDWR)
|
||||
fd->dtype = XIODATA_2PIPE;
|
||||
sfd->dtype = XIODATA_2PIPE;
|
||||
if (rw != XIO_WRONLY) {
|
||||
if (Pipe(rdpip) < 0) {
|
||||
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
||||
|
@ -296,19 +302,18 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
||||
/* rdpip[0]: read by socat; rdpip[1]: write by child */
|
||||
free(*copts);
|
||||
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
|
||||
|
||||
/* withfork usepipes */
|
||||
if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
|
||||
== NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
popts2 = copyopts(popts, GROUP_ALL);
|
||||
copts2 = copyopts(*copts, GROUP_ALL);
|
||||
popts = opts;
|
||||
|
||||
if (rw != XIO_WRONLY) {
|
||||
applyopts_cloexec(rdpip[0], popts);
|
||||
applyopts(rdpip[0], popts, PH_FD);
|
||||
applyopts(rdpip[1], *copts, PH_FD);
|
||||
applyopts(NULL, rdpip[0], popts, PH_FD);
|
||||
applyopts(NULL, rdpip[1], copts, PH_FD);
|
||||
}
|
||||
|
||||
if (rw != XIO_RDONLY) {
|
||||
|
@ -317,65 +322,70 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
||||
|
||||
/* wrpip[1]: write by socat; wrpip[0]: read by child */
|
||||
if (rw != XIO_RDONLY) {
|
||||
applyopts_cloexec(wrpip[1], popts2);
|
||||
applyopts(wrpip[1], popts2, PH_FD);
|
||||
applyopts(wrpip[0], copts2, PH_FD);
|
||||
applyopts_cloexec(wrpip[1], popts);
|
||||
applyopts(NULL, wrpip[1], popts, PH_FD);
|
||||
applyopts(NULL, wrpip[0], copts, PH_FD);
|
||||
}
|
||||
if (fd->howtoend == END_UNSPEC) {
|
||||
fd->howtoend = END_CLOSE_KILL;
|
||||
if (sfd->howtoend == END_UNSPEC) {
|
||||
sfd->howtoend = END_CLOSE_KILL;
|
||||
}
|
||||
|
||||
/* this for parent, was after fork */
|
||||
switch (rw) {
|
||||
case XIO_RDONLY: fd->fd = rdpip[0]; break;
|
||||
case XIO_WRONLY: fd->fd = wrpip[1]; break;
|
||||
case XIO_RDWR: fd->fd = rdpip[0];
|
||||
fd->para.exec.fdout = wrpip[1];
|
||||
case XIO_RDONLY: sfd->fd = rdpip[0]; break;
|
||||
case XIO_WRONLY: sfd->fd = wrpip[1]; break;
|
||||
case XIO_RDWR: sfd->fd = rdpip[0];
|
||||
sfd->para.exec.fdout = wrpip[1];
|
||||
break;
|
||||
}
|
||||
applyopts(fd->fd, popts, PH_FD);
|
||||
applyopts(fd->fd, popts, PH_LATE);
|
||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||
applyopts(sfd, -1, popts, PH_FD);
|
||||
applyopts(sfd, -1, popts, PH_LATE);
|
||||
if (applyopts_single(sfd, popts, PH_LATE) < 0)
|
||||
return -1;
|
||||
|
||||
/* end withfork, use_pipes */
|
||||
} else {
|
||||
/* withfork, socketpair */
|
||||
|
||||
d = AF_UNIX;
|
||||
retropt_int(popts, OPT_PROTOCOL_FAMILY, &d);
|
||||
result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv);
|
||||
retropt_int(opts, OPT_PROTOCOL_FAMILY, &d);
|
||||
result = xiosocketpair(opts, d, SOCK_STREAM, 0, sv);
|
||||
if (result < 0) {
|
||||
return -1;
|
||||
}
|
||||
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
||||
d, type, protocol, sv[0], sv[1]);*/
|
||||
free(*copts);
|
||||
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||
|
||||
/* withfork socketpair */
|
||||
if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
applyopts(sv[0], *copts, PH_PASTSOCKET);
|
||||
applyopts(sv[1], popts, PH_PASTSOCKET);
|
||||
popts = opts;
|
||||
applyopts(NULL, sv[0], copts, PH_PASTSOCKET);
|
||||
applyopts(NULL, sv[1], popts, PH_PASTSOCKET);
|
||||
|
||||
applyopts_cloexec(sv[0], *copts);
|
||||
applyopts(sv[0], *copts, PH_FD);
|
||||
applyopts(sv[1], popts, PH_FD);
|
||||
applyopts_cloexec(sv[0], copts);
|
||||
applyopts(NULL, sv[0], copts, PH_FD);
|
||||
applyopts(NULL, sv[1], popts, PH_FD);
|
||||
|
||||
applyopts(sv[0], *copts, PH_PREBIND);
|
||||
applyopts(sv[0], *copts, PH_BIND);
|
||||
applyopts(sv[0], *copts, PH_PASTBIND);
|
||||
applyopts(sv[1], popts, PH_PREBIND);
|
||||
applyopts(sv[1], popts, PH_BIND);
|
||||
applyopts(sv[1], popts, PH_PASTBIND);
|
||||
applyopts(NULL, sv[0], copts, PH_PREBIND);
|
||||
applyopts(NULL, sv[0], copts, PH_BIND);
|
||||
applyopts(NULL, sv[0], copts, PH_PASTBIND);
|
||||
applyopts(NULL, sv[1], popts, PH_PREBIND);
|
||||
applyopts(NULL, sv[1], popts, PH_BIND);
|
||||
applyopts(NULL, sv[1], popts, PH_PASTBIND);
|
||||
|
||||
if (fd->howtoend == END_UNSPEC) {
|
||||
fd->howtoend = END_SHUTDOWN_KILL;
|
||||
if (sfd->howtoend == END_UNSPEC) {
|
||||
sfd->howtoend = END_SHUTDOWN_KILL;
|
||||
}
|
||||
|
||||
/* this for parent, was after fork */
|
||||
fd->fd = sv[0];
|
||||
applyopts(fd->fd, popts, PH_FD);
|
||||
sfd->fd = sv[0];
|
||||
applyopts(sfd, -1, popts, PH_FD);
|
||||
/* end withfork, socketpair */
|
||||
}
|
||||
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
||||
retropt_bool(copts, OPT_STDERR, &withstderr);
|
||||
|
||||
xiosetchilddied(); /* set SIGCHLD handler */
|
||||
|
||||
|
@ -387,7 +397,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
}
|
||||
if (!withfork || pid == 0) { /* in single process, or in child */
|
||||
applyopts_optgroup(-1, *copts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS);
|
||||
applyopts_optgroup(sfd, -1, copts, GROUP_PROCESS);
|
||||
if (withfork) {
|
||||
Close(trigger[0]); /* in child: not needed here */
|
||||
/* The child should have default handling for SIGCHLD. */
|
||||
|
@ -398,9 +408,9 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
|
||||
#if HAVE_PTY
|
||||
if (usepty) {
|
||||
applyopts_named(tn, *copts, PH_PREOPEN);
|
||||
applyopts_named(tn, *copts, PH_EARLY);
|
||||
applyopts_named(tn, *copts, PH_FD);
|
||||
applyopts_named(tn, copts, PH_PREOPEN);
|
||||
applyopts_named(tn, copts, PH_EARLY);
|
||||
applyopts_named(tn, copts, PH_FD);
|
||||
|
||||
if (ttyfd < 0) {
|
||||
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||
|
@ -427,7 +437,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
#endif
|
||||
|
||||
/* this for child, was after fork */
|
||||
applyopts(ttyfd, *copts, PH_FD);
|
||||
applyopts(NULL, ttyfd, copts, PH_FD);
|
||||
|
||||
Info1("opened pseudo terminal %s", tn);
|
||||
Close(ptyfd);
|
||||
|
@ -451,11 +461,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
if ((rw == XIO_RDONLY || fdi != ttyfd) &&
|
||||
(rw == XIO_WRONLY || fdo != ttyfd)) {
|
||||
applyopts_cloexec(ttyfd, *copts);
|
||||
applyopts_cloexec(ttyfd, copts);
|
||||
}
|
||||
|
||||
applyopts(ttyfd, *copts, PH_LATE);
|
||||
applyopts(ttyfd, *copts, PH_LATE2);
|
||||
applyopts(NULL, ttyfd, copts, PH_LATE);
|
||||
applyopts(NULL, ttyfd, copts, PH_LATE2);
|
||||
} else
|
||||
#endif /* HAVE_PTY */
|
||||
if (usepipes) {
|
||||
|
@ -492,8 +502,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
return -1;
|
||||
}
|
||||
Close(rdpip[1]);
|
||||
/*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
|
||||
/*0 applyopts_cloexec(fdo, *copts);*/
|
||||
}
|
||||
if (rw != XIO_RDONLY && wrpip[0] != fdi) {
|
||||
/* make sure that the internal diagnostic socket pair fds do not conflict
|
||||
|
@ -504,15 +512,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
return -1;
|
||||
}
|
||||
Close(wrpip[0]);
|
||||
/*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
|
||||
/*0 applyopts_cloexec(wrpip[0], *copts);*/ /* option is already consumed! */
|
||||
/* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */
|
||||
}
|
||||
|
||||
applyopts(fdi, *copts, PH_LATE);
|
||||
applyopts(fdo, *copts, PH_LATE);
|
||||
applyopts(fdi, *copts, PH_LATE2);
|
||||
applyopts(fdo, *copts, PH_LATE2);
|
||||
applyopts(NULL, fdi, copts, PH_LATE);
|
||||
applyopts(NULL, fdo, copts, PH_LATE);
|
||||
applyopts(NULL, fdi, copts, PH_LATE2);
|
||||
applyopts(NULL, fdo, copts, PH_LATE2);
|
||||
|
||||
} else { /* socketpair */
|
||||
Close(sv[0]);
|
||||
|
@ -535,12 +541,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
/*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
|
||||
}
|
||||
if (fdi != sv[1] && fdo != sv[1]) {
|
||||
applyopts_cloexec(sv[1], *copts);
|
||||
applyopts_cloexec(sv[1], copts);
|
||||
Close(sv[1]);
|
||||
}
|
||||
|
||||
applyopts(fdi, *copts, PH_LATE);
|
||||
applyopts(fdi, *copts, PH_LATE2);
|
||||
applyopts(NULL, fdi, copts, PH_LATE);
|
||||
applyopts(NULL, fdi, copts, PH_LATE2);
|
||||
}
|
||||
if (withfork) {
|
||||
Info("notifying parent that child process is ready");
|
||||
|
@ -548,8 +554,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
}
|
||||
} /* withfork */
|
||||
else {
|
||||
applyopts(-1, *copts, PH_LATE);
|
||||
applyopts(-1, *copts, PH_LATE2);
|
||||
applyopts(NULL, -1, copts, PH_LATE);
|
||||
applyopts(NULL, -1, copts, PH_LATE2);
|
||||
}
|
||||
_xioopen_setdelayeduser();
|
||||
if (withstderr) {
|
||||
|
@ -558,6 +564,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
*duptostderr = -1;
|
||||
}
|
||||
|
||||
*optsp = copts;
|
||||
return 0; /* indicate child process */
|
||||
}
|
||||
|
||||
|
@ -565,12 +572,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
Notice1("forked off child process "F_pid, pid);
|
||||
Close(trigger[1]); /* in parent */
|
||||
|
||||
#if 0
|
||||
if ((popts = copyopts(*copts,
|
||||
GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL)
|
||||
return STAT_RETRYLATER;
|
||||
#endif
|
||||
|
||||
#if HAVE_PTY
|
||||
if (usepty) {
|
||||
# if 0
|
||||
|
@ -586,13 +587,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
} else {
|
||||
Close(sv[1]);
|
||||
}
|
||||
fd->para.exec.pid = pid;
|
||||
sfd->para.exec.pid = pid;
|
||||
|
||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||
applyopts_signal(fd, popts);
|
||||
applyopts(-1, popts, PH_LATE);
|
||||
applyopts(-1, popts, PH_LATE2);
|
||||
applyopts(-1, popts, PH_PASTEXEC);
|
||||
if (applyopts_single(sfd, popts, PH_LATE) < 0) return -1;
|
||||
applyopts(sfd, -1, popts, PH_LATE);
|
||||
applyopts(sfd, -1, popts, PH_LATE2);
|
||||
applyopts(sfd, -1, popts, PH_PASTEXEC);
|
||||
if ((numleft = leftopts(popts)) > 0) {
|
||||
showleft(popts);
|
||||
Error1("INTERNAL: %d option(s) remained unused", numleft);
|
||||
|
@ -607,6 +607,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
|||
Info("child process notified parent that it is ready");
|
||||
}
|
||||
|
||||
applyopts(sfd, ptyfd, popts, PH_LATE);
|
||||
if (applyopts_single(sfd, popts, PH_LATE) < 0)
|
||||
return -1;
|
||||
|
||||
*optsp = popts;
|
||||
return pid; /* indicate parent (main) process */
|
||||
}
|
||||
#endif /* WITH_EXEC || WITH_SYSTEM */
|
||||
|
|
|
@ -114,7 +114,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, 1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
|
@ -203,6 +203,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
|||
return result;
|
||||
}
|
||||
}
|
||||
xiofreeaddrinfo(themlist);
|
||||
applyopts(xfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||
return result;
|
||||
|
|
28
xio-pty.c
28
xio-pty.c
|
@ -30,6 +30,7 @@ const struct optdesc opt_pty_intervall = { "pty-interval", NULL, OPT_P
|
|||
|
||||
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
/* we expect the form: filename */
|
||||
struct single *sfd = &xfd->stream;
|
||||
int ptyfd = -1, ttyfd = -1;
|
||||
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||
bool useptmx = false; /* use /dev/ptmx or equivalent */
|
||||
|
@ -51,10 +52,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
xfd->stream.howtoend = END_CLOSE;
|
||||
sfd->howtoend = END_CLOSE;
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
|
||||
|
@ -88,10 +89,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv);
|
||||
#endif /* HAVE_POLL */
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts2(-1, opts, PH_INIT, PH_EARLY);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY);
|
||||
|
||||
applyopts(-1, opts, PH_PREBIGEN);
|
||||
applyopts(sfd, -1, opts, PH_PREBIGEN);
|
||||
|
||||
#if defined(HAVE_DEV_PTMX)
|
||||
# define PTMX "/dev/ptmx" /* Linux */
|
||||
|
@ -155,10 +156,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
ptyname, linkname, strerror(errno));
|
||||
}
|
||||
if (opt_unlink_close) {
|
||||
if ((xfd->stream.unlink_close = strdup(linkname)) == NULL) {
|
||||
if ((sfd->unlink_close = strdup(linkname)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", linkname);
|
||||
}
|
||||
xfd->stream.opt_unlink_close = true;
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,9 +167,9 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
applyopts_named(ptyname, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(ptyfd, opts);/*!*/
|
||||
xfd->stream.dtype = XIODATA_PTY;
|
||||
sfd->dtype = XIODATA_PTY;
|
||||
|
||||
applyopts(ptyfd, opts, PH_FD);
|
||||
applyopts(sfd, ptyfd, opts, PH_FD);
|
||||
|
||||
{
|
||||
/* special handling of user-late etc.; with standard behaviour (up to
|
||||
|
@ -196,9 +197,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
|
||||
}
|
||||
|
||||
xfd->stream.fd = ptyfd;
|
||||
applyopts(ptyfd, opts, PH_LATE);
|
||||
if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1;
|
||||
sfd->fd = ptyfd;
|
||||
applyopts(sfd, -1, opts, PH_LATE);
|
||||
if (applyopts_single(sfd, opts, PH_LATE) < 0)
|
||||
return -1;
|
||||
|
||||
#if HAVE_POLL
|
||||
/* if you can and wish: */
|
||||
|
|
|
@ -118,7 +118,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
|||
retropt_int(opts, OPT_PROTOCOL_FAMILY, pf);
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
xfd->salen = sizeof(xfd->peersa);
|
||||
if ((result =
|
||||
|
|
|
@ -40,6 +40,7 @@ const struct optdesc opt_noecho = { "noecho", NULL, OPT_NOECHO,
|
|||
static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xfd, groups_t groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
char msgbuf[256], *cp = msgbuf;
|
||||
bool noprompt = false;
|
||||
|
@ -85,10 +86,10 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
applyopts2(xfd->stream.fd, opts, PH_INIT, PH_FD);
|
||||
applyopts2(sfd, -1, opts, PH_INIT, PH_FD);
|
||||
|
||||
Using_history();
|
||||
applyopts_offset(&xfd->stream, opts);
|
||||
|
|
200
xio-socket.c
200
xio-socket.c
|
@ -219,7 +219,7 @@ static
|
|||
int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, groups_t groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *protname = argv[2];
|
||||
const char *address = argv[3];
|
||||
|
@ -251,11 +251,12 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
|
||||
themsize = 0;
|
||||
if ((result =
|
||||
|
@ -272,24 +273,24 @@ int xioopen_socket_connect(int argc, const char *argv[], struct opt *opts,
|
|||
#endif
|
||||
sizeof(them.soa.sa_family);
|
||||
|
||||
xfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
|
||||
sfd->dtype = XIOREAD_STREAM|XIOWRITE_STREAM;
|
||||
|
||||
socket_init(0, &us);
|
||||
if (retropt_bind(opts, 0 /*pf*/, socktype, proto, (struct sockaddr *)&us, &uslen, 3,
|
||||
xfd->para.socket.ip.ai_flags)
|
||||
sfd->para.socket.ip.ai_flags)
|
||||
!= STAT_NOACTION) {
|
||||
needbind = true;
|
||||
us.soa.sa_family = pf;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
xioopen_connect(xfd,
|
||||
xioopen_connect(sfd,
|
||||
needbind?&us:NULL, uslen,
|
||||
(struct sockaddr *)&them, themlen,
|
||||
opts, pf, socktype, proto, false)) != 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return STAT_OK;
|
||||
|
@ -300,7 +301,7 @@ static
|
|||
int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, xiofile_t *xxfd, groups_t groups,
|
||||
int dummy1, int dummy2, int dummy3) {
|
||||
struct single *xfd = &xxfd->stream;
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *pfname = argv[1];
|
||||
const char *protname = argv[2];
|
||||
const char *usname = argv[3];
|
||||
|
@ -331,7 +332,7 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
socket_init(0, &us);
|
||||
ussize = 0;
|
||||
|
@ -349,14 +350,15 @@ int xioopen_socket_listen(int argc, const char *argv[], struct opt *opts,
|
|||
;
|
||||
us.soa.sa_family = pf;
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_EARLY);
|
||||
|
||||
opts0 = copyopts(opts, GROUP_ALL);
|
||||
|
||||
if ((result =
|
||||
xioopen_listen(xfd, xioflags,
|
||||
xioopen_listen(sfd, xioflags,
|
||||
&us.soa, uslen,
|
||||
opts, opts0, 0/*instead of pf*/, socktype, proto))
|
||||
!= STAT_OK)
|
||||
|
@ -392,7 +394,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
|
|||
const char *protname, const char *address,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
groups_t groups) {
|
||||
xiosingle_t *xfd = &xxfd->stream;
|
||||
xiosingle_t *sfd = &xxfd->stream;
|
||||
char *garbage;
|
||||
union sockaddr_union us = {{0}};
|
||||
socklen_t uslen = 0; size_t ussize;
|
||||
|
@ -422,37 +424,37 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
/*retropt_int(opts, OPT_IP_PROTOCOL, &proto);*/
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
xfd->peersa.soa.sa_family = pf;
|
||||
sfd->peersa.soa.sa_family = pf;
|
||||
themsize = 0;
|
||||
if ((result =
|
||||
dalan(address, (uint8_t *)&xfd->peersa.soa.sa_data, &themsize,
|
||||
sizeof(xfd->peersa), 'i'))
|
||||
dalan(address, (uint8_t *)&sfd->peersa.soa.sa_data, &themsize,
|
||||
sizeof(sfd->peersa), 'i'))
|
||||
< 0) {
|
||||
Error1("data too long: \"%s\"", address);
|
||||
} else if (result > 0) {
|
||||
Error1("syntax error in \"%s\"", address);
|
||||
}
|
||||
xfd->salen = themsize + sizeof(sa_family_t)
|
||||
sfd->salen = themsize + sizeof(sa_family_t)
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
+ sizeof(xfd->peersa.soa.sa_len)
|
||||
+ sizeof(sfd->peersa.soa.sa_len)
|
||||
#endif
|
||||
;
|
||||
#if HAVE_STRUCT_SOCKADDR_SALEN
|
||||
xfd->peersa.soa.sa_len =
|
||||
sizeof(xfd->peersa.soa.sa_len) + sizeof(xfd->peersa.soa.sa_family) +
|
||||
sfd->peersa.soa.sa_len =
|
||||
sizeof(sfd->peersa.soa.sa_len) + sizeof(sfd->peersa.soa.sa_family) +
|
||||
themsize;
|
||||
#endif
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
if (pf == PF_UNSPEC) {
|
||||
pf = xfd->peersa.soa.sa_family;
|
||||
pf = sfd->peersa.soa.sa_family;
|
||||
}
|
||||
|
||||
xfd->dtype = XIODATA_RECVFROM;
|
||||
sfd->dtype = XIODATA_RECVFROM;
|
||||
|
||||
if (retropt_string(opts, OPT_BIND, &bindstring) == 0) {
|
||||
ussize = 0;
|
||||
|
@ -474,7 +476,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
|
|||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups, pf, socktype, proto, 0);
|
||||
opts, xioflags, sfd, groups, pf, socktype, proto, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -773,7 +775,7 @@ int xiogetpacketinfo(struct single *sfd, int fd)
|
|||
Does not fork, does not retry.
|
||||
returns 0 on success.
|
||||
*/
|
||||
int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
||||
int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
|
||||
struct sockaddr *them, size_t themlen,
|
||||
struct opt *opts, int pf, int socktype, int protocol,
|
||||
bool alt, int level) {
|
||||
|
@ -790,40 +792,40 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
}
|
||||
#endif
|
||||
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
|
||||
if ((sfd->fd = xiosocket(opts, pf, socktype, protocol, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
applyopts_offset(xfd, opts);
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd->fd, opts, PH_FD);
|
||||
applyopts_offset(sfd, opts);
|
||||
applyopts(sfd, -1, opts, PH_PASTSOCKET);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_CONNECT);
|
||||
applyopts(sfd, -1, opts, PH_CONNECT);
|
||||
|
||||
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||
fcntl_flags = Fcntl(xfd->fd, F_GETFL);
|
||||
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
|
||||
if (sfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||
sfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||
fcntl_flags = Fcntl(sfd->fd, F_GETFL);
|
||||
Fcntl_l(sfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
|
||||
}
|
||||
|
||||
result = Connect(xfd->fd, them, themlen);
|
||||
result = Connect(sfd->fd, them, themlen);
|
||||
_errno = errno;
|
||||
la.soa.sa_family = them->sa_family; lalen = sizeof(la);
|
||||
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
|
||||
if (Getsockname(sfd->fd, &la.soa, &lalen) < 0) {
|
||||
Msg4(level-1, "getsockname(%d, %p, {%d}): %s",
|
||||
xfd->fd, &la.soa, lalen, strerror(errno));
|
||||
sfd->fd, &la.soa, lalen, strerror(errno));
|
||||
}
|
||||
errno = _errno;
|
||||
if (result < 0) {
|
||||
if (errno == EINPROGRESS) {
|
||||
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||
if (sfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||
sfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||
struct timeval timeout;
|
||||
struct pollfd writefd;
|
||||
int err;
|
||||
|
@ -831,62 +833,62 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
int result;
|
||||
|
||||
Info4("connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
timeout = xfd->para.socket.connect_timeout;
|
||||
writefd.fd = xfd->fd;
|
||||
timeout = sfd->para.socket.connect_timeout;
|
||||
writefd.fd = sfd->fd;
|
||||
writefd.events = (POLLOUT|POLLERR);
|
||||
result = xiopoll(&writefd, 1, &timeout);
|
||||
if (result < 0) {
|
||||
Msg4(level, "xiopoll({%d,POLLOUT|POLLERR},,{"F_tv_sec"."F_tv_usec"): %s",
|
||||
xfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
sfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if (result == 0) {
|
||||
Msg2(level, "connecting to %s: %s",
|
||||
sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
strerror(ETIMEDOUT));
|
||||
Close(xfd->fd);
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if (writefd.revents & POLLERR) {
|
||||
#if 0
|
||||
unsigned char dummy[1];
|
||||
Read(xfd->fd, &dummy, 1); /* get error message */
|
||||
Read(sfd->fd, &dummy, 1); /* get error message */
|
||||
Msg2(level, "connecting to %s: %s",
|
||||
sockaddr_info(them, infobuff, sizeof(infobuff)),
|
||||
strerror(errno));
|
||||
#else
|
||||
Connect(xfd->fd, them, themlen); /* get error message */
|
||||
Connect(sfd->fd, them, themlen); /* get error message */
|
||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
#endif
|
||||
Close(xfd->fd);
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
/* otherwise OK or network error */
|
||||
result = Getsockopt(xfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
|
||||
result = Getsockopt(sfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
|
||||
if (result != 0) {
|
||||
Msg2(level, "getsockopt(%d, SOL_SOCKET, SO_ERROR, ...): %s",
|
||||
xfd->fd, strerror(err));
|
||||
Close(xfd->fd);
|
||||
sfd->fd, strerror(err));
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
Debug2("getsockopt(%d, SOL_SOCKET, SO_ERROR, { %d }) -> 0",
|
||||
xfd->fd, err);
|
||||
sfd->fd, err);
|
||||
if (err != 0) {
|
||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(err));
|
||||
Close(xfd->fd);
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags);
|
||||
Fcntl_l(sfd->fd, F_SETFL, fcntl_flags);
|
||||
} else {
|
||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
}
|
||||
} else if (pf == PF_UNIX) {
|
||||
|
@ -896,21 +898,21 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
*/
|
||||
int _errno = errno;
|
||||
Info4("connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
/* caller must handle this condition */
|
||||
Close(xfd->fd); xfd->fd = -1;
|
||||
Close(sfd->fd); sfd->fd = -1;
|
||||
errno = _errno;
|
||||
return STAT_RETRYLATER;
|
||||
} else {
|
||||
/* try to find details about error, especially from ICMP */
|
||||
xiogetpacketinfo(xfd, xfd->fd);
|
||||
xiogetpacketinfo(sfd, sfd->fd);
|
||||
|
||||
/* continue mainstream */
|
||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||
themlen, strerror(errno));
|
||||
Close(xfd->fd);
|
||||
Close(sfd->fd);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
} else { /* result >= 0 */
|
||||
|
@ -918,14 +920,14 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
|
||||
}
|
||||
|
||||
applyopts_fchown(xfd->fd, opts); /* OPT_USER, OPT_GROUP */
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts_fchown(sfd->fd, opts); /* OPT_USER, OPT_GROUP */
|
||||
applyopts(sfd, -1, opts, PH_CONNECTED);
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||
}
|
||||
#endif
|
||||
applyopts(xfd->fd, opts, PH_LATE);
|
||||
applyopts(sfd, -1, opts, PH_LATE);
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
@ -1043,7 +1045,7 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
|||
int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||
union sockaddr_union *us, socklen_t uslen,
|
||||
struct opt *opts,
|
||||
int xioflags, xiosingle_t *xfd, groups_t groups,
|
||||
int xioflags, xiosingle_t *sfd, groups_t groups,
|
||||
int pf, int socktype, int ipproto, bool alt) {
|
||||
int level = E_ERROR;
|
||||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||
|
@ -1055,39 +1057,39 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
|||
}
|
||||
#endif
|
||||
|
||||
if ((xfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
|
||||
if ((sfd->fd = xiosocket(opts, pf, socktype, ipproto, level)) < 0) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
applyopts_offset(xfd, opts);
|
||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts_single(xfd, opts, PH_FD);
|
||||
applyopts(xfd->fd, opts, PH_FD);
|
||||
applyopts_offset(sfd, opts);
|
||||
applyopts_single(sfd, opts, PH_PASTSOCKET);
|
||||
applyopts(sfd, -1, opts, PH_PASTSOCKET);
|
||||
applyopts_single(sfd, opts, PH_FD);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
if (xiobind(xfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*applyopts(xfd->fd, opts, PH_CONNECT);*/
|
||||
/*applyopts(sfd, -1, opts, PH_CONNECT);*/
|
||||
|
||||
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
|
||||
if (Getsockname(sfd->fd, &la.soa, &lalen) < 0) {
|
||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||
xfd->fd, &la.soa, lalen, strerror(errno));
|
||||
sfd->fd, &la.soa, lalen, strerror(errno));
|
||||
}
|
||||
|
||||
applyopts_fchown(xfd->fd, opts);
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
applyopts(sfd, -1, opts, PH_CONNECTED);
|
||||
#if WITH_UNIX
|
||||
if (pf == PF_UNIX && us != NULL) {
|
||||
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||
}
|
||||
#endif
|
||||
/*0 applyopts(xfd->fd, opts, PH_LATE); */
|
||||
/*0 applyopts(sfd, -1, opts, PH_LATE); */
|
||||
|
||||
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||
/* sfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||
Notice1("successfully prepared local socket %s",
|
||||
sockaddr_info(&la.soa, lalen, infobuff, sizeof(infobuff)));
|
||||
|
||||
|
@ -1150,8 +1152,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd, -1, opts, PH_PASTSOCKET);
|
||||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
|
@ -1160,12 +1161,11 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
return -1;
|
||||
}
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
applyopts(xfd, -1, opts, PH_PASTBIND);
|
||||
|
||||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
|
||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
|
@ -1283,9 +1283,9 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||
/*xiosetsockaddrenv("SOCK", la, lalen, proto);*/
|
||||
xiosetsockaddrenv("PEER", pa, palen, proto);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_FD);
|
||||
applyopts(xfd, -1, opts, PH_FD);
|
||||
|
||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||
applyopts(xfd, -1, opts, PH_CONNECTED);
|
||||
|
||||
xfd->peersa = *(union sockaddr_union *)pa;
|
||||
xfd->salen = palen;
|
||||
|
@ -1357,8 +1357,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(xfd, -1, opts, PH_PASTSOCKET);
|
||||
|
||||
applyopts_cloexec(xfd->fd, opts);
|
||||
|
||||
|
@ -1369,7 +1368,6 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
|||
#if WITH_UNIX
|
||||
if (pf == AF_UNIX && us != NULL) {
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD);
|
||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY);
|
||||
applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
|
@ -2023,7 +2021,7 @@ xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
|
|||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &proto);
|
||||
applyopts(-1, opts, PH_PRESOCKET);
|
||||
applyopts(NULL, -1, opts, PH_PRESOCKET);
|
||||
result = Socket(pf, socktype, proto);
|
||||
if (result < 0) {
|
||||
int _errno = errno;
|
||||
|
@ -2070,8 +2068,8 @@ int xiobind(
|
|||
applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
|
||||
}
|
||||
#endif
|
||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd->fd, opts, PH_BIND);
|
||||
applyopts(xfd, xfd->fd, opts, PH_PREBIND);
|
||||
applyopts(xfd, xfd->fd, opts, PH_BIND);
|
||||
#if WITH_TCP || WITH_UDP
|
||||
if (alt) {
|
||||
union sockaddr_union sin, *sinp;
|
||||
|
@ -2170,7 +2168,7 @@ int xiobind(
|
|||
}
|
||||
#endif
|
||||
|
||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
||||
applyopts(xfd, -1, opts, PH_PASTBIND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ static int xioopen_socketpair(int argc, const char *argv[], struct opt *opts, in
|
|||
const struct addrdesc xioaddr_socketpair = { "SOCKETPAIR", 3, xioopen_socketpair, GROUP_FD|GROUP_SOCKET, 0, 0, 0 HELP(":<filename>") };
|
||||
|
||||
|
||||
/* open a socketpair */
|
||||
/* Open a socketpair */
|
||||
static int xioopen_socketpair(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
|
@ -32,7 +32,7 @@ static int xioopen_socketpair(
|
|||
int dummy2,
|
||||
int dummy3)
|
||||
{
|
||||
struct single *sfd;
|
||||
struct single *sfd = &xfd->stream;
|
||||
struct opt *opts2;
|
||||
int pf = PF_UNIX;
|
||||
int protocol = 0;
|
||||
|
@ -44,10 +44,9 @@ static int xioopen_socketpair(
|
|||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
sfd = &xfd->stream;
|
||||
sfd->para.bipipe.socktype = SOCK_DGRAM;
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
retropt_int(opts, OPT_PROTOCOL_FAMILY, &pf);
|
||||
retropt_int(opts, OPT_SO_TYPE, &sfd->para.bipipe.socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
|
||||
|
@ -78,7 +77,7 @@ static int xioopen_socketpair(
|
|||
}
|
||||
|
||||
/* apply options to first FD */
|
||||
if ((result = applyopts(sfd->fd, opts, PH_ALL)) < 0) {
|
||||
if ((result = applyopts(sfd, -1, opts, PH_ALL)) < 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) {
|
||||
|
@ -86,10 +85,8 @@ static int xioopen_socketpair(
|
|||
}
|
||||
|
||||
/* apply options to second FD */
|
||||
if ((result = applyopts(sfd->para.bipipe.fdout, opts2, PH_ALL)) < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (applyopts(sfd, sfd->para.bipipe.fdout, opts2, PH_ALL) < 0)
|
||||
return -1;
|
||||
|
||||
if ((numleft = leftopts(opts)) > 0) {
|
||||
Error1("%d option(s) could not be used", numleft);
|
||||
|
|
|
@ -76,7 +76,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, 1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
|
@ -180,6 +180,8 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
|||
xiofreeaddrinfo(themlist);
|
||||
return result;
|
||||
}
|
||||
xiofreeaddrinfo(themlist);
|
||||
applyopts(xfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||
return result;
|
||||
|
|
|
@ -539,7 +539,7 @@ static int xioopen_socks5(
|
|||
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_bool(opts, OPT_FORK, &dofork);
|
||||
|
@ -594,7 +594,7 @@ static int xioopen_socks5(
|
|||
}
|
||||
}
|
||||
xiofreeaddrinfo(themlist);
|
||||
applyopts(xfd->fd, opts, PH_ALL);
|
||||
applyopts(xfd, -1, opts, PH_ALL);
|
||||
|
||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||
return result;
|
||||
|
|
12
xio-stdio.c
12
xio-stdio.c
|
@ -89,16 +89,16 @@ int xioopen_stdio_bi(xiofile_t *sock) {
|
|||
sock->dual.stream[1]->opts, PH_INIT)
|
||||
< 0)
|
||||
return -1;
|
||||
applyopts(-1, sock->dual.stream[0]->opts, PH_INIT);
|
||||
applyopts(-1, sock->dual.stream[1]->opts, PH_INIT);
|
||||
if ((result = applyopts(-1, optspr, PH_EARLY)) < 0)
|
||||
applyopts(sock->dual.stream[0], -1, sock->dual.stream[0]->opts, PH_INIT);
|
||||
applyopts(sock->dual.stream[1], -1, sock->dual.stream[1]->opts, PH_INIT);
|
||||
if ((result = applyopts(NULL, -1, optspr, PH_EARLY)) < 0)
|
||||
return result;
|
||||
if ((result = applyopts(-1, optspr, PH_PREOPEN)) < 0)
|
||||
if ((result = applyopts(NULL, -1, optspr, PH_PREOPEN)) < 0)
|
||||
return result;
|
||||
|
||||
/* apply options to first FD */
|
||||
if ((result =
|
||||
applyopts(sock->dual.stream[0]->fd,
|
||||
applyopts(sock->dual.stream[0], -1,
|
||||
sock->dual.stream[0]->opts, PH_ALL))
|
||||
< 0) {
|
||||
return result;
|
||||
|
@ -113,7 +113,7 @@ int xioopen_stdio_bi(xiofile_t *sock) {
|
|||
#endif
|
||||
|
||||
/* apply options to second FD */
|
||||
if ((result = applyopts(sock->dual.stream[1]->fd,
|
||||
if ((result = applyopts(sock->dual.stream[1], -1,
|
||||
sock->dual.stream[1]->opts, PH_ALL)) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -43,18 +43,20 @@ void dummy(void) {
|
|||
if (0) { { ;
|
||||
#endif
|
||||
#ifdef I_POP
|
||||
} else if (opt->desc->func == OFUNC_STREAMS_I_POP_ALL) {
|
||||
case OFUNC_STREAMS_I_POP_ALL:
|
||||
while (Ioctl(fd, I_POP, 0) >= 0) {
|
||||
Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef I_PUSH
|
||||
} else if (opt->desc->func == OFUNC_STREAMS_I_PUSH) {
|
||||
case OFUNC_STREAMS_I_PUSH:
|
||||
if (Ioctl(fd, I_PUSH, opt->value.u_string) < 0) {
|
||||
Warn3("ioctl(%d, I_PUSH, \"%s\"): %s",
|
||||
fd, opt->value.u_string, strerror(errno));
|
||||
return -1;
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if 0
|
||||
} } }
|
||||
|
|
|
@ -25,18 +25,20 @@ const struct addrdesc xioaddr_system = { "SYSTEM", 3, xioopen_system, GROUP_FD|G
|
|||
|
||||
static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
||||
int xioflags, /* XIO_RDONLY etc. */
|
||||
xiofile_t *fd,
|
||||
xiofile_t *xfd,
|
||||
groups_t groups,
|
||||
int dummy1, int dummy2, int dummy3
|
||||
) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
int status;
|
||||
char *path = NULL;
|
||||
int duptostderr;
|
||||
int result;
|
||||
const char *string = argv[1];
|
||||
|
||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr);
|
||||
if (status < 0) return status;
|
||||
status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status == 0) { /* child */
|
||||
int numleft;
|
||||
|
||||
|
@ -72,6 +74,7 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
|||
}
|
||||
|
||||
/* parent */
|
||||
_xio_openlate(sfd, opts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
27
xio-tun.c
27
xio-tun.c
|
@ -46,6 +46,7 @@ static const struct optname xio_route_options[] = {
|
|||
#endif
|
||||
|
||||
static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
char *tundevice = NULL;
|
||||
char *tunname = NULL, *tuntype = NULL;
|
||||
int pf = /*! PF_UNSPEC*/ PF_INET;
|
||||
|
@ -79,10 +80,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
|
||||
/*========================= the tunnel interface =========================*/
|
||||
Notice("creating tunnel network interface");
|
||||
applyopts_optgroup(-1, opts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS);
|
||||
applyopts_optgroup(&xfd->stream, -1, opts, GROUP_PROCESS);
|
||||
if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
|
||||
return result;
|
||||
xfd->stream.fd = result;
|
||||
sfd->fd = result;
|
||||
|
||||
/* prepare configuration of the new network interface */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
@ -113,10 +114,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
}
|
||||
}
|
||||
|
||||
if (Ioctl(xfd->stream.fd, TUNSETIFF, &ifr) < 0) {
|
||||
if (Ioctl(sfd->fd, TUNSETIFF, &ifr) < 0) {
|
||||
Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
|
||||
xfd->stream.fd, ifr.ifr_name, strerror(errno));
|
||||
Close(xfd->stream.fd);
|
||||
sfd->fd, ifr.ifr_name, strerror(errno));
|
||||
Close(sfd->fd);
|
||||
}
|
||||
Notice1("TUN: new device \"%s\"", ifr.ifr_name);
|
||||
|
||||
|
@ -125,7 +126,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
/* we seem to need a socket for manipulating the interface */
|
||||
if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||
sockfd = xfd->stream.fd; /* desparate fallback attempt */
|
||||
sockfd = sfd->fd; /* desparate fallback attempt */
|
||||
}
|
||||
|
||||
/*--------------------- setting interface address and netmask ------------*/
|
||||
|
@ -135,7 +136,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
return STAT_RETRYLATER;
|
||||
}
|
||||
if ((result = xioparsenetwork(ifaddr, pf, &network,
|
||||
xfd->stream.para.socket.ip.ai_flags))
|
||||
sfd->para.socket.ip.ai_flags))
|
||||
!= STAT_OK) {
|
||||
/*! recover */
|
||||
return result;
|
||||
|
@ -157,16 +158,16 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
|||
free(ifaddr);
|
||||
}
|
||||
/*--------------------- setting interface flags --------------------------*/
|
||||
applyopts_single(&xfd->stream, opts, PH_FD);
|
||||
applyopts_single(sfd, opts, PH_FD);
|
||||
|
||||
_xiointerface_apply_iff(sockfd, ifr.ifr_name, xfd->stream.para.interface.iff_opts);
|
||||
_xiointerface_apply_iff(sockfd, ifr.ifr_name, sfd->para.interface.iff_opts);
|
||||
|
||||
applyopts(xfd->stream.fd, opts, PH_FD);
|
||||
applyopts_cloexec(xfd->stream.fd, opts);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
applyopts_fchown(xfd->stream.fd, opts);
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
|
||||
if ((result = _xio_openlate(&xfd->stream, opts)) < 0)
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
|
|
20
xio-udp.c
20
xio-udp.c
|
@ -149,7 +149,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
}
|
||||
doreuseaddr |= (retropt_2integrals(opts, OPT_SO_REUSEADDR,
|
||||
&reuseaddr, ¬null) >= 0);
|
||||
applyopts(sfd->fd, opts, PH_PASTSOCKET);
|
||||
applyopts(sfd, -1, opts, PH_PASTSOCKET);
|
||||
|
||||
/* SO_REUSEADDR handling of UDP sockets is helpful on Solaris */
|
||||
if (doreuseaddr) {
|
||||
|
@ -163,8 +163,8 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
}
|
||||
}
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
applyopts(sfd->fd, opts, PH_PREBIND);
|
||||
applyopts(sfd->fd, opts, PH_BIND);
|
||||
applyopts(sfd, -1, opts, PH_PREBIND);
|
||||
applyopts(sfd, -1, opts, PH_BIND);
|
||||
if (Bind(sfd->fd, &us->soa, uslen) < 0) {
|
||||
Error4("bind(%d, {%s}, "F_socklen"): %s", sfd->fd,
|
||||
sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
|
||||
|
@ -176,7 +176,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
Error4("getsockname(%d, %p, {%d}): %s",
|
||||
sfd->fd, &us->soa, uslen, strerror(errno));
|
||||
}
|
||||
applyopts(sfd->fd, opts, PH_PASTBIND);
|
||||
applyopts(sfd, -1, opts, PH_PASTBIND);
|
||||
|
||||
if (ipproto == IPPROTO_UDP) {
|
||||
Notice1("listening on UDP %s",
|
||||
|
@ -255,7 +255,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
break;
|
||||
} /* end of the big while loop */
|
||||
|
||||
applyopts(sfd->fd, opts, PH_CONNECT);
|
||||
applyopts(sfd, -1, opts, PH_CONNECT);
|
||||
if ((result = Connect(sfd->fd, &them->soa, themlen)) < 0) {
|
||||
Error4("connect(%d, {%s}, "F_socklen"): %s",
|
||||
sfd->fd,
|
||||
|
@ -274,7 +274,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
|||
|
||||
sfd->howtoend = END_SHUTDOWN;
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
applyopts(sfd->fd, opts, PH_LATE);
|
||||
applyopts(sfd, -1, opts, PH_LATE);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
@ -287,6 +287,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
int xioflags, xiofile_t *xfd,
|
||||
groups_t groups, int pf, int ipproto,
|
||||
int protname) {
|
||||
struct single *sfd = &xfd->stream;
|
||||
const char *portname = argv[1];
|
||||
union sockaddr_union us;
|
||||
int socktype = SOCK_DGRAM;
|
||||
|
@ -314,8 +315,9 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
|
||||
|
||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
uslen = socket_init(pf, &us);
|
||||
retropt_bind(opts, pf, socktype, ipproto,
|
||||
|
@ -383,7 +385,7 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
|||
xfd->howtoend = END_SHUTDOWN;
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
xfd->salen = sizeof(xfd->peersa);
|
||||
if ((result =
|
||||
|
|
41
xio-unix.c
41
xio-unix.c
|
@ -148,10 +148,10 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
|||
}
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts_named(name, opts, PH_EARLY); /* umask! */
|
||||
applyopts_offset(xfd, opts);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
|
||||
|
||||
|
@ -229,9 +229,9 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts_offset(xfd, opts);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight);
|
||||
|
||||
|
@ -361,6 +361,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
socklen_t uslen = sizeof(us);
|
||||
bool needbind = false;
|
||||
bool opt_unlink_close = (abstract != 1);
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)",
|
||||
|
@ -394,20 +395,24 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
|||
Error1("Option \"%s\" only with bind option", namedopt->desc->defname);
|
||||
}
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
|
||||
result =
|
||||
_xioopen_dgram_sendto(needbind?(union sockaddr_union *)&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype, protocol, 0);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (opt_unlink_close && needbind) {
|
||||
if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", name);
|
||||
}
|
||||
xfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
|
||||
return
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, xfd, groups,
|
||||
pf, socktype, protocol, 0);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,7 +443,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
xfd->howtoend = END_NONE;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts_named(name, opts, PH_EARLY); /* umask! */
|
||||
applyopts_offset(xfd, opts);
|
||||
|
||||
|
@ -447,7 +452,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight);
|
||||
|
||||
|
@ -519,7 +524,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts_named(name, opts, PH_EARLY); /* umask! */
|
||||
applyopts_offset(xfd, opts);
|
||||
|
||||
|
@ -528,7 +533,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
|||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
}
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight);
|
||||
|
||||
|
@ -607,11 +612,11 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups,
|
|||
retropt_socket_pf(opts, &pf);
|
||||
xfd->howtoend = END_SHUTDOWN;
|
||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts_offset(xfd, opts);
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
retropt_int(opts, OPT_SO_PROTOTYPE, &protocol);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight);
|
||||
if (!(ABSTRACT && abstract)) {
|
||||
|
|
|
@ -52,8 +52,8 @@ static int vsock_init(struct opt *opts, struct single *xfd) {
|
|||
if (applyopts_single(xfd, opts, PH_INIT) < 0)
|
||||
return STAT_NORETRY;
|
||||
|
||||
applyopts(-1, opts, PH_INIT);
|
||||
applyopts(-1, opts, PH_EARLY);
|
||||
applyopts(xfd, -1, opts, PH_INIT);
|
||||
applyopts(xfd, -1, opts, PH_EARLY);
|
||||
|
||||
xfd->dtype = XIODATA_STREAM;
|
||||
|
||||
|
|
2
xio.h
2
xio.h
|
@ -172,7 +172,7 @@ typedef struct single {
|
|||
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
||||
xiolock_t lock; /* parameters of lockfile */
|
||||
bool havelock; /* we are happy owner of the above lock */
|
||||
int triggerfd; /* close this FD in child process to notify parent */
|
||||
int triggerfd; /* in child process close this FD to notify parent */
|
||||
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
||||
/* until here, keep consistent with bipipe.dual ! */
|
||||
int argc; /* number of fields in argv */
|
||||
|
|
|
@ -111,6 +111,15 @@ static int xiohelp_option(FILE *of, const struct optname *on, const char *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char *xiohelp_opttypename(enum e_types typnum)
|
||||
{
|
||||
if (typnum < 0 || typnum >= TYPE_OVERFLOW) {
|
||||
Warn2("%s(): invalid type number %d", __func__, typnum);
|
||||
return "<invalid>";
|
||||
}
|
||||
return optiontypenames[typnum];
|
||||
}
|
||||
|
||||
int xioopenhelp(FILE *of,
|
||||
int level /* 0..only addresses, 1..and options */
|
||||
) {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef __xiohelp_h_included
|
||||
#define __xiohelp_h_included 1
|
||||
|
||||
extern const char *xiohelp_opttypename(enum e_types typnum);
|
||||
|
||||
extern int xioopenhelp(FILE *of,
|
||||
int level /* 0..only addresses, 1..and options */
|
||||
);
|
||||
|
|
627
xioopts.c
627
xioopts.c
|
@ -12,6 +12,7 @@
|
|||
#include "xiomodes.h"
|
||||
#include "xiolockfile.h"
|
||||
#include "nestlex.h"
|
||||
#include "xiohelp.h"
|
||||
|
||||
bool xioopts_ignoregroups;
|
||||
|
||||
|
@ -151,6 +152,7 @@ bool xioopts_ignoregroups;
|
|||
|
||||
|
||||
static int applyopt_offset(struct single *xfd, struct opt *opt);
|
||||
static int applyopt(struct single *sfd, int fd, struct opt *opt);
|
||||
|
||||
|
||||
/* address options - keep this array strictly alphabetically sorted for
|
||||
|
@ -3253,32 +3255,38 @@ int retropt_bind(struct opt *opts,
|
|||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
/* Applies to FD all options belonging to phase */
|
||||
/* Note: not all options can be applied this way */
|
||||
int applyopt(
|
||||
int applyopt_seek32(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
|
||||
return 0;
|
||||
|
||||
if (opt->desc->func == OFUNC_SEEK32) {
|
||||
if (Lseek(fd, opt->value.u_off, opt->desc->major) < 0) {
|
||||
Error4("lseek(%d, "F_off", %d): %s",
|
||||
fd, opt->value.u_off, opt->desc->major, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_LSEEK64
|
||||
} else if (opt->desc->func == OFUNC_SEEK64) {
|
||||
int applyopt_seek64(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
/*! this depends on off64_t atomic type */
|
||||
if (Lseek64(fd, opt->value.u_off64, opt->desc->major) < 0) {
|
||||
Error4("lseek64(%d, "F_off64", %d): %s",
|
||||
fd, opt->value.u_off64, opt->desc->major, strerror(errno));
|
||||
fd, opt->value.u_off64, opt->desc->major,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_LSEEK64 */
|
||||
|
||||
} else if (opt->desc->func == OFUNC_FCNTL) {
|
||||
int applyopt_fcntl(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
int flag;
|
||||
|
||||
/* retrieve existing flag setttings */
|
||||
|
@ -3294,19 +3302,30 @@ int applyopt(
|
|||
}
|
||||
if (Fcntl_l(fd, opt->desc->major, flag) < 0) {
|
||||
Error4("fcntl(%d, %d, %d): %s",
|
||||
fd, opt->desc->major, flag, strerror(errno));
|
||||
fd, opt->desc->major, flag,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_IOCTL) {
|
||||
int applyopt_ioctl(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
if (Ioctl(fd, opt->desc->major, (void *)&opt->value) < 0) {
|
||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||
fd, opt->desc->major, (void *)&opt->value, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_IOCTL_MASK_LONG) {
|
||||
int applyopt_ioctl_mask_long(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
long val;
|
||||
int getreq = opt->desc->major;
|
||||
int setreq = opt->desc->minor;
|
||||
|
@ -3318,14 +3337,20 @@ int applyopt(
|
|||
return -1;
|
||||
}
|
||||
val &= ~mask;
|
||||
if (opt->value.u_bool) val |= mask;
|
||||
if (opt->value.u_bool)
|
||||
val |= mask;
|
||||
if (Ioctl(fd, setreq, (void *)&val) < 0) {
|
||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
||||
fd, opt->desc->major, (void *)&val, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_IOCTL_GENERIC) {
|
||||
int applyopt_ioctl_generic(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT:
|
||||
if (Ioctl(fd, opt->value.u_int, NULL) < 0) {
|
||||
|
@ -3363,17 +3388,19 @@ int applyopt(
|
|||
}
|
||||
break;
|
||||
default:
|
||||
Error1("ioctl() data type %d not implemented",
|
||||
opt->desc->type);
|
||||
Error3("%s(opt:%s) data type %d not implemented",
|
||||
__func__, opt->desc->defname, opt->desc->type);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WITH_SOCKET
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT) {
|
||||
if (0) {
|
||||
;
|
||||
int applyopt_sockopt(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
#if 0 && HAVE_STRUCT_LINGER
|
||||
} else if (opt->desc->optcode == OPT_SO_LINGER) {
|
||||
if (opt->desc->optcode == OPT_SO_LINGER) {
|
||||
struct linger lingstru;
|
||||
lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0);
|
||||
lingstru.l_linger = opt->value.u_int;
|
||||
|
@ -3384,8 +3411,10 @@ int applyopt(
|
|||
lingstru.l_linger, sizeof(lingstru));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
#endif /* HAVE_STRUCT_LINGER */
|
||||
} else {
|
||||
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_BIN:
|
||||
if (Setsockopt(fd, opt->desc->major, opt->desc->minor,
|
||||
|
@ -3521,17 +3550,24 @@ int applyopt(
|
|||
#endif /* defined(WITH_IP4) */
|
||||
default:
|
||||
#if !NDEBUG
|
||||
Error1("applyopts(): type %d not implemented",
|
||||
opt->desc->type);
|
||||
Error3("%s(opt:\"%s\"): type %d no implemented",
|
||||
__func__, opt->desc->defname, opt->desc->type);
|
||||
#else
|
||||
Warn1("applyopts(): type %d not implemented",
|
||||
opt->desc->type);
|
||||
Warn3("%s(opt:\"%s\"): type %d no implemented",
|
||||
__func__, opt->desc->defname, opt->desc->type);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) {
|
||||
/* Appends the provided data to the current value of this sockopt.
|
||||
Used (e.g.) for IP_OPTIONS.
|
||||
*/
|
||||
int applyopt_sockopt_append(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
switch (opt->desc->type) {
|
||||
uint8_t data[256];
|
||||
socklen_t oldlen, newlen;
|
||||
|
@ -3562,7 +3598,13 @@ int applyopt(
|
|||
opt->desc->defname, opt->desc->type);
|
||||
break;
|
||||
}
|
||||
} else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int applyopt_sockopt_generic(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
switch (opt->desc->type) {
|
||||
case TYPE_INT_INT_INT:
|
||||
if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int,
|
||||
|
@ -3594,23 +3636,40 @@ int applyopt(
|
|||
}
|
||||
break;
|
||||
default:
|
||||
Error1("setsockopt() data type %d not implemented",
|
||||
opt->desc->type);
|
||||
Error3("%s(opt:\"%s\"): INTERNAL: data type %d not implemented",
|
||||
__func__, opt->desc->defname, opt->desc->type);
|
||||
return -1;
|
||||
}
|
||||
#endif /* _WITH_SOCKET */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_FLOCK
|
||||
} else if (opt->desc->func == OFUNC_FLOCK) {
|
||||
int applyopt_flock(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
if (Flock(fd, opt->desc->major) < 0) {
|
||||
Error3("flock(%d, %d): %s",
|
||||
fd, opt->desc->major, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif /* defined(HAVE_FLOCK) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Applies an option that needs handling specific to its OPT_* setting.
|
||||
Does not overwrite the option instance with ODESC_DONE or ODESC_ERROR,
|
||||
instead:
|
||||
Returns 0 if option was just applied (caller has to ODESC_DONE);
|
||||
returns -1 if a problem occurred (caller has to ODESC_ERROR);
|
||||
returns 1 if the instance has to be kept, this happens when the option desc has
|
||||
been overwritten to, e.g., undo the option in a later phase. */
|
||||
int applyopt_spec(
|
||||
struct single *sfd,
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
if (fd < 0 && sfd != NULL)
|
||||
fd = sfd->fd;
|
||||
|
||||
} else if (opt->desc->func == OFUNC_SPEC ||
|
||||
opt->desc->func == OFUNC_FLAG) {
|
||||
switch (opt->desc->optcode) {
|
||||
case OPT_USER:
|
||||
case OPT_USER_LATE:
|
||||
|
@ -3830,6 +3889,28 @@ int applyopt(
|
|||
}
|
||||
break;
|
||||
|
||||
#if _WITH_SOCKET
|
||||
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
|
||||
case OPT_IP_ADD_MEMBERSHIP:
|
||||
return xioapply_ip_add_membership(sfd, opt);
|
||||
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
|
||||
|
||||
#if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
case OPT_IP_ADD_SOURCE_MEMBERSHIP:
|
||||
return xioapply_ip_add_source_membership(sfd, opt);
|
||||
#endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
|
||||
|
||||
#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
|
||||
case OPT_IPV6_JOIN_GROUP:
|
||||
return xioapply_ipv6_join_group(sfd, opt);
|
||||
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
|
||||
|
||||
#if WITH_IP6 && defined(HAVE_STRUCT_GROUP_SOURCE_REQ)
|
||||
case OPT_IPV6_JOIN_SOURCE_GROUP:
|
||||
return xioapply_ip6_join_source_group(sfd, opt);
|
||||
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if _WITH_INTERFACE
|
||||
case OPT_RETRIEVE_VLAN:
|
||||
if (!xioparms.experimental) {
|
||||
|
@ -3841,18 +3922,17 @@ int applyopt(
|
|||
break;
|
||||
#endif /* _WITH_INTERFACE */
|
||||
|
||||
default: Error1("INTERNAL: applyopts(): option \"%s\" not implemented",
|
||||
default: Error1("applyopt_spec(opt:%s): INTERNAL option not implemented",
|
||||
opt->desc->defname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if WITH_TERMIOS
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_FLAG) {
|
||||
if (xiotermiosflag_applyopt(fd, opt) < 0) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_VALUE) {
|
||||
int applyopts_termios_value(
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
if (((opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) !=
|
||||
(opt->value.u_uint << opt->desc->arg3)) {
|
||||
Error2("option %s: invalid value %u",
|
||||
|
@ -3863,141 +3943,79 @@ int applyopt(
|
|||
(opt->value.u_uint << opt->desc->arg3) & opt->desc->minor) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_PATTERN) {
|
||||
if (xiotermios_value(fd, opt->desc->major, opt->desc->arg3, opt->desc->minor) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_CHAR) {
|
||||
if (xiotermios_char(fd, opt->desc->major, opt->value.u_byte) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TERMIOS_ISPEED
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_SPEED) {
|
||||
if (xiotermios_speed(fd, opt->desc->major, opt->value.u_uint) < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif /* HAVE_TERMIOS_ISPEED */
|
||||
|
||||
} else if (opt->desc->func == OFUNC_TERMIOS_SPEC) {
|
||||
if (xiotermios_spec(fd, opt->desc->optcode) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* WITH_TERMIOS */
|
||||
|
||||
#if WITH_STREAMS
|
||||
#define ENABLE_APPLYOPT
|
||||
#include "xio-streams.c"
|
||||
#undef ENABLE_APPLYOPT
|
||||
#endif /* WITH_STREAMS */
|
||||
|
||||
} else {
|
||||
/*Error1("applyopts(): function %d not implemented",
|
||||
opt->desc->func);*/
|
||||
if (opt->desc->func != OFUNC_EXT && opt->desc->func != OFUNC_SIGNAL) {
|
||||
Error1("applyopts(): internal error: option \"%s\" does not apply",
|
||||
opt->desc->defname);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
opt->desc = ODESC_DONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
|
||||
implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
|
||||
OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
|
||||
int applyopts(int fd, struct opt *opts, enum e_phase phase)
|
||||
int applyopts(struct single *sfd, int fd, struct opt *opts, enum e_phase phase)
|
||||
{
|
||||
struct opt *opt;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
opt = opts;
|
||||
while (opt && opt->desc != ODESC_END) {
|
||||
if (opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR &&
|
||||
(phase == PH_ALL || phase == opt->desc->phase)) {
|
||||
rc = applyopt(fd, opt);
|
||||
if (rc < 0)
|
||||
opt->desc = ODESC_ERROR;
|
||||
if (applyopt(sfd, fd, opt) < 0)
|
||||
rc = -1;
|
||||
}
|
||||
++opt;
|
||||
}
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (phase == PH_FD || phase == PH_ALL) {
|
||||
xiotermios_flush(fd);
|
||||
if ((phase == PH_FD || phase == PH_ALL) && (fd >= 0 || sfd != NULL)) {
|
||||
xiotermios_flush(fd >= 0 ? fd : sfd->fd);
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* applies to fd all options belonging to phases */
|
||||
/* note: not all options can be applied this way (e.g. OFUNC_SPEC with PH_OPEN)
|
||||
implemented are: OFUNC_FCNTL, OFUNC_SOCKOPT (probably not all types),
|
||||
OFUNC_TERMIOS_FLAG, OFUNC_TERMIOS_PATTERN, and some OFUNC_SPEC */
|
||||
int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to) {
|
||||
unsigned int i;
|
||||
int stat;
|
||||
|
||||
for (i = from; i <= to; ++i) {
|
||||
if ((stat = applyopts(fd, opts, i)) < 0)
|
||||
return stat;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Apply and consume all options of type FLAG and group.
|
||||
Return 0 when everything went right, or -1 if an error occurred. */
|
||||
int applyopts_optgroup(
|
||||
int applyopts2(
|
||||
struct single *sfd,
|
||||
int fd,
|
||||
struct opt *opts,
|
||||
unsigned int from,
|
||||
unsigned int to) {
|
||||
unsigned int ph;
|
||||
int rc = 0;
|
||||
|
||||
for (ph = from; ph <= to; ++ph) {
|
||||
rc |= applyopts(sfd, fd, opts, ph);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int applyopts_optgroup(
|
||||
struct single *sfd,
|
||||
int fd,
|
||||
struct opt *opts,
|
||||
int from, /* -1: from first phase, not in order */
|
||||
int to, /* -1: to last phase, not in order */
|
||||
groups_t groups)
|
||||
{
|
||||
struct opt *opt = opts;
|
||||
unsigned int i;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
if (opts == NULL)
|
||||
return 0;
|
||||
|
||||
/* Just apply all opts matching from/to phases, in their stored order */
|
||||
if (from < 0 || to < 0) {
|
||||
if (from < 0)
|
||||
from = 0;
|
||||
if (to < 0)
|
||||
to = UINT_MAX;
|
||||
while (opt->desc != ODESC_END) {
|
||||
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
|
||||
i = 0;
|
||||
while (opts[i].desc != ODESC_END) {
|
||||
if (opts[i].desc == ODESC_DONE &&
|
||||
opts[i].desc == ODESC_ERROR) {
|
||||
++i;
|
||||
continue;
|
||||
if ((opt->desc->group & groups) == 0)
|
||||
continue;
|
||||
if (opt->desc->phase < from ||
|
||||
opt->desc->phase > to)
|
||||
continue;
|
||||
applyopt(fd, opt);
|
||||
/* Dont check rc: on error is should not come here */
|
||||
|
||||
++opt;
|
||||
}
|
||||
if (opts[i].desc->group & groups) {
|
||||
rc |= applyopt(sfd, sfd->fd, &opts[i]);
|
||||
}
|
||||
|
||||
/* Just apply all opts from, to phase, in their phases order */
|
||||
for (i = from; i <= to; ++i) {
|
||||
while (opt->desc != ODESC_END) {
|
||||
if (opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR &&
|
||||
(opt->desc->group & groups) && opt->desc->phase == i) {
|
||||
applyopt(fd, opt);
|
||||
/* Dont check rc: on error is should not come here */
|
||||
++i;
|
||||
}
|
||||
++opt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* apply and consume all options of type FLAG and group.
|
||||
|
@ -4091,8 +4109,8 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) {
|
|||
*(int *)ptr = opt->desc->minor;
|
||||
break;
|
||||
default:
|
||||
Error1("applyopt_offset(): type %d not implemented",
|
||||
opt->desc->type);
|
||||
Error2("applyopt_offset(opt:%s): type %s not implemented",
|
||||
opt->desc->defname, xiohelp_opttypename(opt->desc->type));
|
||||
return -1;
|
||||
}
|
||||
opt->desc = ODESC_DONE;
|
||||
|
@ -4118,80 +4136,222 @@ int applyopts_offset(struct single *xfd, struct opt *opts) {
|
|||
returns -1 if an error occurred */
|
||||
int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
||||
struct opt *opt;
|
||||
int lockrc;
|
||||
int rc = 0;
|
||||
|
||||
if (!opts) return 0;
|
||||
if (!opts)
|
||||
return 0;
|
||||
|
||||
opt = opts; while (opt->desc != ODESC_END) {
|
||||
if ((opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR) ||
|
||||
(opt->desc->phase != phase && phase != PH_ALL)) {
|
||||
/* option not handled in this function */
|
||||
++opt; continue;
|
||||
if ((opt->desc != ODESC_DONE && opt->desc != ODESC_ERROR) &&
|
||||
(opt->desc->phase == phase && phase != PH_ALL)) {
|
||||
if (opt->desc->func < OFUNC_XIO) {
|
||||
rc = applyopt(NULL, xfd->fd, opt);
|
||||
} else {
|
||||
rc = applyopt(xfd, -1, opt);
|
||||
}
|
||||
if (rc == 0)
|
||||
opt->desc = ODESC_DONE;
|
||||
else
|
||||
opt->desc = ODESC_ERROR;
|
||||
}
|
||||
++opt;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Applies to sfd or fd the given option.
|
||||
Note: not all options can be applied this way.
|
||||
Returns 0.
|
||||
*/
|
||||
static int applyopt(
|
||||
struct single *sfd,
|
||||
int fd,
|
||||
struct opt *opt)
|
||||
{
|
||||
int lockrc;
|
||||
int rc = 0;
|
||||
|
||||
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR)
|
||||
return 0;
|
||||
|
||||
if (sfd != NULL && fd < 0)
|
||||
fd = sfd->fd;
|
||||
|
||||
switch (opt->desc->func) {
|
||||
|
||||
case OFUNC_SPEC:
|
||||
rc = applyopt_spec(sfd, fd, opt);
|
||||
break;
|
||||
case OFUNC_SEEK32:
|
||||
rc = applyopt_seek32(fd, opt);
|
||||
break;
|
||||
|
||||
#if HAVE_LSEEK64
|
||||
case OFUNC_SEEK64:
|
||||
rc = applyopt_seek64(fd, opt);
|
||||
break;
|
||||
#endif /* HAVE_LSEEK64 */
|
||||
|
||||
case OFUNC_FCNTL:
|
||||
rc = applyopt_fcntl(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_IOCTL:
|
||||
rc = applyopt_ioctl(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_IOCTL_MASK_LONG:
|
||||
rc = applyopt_ioctl_mask_long(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_IOCTL_GENERIC:
|
||||
rc = applyopt_ioctl_generic(fd, opt);
|
||||
break;
|
||||
|
||||
#if _WITH_SOCKET
|
||||
case OFUNC_SOCKOPT:
|
||||
rc = applyopt_sockopt(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_SOCKOPT_APPEND:
|
||||
rc = applyopt_sockopt_append(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_SOCKOPT_GENERIC:
|
||||
rc = applyopt_sockopt_generic(fd, opt);
|
||||
break;
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if HAVE_FLOCK
|
||||
case OFUNC_FLOCK:
|
||||
rc = applyopt_flock(fd, opt);
|
||||
break;
|
||||
#endif /* defined(HAVE_FLOCK) */
|
||||
|
||||
#if WITH_TERMIOS
|
||||
case OFUNC_TERMIOS_FLAG:
|
||||
rc = xiotermiosflag_applyopt(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_TERMIOS_VALUE:
|
||||
rc = applyopts_termios_value(fd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_TERMIOS_PATTERN:
|
||||
rc = xiotermios_value(fd, opt->desc->major,
|
||||
opt->desc->arg3, opt->desc->minor);
|
||||
break;
|
||||
|
||||
case OFUNC_TERMIOS_CHAR:
|
||||
rc = xiotermios_char(fd, opt->desc->major, opt->value.u_byte);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_TERMIOS_ISPEED
|
||||
case OFUNC_TERMIOS_SPEED:
|
||||
rc = xiotermios_speed(fd, opt->desc->major, opt->value.u_uint);
|
||||
break;
|
||||
#endif /* HAVE_TERMIOS_ISPEED */
|
||||
|
||||
case OFUNC_TERMIOS_SPEC:
|
||||
rc = xiotermios_spec(fd, opt->desc->optcode);
|
||||
break;
|
||||
#endif /* WITH_TERMIOS */
|
||||
|
||||
#if WITH_STREAMS
|
||||
#define ENABLE_APPLYOPT
|
||||
#include "xio-streams.c"
|
||||
#undef ENABLE_APPLYOPT
|
||||
#endif /* WITH_STREAMS */
|
||||
|
||||
case OFUNC_OFFSET:
|
||||
applyopt_offset(xfd, opt);
|
||||
rc = applyopt_offset(sfd, opt);
|
||||
break;
|
||||
|
||||
case OFUNC_EXT:
|
||||
switch (opt->desc->optcode) {
|
||||
#if 0
|
||||
case OPT_IGNOREEOF:
|
||||
xfd->ignoreeof = true;
|
||||
break;
|
||||
sfd->ignoreeof = true;
|
||||
return 0;
|
||||
case OPT_CR:
|
||||
xfd->lineterm = LINETERM_CR;
|
||||
break;
|
||||
sfd->lineterm = LINETERM_CR;
|
||||
return 0;
|
||||
case OPT_CRNL:
|
||||
xfd->lineterm = LINETERM_CRNL;
|
||||
break;
|
||||
sfd->lineterm = LINETERM_CRNL;
|
||||
return 0;
|
||||
#endif /* 0 */
|
||||
case OPT_READBYTES:
|
||||
xfd->readbytes = opt->value.u_sizet;
|
||||
xfd->actbytes = xfd->readbytes;
|
||||
sfd->readbytes = opt->value.u_sizet;
|
||||
sfd->actbytes = sfd->readbytes;
|
||||
break;
|
||||
|
||||
case OPT_LOCKFILE:
|
||||
if (xfd->lock.lockfile) {
|
||||
if (sfd->lock.lockfile) {
|
||||
Error("only one use of options lockfile and waitlock allowed");
|
||||
}
|
||||
xfd->lock.lockfile = strdup(opt->value.u_string);
|
||||
xfd->lock.intervall.tv_sec = 1;
|
||||
xfd->lock.intervall.tv_nsec = 0;
|
||||
sfd->lock.lockfile = strdup(opt->value.u_string);
|
||||
sfd->lock.intervall.tv_sec = 1;
|
||||
sfd->lock.intervall.tv_nsec = 0;
|
||||
|
||||
if ((lockrc = xiolock(&xfd->lock)) < 0) {
|
||||
if ((lockrc = xiolock(&sfd->lock)) < 0) {
|
||||
/* error message already printed */
|
||||
return -1;
|
||||
rc = -1;
|
||||
}
|
||||
if (lockrc) {
|
||||
Error1("could not obtain lock \"%s\"", xfd->lock.lockfile);
|
||||
Error1("could not obtain lock \"%s\"", sfd->lock.lockfile);
|
||||
rc = -1;
|
||||
} else {
|
||||
xfd->havelock = true;
|
||||
sfd->havelock = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_WAITLOCK:
|
||||
if (xfd->lock.lockfile) {
|
||||
if (sfd->lock.lockfile) {
|
||||
Error("only one use of options lockfile and waitlock allowed");
|
||||
}
|
||||
xfd->lock.lockfile = strdup(opt->value.u_string);
|
||||
xfd->lock.waitlock = true;
|
||||
xfd->lock.intervall.tv_sec = 1;
|
||||
xfd->lock.intervall.tv_nsec = 0;
|
||||
sfd->lock.lockfile = strdup(opt->value.u_string);
|
||||
sfd->lock.waitlock = true;
|
||||
sfd->lock.intervall.tv_sec = 1;
|
||||
sfd->lock.intervall.tv_nsec = 0;
|
||||
|
||||
/*! this should be integrated into central select()/poll() loop */
|
||||
if (xiolock(&xfd->lock) < 0) {
|
||||
return -1;
|
||||
}
|
||||
xfd->havelock = true;
|
||||
rc = xiolock(&sfd->lock);
|
||||
if (rc < 0)
|
||||
break;
|
||||
sfd->havelock = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* just store the value in the correct component of struct single */
|
||||
if (opt->desc->type == TYPE_CONST) {
|
||||
/* only for integral types compatible to int */
|
||||
*(int *)(&((char *)xfd)[opt->desc->major]) = opt->desc->arg3;
|
||||
*(int *)(&((char *)sfd)[opt->desc->major]) = opt->desc->arg3;
|
||||
} else {
|
||||
memcpy(&((char *)xfd)[opt->desc->major], &opt->value, opt->desc->minor);
|
||||
memcpy(&((char *)sfd)[opt->desc->major], &opt->value, opt->desc->minor);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OFUNC_OFFSET_MASK:
|
||||
/* Currently not used */
|
||||
/* Data target is some integer with independent bits in sfd;
|
||||
set or unset the specified bits. */
|
||||
{
|
||||
void *mask = (char *)sfd + opt->desc->major;
|
||||
size_t masksize = opt->desc->minor;
|
||||
unsigned long bit = opt->desc->arg3;
|
||||
switch (masksize) {
|
||||
case sizeof(int):
|
||||
if (opt->value.u_bool) {
|
||||
(*(int *)mask) |= bit;
|
||||
} else {
|
||||
(*(int *)mask) &= ~bit;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Info1("sizeof(int)="F_Zu, sizeof(int));
|
||||
Error2("applyopts_single(opt:%s): INTERNAL: OFUNC_OFFSET_MASK size "F_Zu" not implemented",
|
||||
opt->desc->defname, masksize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -4202,7 +4362,7 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
|||
element holds the bit mask to be set, the second one those to be
|
||||
cleared. Each related option sets or unsets a specific bit. */
|
||||
{
|
||||
void *masks = (char *)xfd + opt->desc->major;
|
||||
void *masks = (char *)sfd + opt->desc->major;
|
||||
size_t masksize = opt->desc->minor;
|
||||
unsigned long bit = opt->desc->arg3;
|
||||
switch (masksize>>1) {
|
||||
|
@ -4228,104 +4388,53 @@ int applyopts_single(struct single *xfd, struct opt *opts, enum e_phase phase) {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
Error1("applyopts_single: masksize "F_Zu" not implemented",
|
||||
masksize);
|
||||
Info1("sizeof(uint32_t)="F_Zu, sizeof(uint32_t));
|
||||
Error2("applyopts_single(opt:%s): INTERNAL: OFUNC_OFFSET_MASKS size "F_Zu" not implemented",
|
||||
opt->desc->defname, masksize);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if _WITH_SOCKET
|
||||
case OFUNC_SOCKOPT:
|
||||
switch (opt->desc->optcode) {
|
||||
#if WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN))
|
||||
case OPT_IP_ADD_MEMBERSHIP:
|
||||
if (xioapply_ip_add_membership(xfd, opt) < 0) {
|
||||
continue;
|
||||
}
|
||||
case OFUNC_SIGNAL:
|
||||
rc = xio_opt_signal(sfd->para.exec.pid, opt->desc->major);
|
||||
break;
|
||||
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
|
||||
|
||||
#if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
case OPT_IP_ADD_SOURCE_MEMBERSHIP:
|
||||
if (xioapply_ip_add_source_membership(xfd, opt) < 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
|
||||
|
||||
#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
|
||||
case OPT_IPV6_JOIN_GROUP:
|
||||
if (xioapply_ipv6_join_group(xfd, opt) < 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
|
||||
|
||||
#if WITH_IP6 && defined(HAVE_STRUCT_GROUP_SOURCE_REQ)
|
||||
case OPT_IPV6_JOIN_SOURCE_GROUP:
|
||||
if (xioapply_ip6_join_source_group(xfd, opt) < 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ) */
|
||||
default:
|
||||
/* ignore here */
|
||||
++opt; continue;
|
||||
}
|
||||
break;
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
default:
|
||||
++opt;
|
||||
continue;
|
||||
Error2("applyopt(opt:%s): INTERNAL: ofunc %d not implemented",
|
||||
opt->desc->defname, opt->desc->func);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
if (rc == 0)
|
||||
opt->desc = ODESC_DONE;
|
||||
++opt;
|
||||
}
|
||||
}
|
||||
else if (rc < 0)
|
||||
opt->desc = ODESC_ERROR;
|
||||
/* rc > 0: no action */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* xfd->para.exec.pid must be set */
|
||||
int applyopts_signal(struct single *xfd, struct opt *opts) {
|
||||
struct opt *opt;
|
||||
|
||||
if (!opts) return 0;
|
||||
|
||||
opt = opts; while (opt->desc != ODESC_END) {
|
||||
if (opt->desc == ODESC_DONE || opt->desc == ODESC_ERROR ||
|
||||
opt->desc->func != OFUNC_SIGNAL) {
|
||||
++opt; continue;
|
||||
}
|
||||
|
||||
if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
|
||||
opt->desc = ODESC_ERROR; continue;
|
||||
}
|
||||
opt->desc = ODESC_DONE;
|
||||
++opt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* apply remaining options to file descriptor, and tell us if something is
|
||||
still unused */
|
||||
int _xio_openlate(struct single *fd, struct opt *opts) {
|
||||
int _xio_openlate(struct single *sfd, struct opt *opts) {
|
||||
int numleft;
|
||||
int result;
|
||||
|
||||
_xioopen_setdelayeduser();
|
||||
|
||||
if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) {
|
||||
if ((result = applyopts(sfd, sfd->fd, opts, PH_LATE)) < 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
|
||||
if ((result = applyopts_single(sfd, opts, PH_LATE)) < 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) {
|
||||
if ((result = applyopts(sfd, sfd->fd, opts, PH_LATE2)) < 0) {
|
||||
return result;
|
||||
}
|
||||
if ((result = applyopts(fd->fd, opts, PH_PASTEXEC)) < 0) {
|
||||
if ((result = applyopts(sfd, sfd->fd, opts, PH_PASTEXEC)) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -4364,3 +4473,21 @@ int dropopts2(struct opt *opts, unsigned int from, unsigned int to) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dumpopts(struct opt *opts)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (opts == NULL) {
|
||||
Warn("dumpopts: NULL");
|
||||
return 0;
|
||||
}
|
||||
i = 0;
|
||||
while (opts[i].desc != ODESC_END) {
|
||||
if (opts[i].desc != ODESC_DONE &&
|
||||
opts[i].desc != ODESC_ERROR) {
|
||||
Warn2("dumpopts(): %d %s", i, opts[i].desc->defname);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
33
xioopts.h
33
xioopts.h
|
@ -82,10 +82,12 @@ enum e_types {
|
|||
#endif
|
||||
|
||||
TYPE_GENERIC, /* type is determined from (text) data provided (dalan syntax) */
|
||||
TYPE_OVERFLOW /* marker: beyond last type */
|
||||
} ;
|
||||
|
||||
enum e_func {
|
||||
OFUNC_NONE, /* no function - should not occur */
|
||||
/* Options to be applied to FD directly */
|
||||
OFUNC_FLAG, /* no function, but bitposition, only with bool; arg1 is mask */
|
||||
OFUNC_FLAG_PATTERN, /* no function, but bitpattern: arg1 is pattern, arg2 is mask */
|
||||
OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */
|
||||
|
@ -100,12 +102,6 @@ enum e_func {
|
|||
OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */
|
||||
OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */
|
||||
OFUNC_FLOCK, /* flock() */
|
||||
OFUNC_TERMIO, /* termio() ? */
|
||||
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
||||
OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
|
||||
OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */
|
||||
/*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
|
||||
OFUNC_EXT, /* with extended file descriptors only */
|
||||
OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit
|
||||
*/
|
||||
OFUNC_TERMIOS_PATTERN, /* a multibit: major..tcflag, minor..pattern,
|
||||
|
@ -114,14 +110,23 @@ enum e_func {
|
|||
OFUNC_TERMIOS_CHAR, /* a termios functional character: major..c_cc index */
|
||||
OFUNC_TERMIOS_SPEED, /* termios c_ispeed etc on FreeBSD */
|
||||
OFUNC_TERMIOS_SPEC, /* termios combined modes */
|
||||
|
||||
OFUNC_EXT, /* with extended file descriptors only */
|
||||
# define OFUNC_XIO OFUNC_EXT
|
||||
OFUNC_SPEC, /* special, i.e. no generalizable function call */
|
||||
OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */
|
||||
OFUNC_OFFSET_MASK, /* set/unset bit pattern in variable */
|
||||
OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */
|
||||
/*OFUNC_APPL,*/ /* special, i.e. application must know which f. */
|
||||
OFUNC_SIGNAL, /* a signal that should be passed to child process */
|
||||
OFUNC_RESOLVER, /* a bit position used on _res.options */
|
||||
OFUNC_IFFLAG, /* interface flag: locical-or a 1bit mask */
|
||||
OFUNC_IFFLAG, /* interface flag: logical-or a 1bit mask */
|
||||
OFUNC_SET_NAMESPACE, /* set/change Linux namespace */
|
||||
OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */
|
||||
# define ENABLE_OFUNC
|
||||
# include "xio-streams.h" /* push a POSIX STREAMS module */
|
||||
# undef ENABLE_OFUNC
|
||||
OFUNC_SET_NAMESPACE, /* set/change Linux namespace */
|
||||
OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */
|
||||
OFUNC_OVERFLOW /* marker: beyond last func */
|
||||
} ;
|
||||
|
||||
/* for simpler handling of option-to-connection-type relations we define
|
||||
|
@ -980,12 +985,13 @@ extern int retropt_flag(struct opt *opts, int optcode, flags_t *result);
|
|||
extern int retropt_string(struct opt *opts, int optcode, char **result);
|
||||
extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result);
|
||||
extern int retropt_bind(struct opt *opts, int af, int socktype, int ipproto, struct sockaddr *sa, socklen_t *salen, int feats, const int ai_flags[2]);
|
||||
extern int applyopts(int fd, struct opt *opts, enum e_phase phase);
|
||||
extern int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to);
|
||||
extern int applyopts_optgroup(int fd, struct opt *opts, int from, int to, groups_t groups);
|
||||
extern int applyopt_fd(int fd, struct opt *opt);
|
||||
extern int applyopt_single(struct single *sfd, struct opt *opt);
|
||||
extern int applyopts(struct single *sfd, int fd, struct opt *opts, enum e_phase phase);
|
||||
extern int applyopts2(struct single *sfd, int fd, struct opt *opts, unsigned int from, unsigned int to);
|
||||
extern int applyopts_optgroup(struct single *sfd, int fd, struct opt *opts, groups_t groups);
|
||||
extern int applyopts_flags(struct opt *opts, groups_t group, flags_t *result);
|
||||
extern int applyopts_cloexec(int fd, struct opt *opts);
|
||||
extern int applyopts_early(const char *path, struct opt *opts);
|
||||
extern int applyopts_fchown(int fd, struct opt *opts);
|
||||
extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase phase);
|
||||
extern int applyopts_offset(struct single *xfd, struct opt *opts);
|
||||
|
@ -1005,6 +1011,7 @@ extern groups_t groupbits(int fd);
|
|||
extern groups_t _groupbits(mode_t mode);
|
||||
extern int dropopts(struct opt *opts, unsigned int phase);
|
||||
extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to);
|
||||
extern int dumpopts(struct opt *opts);
|
||||
|
||||
#if HAVE_BASIC_UID_T==1
|
||||
# define retropt_uid(o,c,r) retropt_short(o,c,r)
|
||||
|
|
|
@ -62,14 +62,19 @@ void socatsignalpass(int sig) {
|
|||
return;
|
||||
}
|
||||
|
||||
{ /*debug*/
|
||||
int n = 0;
|
||||
for (i=0; i<sigdesc->sig_use; ++i) {
|
||||
if (sigdesc->sig_pids[i]) {
|
||||
++n;
|
||||
if (Kill(sigdesc->sig_pids[i], sig) < 0) {
|
||||
Warn2("kill("F_pid", %d): %m",
|
||||
sigdesc->sig_pids[i], sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
Info1("socatsignalpass(): n=%d", n);
|
||||
}
|
||||
#if !HAVE_SIGACTION
|
||||
Signal(sig, socatsignalpass);
|
||||
#endif /* !HAVE_SIGACTION */
|
||||
|
|
Loading…
Reference in a new issue