Internal: Reworked xioopts

This commit is contained in:
Gerhard Rieger 2023-07-13 09:06:08 +02:00
parent 1c1a91027a
commit 5eebca3a5b
37 changed files with 1380 additions and 1199 deletions

View file

@ -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" ||

View file

@ -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;

View file

@ -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 */

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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) {

View file

@ -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 };

View file

@ -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,

View file

@ -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;

View file

@ -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 {

View file

@ -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);

View file

@ -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 */

View file

@ -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);

View file

@ -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 */

View file

@ -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;

View file

@ -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: */

View file

@ -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 =

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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
} } }

View file

@ -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;
}

View file

@ -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;

View file

@ -149,7 +149,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
}
doreuseaddr |= (retropt_2integrals(opts, OPT_SO_REUSEADDR,
&reuseaddr, &notnull) >= 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 =

View file

@ -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)) {

View file

@ -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
View file

@ -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 */

View file

@ -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 */
) {

View file

@ -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
View file

@ -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;
}

View file

@ -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)

View file

@ -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 */