From 5eebca3a5b8b78c2412b421efa3ee2f21001f23c Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Thu, 13 Jul 2023 09:06:08 +0200 Subject: [PATCH] Internal: Reworked xioopts --- test.sh | 5 +- xio-creat.c | 19 +- xio-exec.c | 11 +- xio-fdnum.c | 6 +- xio-file.c | 27 +- xio-gopen.c | 33 +- xio-interface.c | 2 +- xio-ip.c | 2 +- xio-ipapp.c | 9 +- xio-listen.c | 25 +- xio-named.c | 8 +- xio-openssl.c | 8 +- xio-pipe.c | 54 +- xio-posixmq.c | 2 +- xio-progcall.c | 219 +++--- xio-proxy.c | 4 +- xio-pty.c | 28 +- xio-rawip.c | 2 +- xio-readline.c | 7 +- xio-socket.c | 216 +++--- xio-socketpair.c | 15 +- xio-socks.c | 4 +- xio-socks5.c | 4 +- xio-stdio.c | 12 +- xio-streams.c | 22 +- xio-system.c | 9 +- xio-termios.c | 2 +- xio-tun.c | 27 +- xio-udp.c | 20 +- xio-unix.c | 41 +- xio-vsock.c | 4 +- xio.h | 2 +- xiohelp.c | 9 + xiohelp.h | 2 + xioopts.c | 1681 +++++++++++++++++++++++++--------------------- xioopts.h | 33 +- xiosignal.c | 5 + 37 files changed, 1380 insertions(+), 1199 deletions(-) diff --git a/test.sh b/test.sh index df336a6..052721c 100755 --- a/test.sh +++ b/test.sh @@ -17093,11 +17093,12 @@ tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" -CMD0="$TRACE $SOCAT $opts -T 1 PIPE EXEC:cat,setsid,sigint" +CMD0="$TRACE $SOCAT $opts -T 2 PIPE EXEC:\"$CAT\",pty,setsid,sigint" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! -relsleep 2 +#echo "pid0=$pid0" >&2 #!!! +sleep 1 kill -INT $pid0 wait if grep -q " W waitpid..: child .* exited with status 130" "${te}0" || diff --git a/xio-creat.c b/xio-creat.c index e5b197a..2d7fbdc 100644 --- a/xio-creat.c +++ b/xio-creat.c @@ -37,7 +37,8 @@ static int _xioopen_creat(const char *path, int rw, struct opt *opts) { } -static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) { +static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, groups_t groups, int dummy1, int dummy2, int dummy3) { + struct single *sfd = &xxfd->stream; const char *filename = argv[1]; int rw = (xioflags&XIO_ACCMODE); bool exists; @@ -45,32 +46,32 @@ static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xio int result; /* remove old file, or set user/permissions on old file; parse options */ - if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) { + if ((result = _xioopen_named_early(argc, argv, xxfd, groups, &exists, opts)) < 0) { return result; } retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); if (opt_unlink_close) { - if ((fd->stream.unlink_close = strdup(filename)) == NULL) { + if ((sfd->unlink_close = strdup(filename)) == NULL) { Error1("strdup(\"%s\"): out of memory", filename); } - fd->stream.opt_unlink_close = true; + sfd->opt_unlink_close = true; } Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]); if ((result = _xioopen_creat(filename, rw, opts)) < 0) return result; - fd->stream.fd = result; + sfd->fd = result; applyopts_named(filename, opts, PH_PASTOPEN); - if ((result = applyopts2(fd->stream.fd, opts, PH_PASTOPEN, PH_LATE2)) < 0) + if ((result = applyopts2(sfd, -1, opts, PH_PASTOPEN, PH_LATE2)) < 0) return result; - applyopts_cloexec(fd->stream.fd, opts); + applyopts_cloexec(sfd->fd, opts); - applyopts_fchown(fd->stream.fd, opts); + applyopts_fchown(sfd->fd, opts); - if ((result = _xio_openlate(&fd->stream, opts)) < 0) + if ((result = _xio_openlate(sfd, opts)) < 0) return result; return 0; diff --git a/xio-exec.c b/xio-exec.c index a59db4f..5ca274e 100644 --- a/xio-exec.c +++ b/xio-exec.c @@ -26,13 +26,15 @@ const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREE static int xioopen_exec(int argc, const char *argv[], struct opt *opts, int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */ - xiofile_t *fd, + xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3 ) { + struct single *sfd = &xfd->stream; int status; bool dash = false; int duptostderr; + int numleft; if (argc != 2) { Error2("\"%s\": wrong number of parameters (%d instead of 1)", argv[0], argc-1); @@ -40,8 +42,9 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts, retropt_bool(opts, OPT_DASH, &dash); - status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts, &duptostderr); - if (status < 0) return status; + status = _xioopen_foxec(xioflags, sfd, groups, &opts, &duptostderr); + if (status < 0) + return status; if (status == 0) { /* child */ const char *ends[] = { " ", NULL }; const char *hquotes[] = { "'", NULL }; @@ -61,7 +64,6 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts, char *tokp; char *path = NULL; char *tmp; - int numleft; /*! Close(something) */ /* parse command line */ @@ -143,6 +145,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts, } /* parent */ + _xio_openlate(sfd, opts); return 0; } #endif /* WITH_EXEC */ diff --git a/xio-fdnum.c b/xio-fdnum.c index 71611d9..26bc48a 100644 --- a/xio-fdnum.c +++ b/xio-fdnum.c @@ -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); } diff --git a/xio-file.c b/xio-file.c index 9227fb4..f41226e 100644 --- a/xio-file.c +++ b/xio-file.c @@ -72,50 +72,51 @@ const struct addrdesc xioaddr_open = { "OPEN", 3, xioopen_open, GROUP_FD|GRO if the filesystem entry already exists, the data is appended if it does not exist, a file is created and the data is appended */ -static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) { +static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { const char *filename = argv[1]; int rw = (xioflags & XIO_ACCMODE); + struct single *sfd = &xfd->stream; bool exists; bool opt_unlink_close = false; int result; /* remove old file, or set user/permissions on old file; parse options */ - if ((result = _xioopen_named_early(argc, argv, fd, groups, &exists, opts)) < 0) { + if ((result = _xioopen_named_early(argc, argv, xfd, groups, &exists, opts)) < 0) { return result; } retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); if (opt_unlink_close) { - if ((fd->stream.unlink_close = strdup(filename)) == NULL) { + if ((sfd->unlink_close = strdup(filename)) == NULL) { Error1("strdup(\"%s\"): out of memory", filename); } - fd->stream.opt_unlink_close = true; + sfd->opt_unlink_close = true; } Notice3("opening %s \"%s\" for %s", filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]); if ((result = _xioopen_open(filename, rw, opts)) < 0) return result; - fd->stream.fd = result; + sfd->fd = result; #if WITH_TERMIOS - if (Isatty(fd->stream.fd)) { - if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) { + if (Isatty(sfd->fd)) { + if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) { Warn2("cannot query current terminal settings on fd %d: %s", - fd->stream.fd, strerror(errno)); + sfd->fd, strerror(errno)); } else { - fd->stream.ttyvalid = true; + sfd->ttyvalid = true; } } #endif /* WITH_TERMIOS */ applyopts_named(filename, opts, PH_FD); - applyopts(fd->stream.fd, opts, PH_FD); - applyopts_cloexec(fd->stream.fd, opts); + applyopts(sfd, -1, opts, PH_FD); + applyopts_cloexec(sfd->fd, opts); - applyopts_fchown(fd->stream.fd, opts); + applyopts_fchown(sfd->fd, opts); - if ((result = _xio_openlate(&fd->stream, opts)) < 0) + if ((result = _xio_openlate(sfd, opts)) < 0) return result; return 0; diff --git a/xio-gopen.c b/xio-gopen.c index 0bd62fd..27488a2 100644 --- a/xio-gopen.c +++ b/xio-gopen.c @@ -19,7 +19,8 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":") }; -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; } diff --git a/xio-interface.c b/xio-interface.c index f29012f..6fe1231 100644 --- a/xio-interface.c +++ b/xio-interface.c @@ -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) { diff --git a/xio-ip.c b/xio-ip.c index 471b658..a89183d 100644 --- a/xio-ip.c +++ b/xio-ip.c @@ -69,7 +69,7 @@ const struct optdesc opt_ip_multicast_if ={"ip-multicast-if", "multicast-if", const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PKTOPTIONS, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_PKTOPTIONS }; #endif #ifdef IP_ADD_MEMBERSHIP -const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IP, IP_ADD_MEMBERSHIP }; +const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SPEC, SOL_IP, IP_ADD_MEMBERSHIP }; #endif #if defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) const struct optdesc opt_ip_add_source_membership = { "ip-add-source-membership", "source-membership",OPT_IP_ADD_SOURCE_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQ_SOURCE, OFUNC_SOCKOPT, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP }; diff --git a/xio-ipapp.c b/xio-ipapp.c index 44ec8c1..7fbeb70 100644 --- a/xio-ipapp.c +++ b/xio-ipapp.c @@ -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, diff --git a/xio-listen.c b/xio-listen.c index aef31ee..078001b 100644 --- a/xio-listen.c +++ b/xio-listen.c @@ -113,16 +113,16 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) { return STAT_RETRYLATER; } - applyopts(xfd->fd, opts, PH_PASTSOCKET); + applyopts(xfd, -1, opts, PH_PASTSOCKET); applyopts_offset(xfd, opts); applyopts_cloexec(xfd->fd, opts); /* Phase prebind */ xiosock_reuseaddr(xfd->fd, proto, opts); - applyopts(xfd->fd, opts, PH_PREBIND); + applyopts(xfd, -1, opts, PH_PREBIND); - applyopts(xfd->fd, opts, PH_BIND); + applyopts(xfd, -1, opts, PH_BIND); if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) { Msg4(level, "bind(%d, {%s}, "F_socklen"): %s", xfd->fd, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen, @@ -136,28 +136,27 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') { applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_FD); } else { - applyopts(xfd->fd, opts, PH_FD); + applyopts(xfd, -1, opts, PH_FD); } } #endif - applyopts(xfd->fd, opts, PH_PASTBIND); + applyopts(xfd, -1, opts, PH_PASTBIND); #if WITH_UNIX if (us->sa_family == AF_UNIX) { if (((union sockaddr_union *)us)->un.sun_path[0] != '\0') { - /*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/ applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_EARLY); applyopts_named(((struct sockaddr_un *)us)->sun_path, opts, PH_PREOPEN); } else { - applyopts(xfd->fd, opts, PH_EARLY); - applyopts(xfd->fd, opts, PH_PREOPEN); + applyopts(xfd, -1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_PREOPEN); } } #endif /* WITH_UNIX */ - applyopts(xfd->fd, opts, PH_PRELISTEN); + applyopts(xfd, -1, opts, PH_PRELISTEN); retropt_int(opts, OPT_BACKLOG, &backlog); - applyopts(xfd->fd, opts, PH_LISTEN); + applyopts(xfd, -1, opts, PH_LISTEN); if (Listen(xfd->fd, backlog) < 0) { Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno)); return STAT_RETRYLATER; @@ -419,9 +418,9 @@ int _xioopen_accept_fd( } } - applyopts(xfd->fd, opts, PH_FD); - applyopts(xfd->fd, opts, PH_PASTSOCKET); - applyopts(xfd->fd, opts, PH_CONNECTED); + applyopts(xfd, -1, opts, PH_FD); + applyopts(xfd, -1, opts, PH_PASTSOCKET); + applyopts(xfd, -1, opts, PH_CONNECTED); if ((result = _xio_openlate(xfd, opts)) < 0) return result; diff --git a/xio-named.c b/xio-named.c index ceae370..0d07356 100644 --- a/xio-named.c +++ b/xio-named.c @@ -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 { diff --git a/xio-openssl.c b/xio-openssl.c index dcb4d63..dfcead4 100644 --- a/xio-openssl.c +++ b/xio-openssl.c @@ -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); diff --git a/xio-pipe.c b/xio-pipe.c index 5b7d077..782e0d1 100644 --- a/xio-pipe.c +++ b/xio-pipe.c @@ -24,13 +24,14 @@ const struct addrdesc xioaddr_pipe = { "PIPE", 3, xioopen_fifo, GROUP_FD|GR /* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with options */ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) { + struct single *sfd = &sock->stream; struct opt *opts2; int filedes[2]; int numleft; int result; - if (applyopts_single(&sock->stream, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); + if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; + applyopts(sfd, -1, opts, PH_INIT); if (Pipe(filedes) != 0) { Error2("pipe(%p): %s", filedes, strerror(errno)); @@ -39,15 +40,15 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) { /*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/ sock->common.tag = XIO_TAG_RDWR; - sock->stream.dtype = XIODATA_PIPE; - sock->stream.fd = filedes[0]; - sock->stream.para.bipipe.fdout = filedes[1]; - sock->stream.para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */ - applyopts_cloexec(sock->stream.fd, opts); - applyopts_cloexec(sock->stream.para.bipipe.fdout, opts); + sfd->dtype = XIODATA_PIPE; + sfd->fd = filedes[0]; + sfd->para.bipipe.fdout = filedes[1]; + sfd->para.bipipe.socktype = SOCK_STREAM; /* due to socketpair reuse */ + applyopts_cloexec(sfd->fd, opts); + applyopts_cloexec(sfd->para.bipipe.fdout, opts); /* one-time and input-direction options, no second application */ - retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof); + retropt_bool(opts, OPT_IGNOREEOF, &sfd->ignoreeof); /* here we copy opts! */ if ((opts2 = copyopts(opts, GROUP_FIFO)) == NULL) { @@ -55,18 +56,16 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) { } /* apply options to first FD */ - if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) { + if ((result = applyopts(sfd, -1, opts, PH_ALL)) < 0) { return result; } - if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) { + if ((result = applyopts_single(sfd, opts, PH_ALL)) < 0) { return result; } /* apply options to second FD */ - if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0) - { - return result; - } + if (applyopts(&sock->stream, sfd->para.bipipe.fdout, opts2, PH_ALL) < 0) + return -1; if ((numleft = leftopts(opts)) > 0) { showleft(opts); @@ -78,7 +77,8 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) { /* open a named or unnamed pipe/fifo */ -static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, groups_t groups, int dummy1, int dummy2, int dummy3) { +static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { + struct single *sfd = &xfd->stream; const char *pipename = argv[1]; int rw = (xioflags & XIO_ACCMODE); #if HAVE_STAT64 @@ -92,19 +92,20 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof int result; if (argc == 1) { - return xioopen_fifo_unnamed(fd, fd->stream.opts); + return xioopen_fifo_unnamed(xfd, sfd->opts); } if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); } - if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); + if (applyopts_single(sfd, opts, PH_INIT) < 0) + return -1; + applyopts(sfd, -1, opts, PH_INIT); retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); applyopts_named(pipename, opts, PH_EARLY); /* umask! */ - applyopts(-1, opts, PH_EARLY); + applyopts(sfd, -1, opts, PH_EARLY); if (opt_unlink_early) { if (Unlink(pipename) < 0) { @@ -149,10 +150,10 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof } if (opt_unlink_close) { - if ((fd->stream.unlink_close = strdup(pipename)) == NULL) { + if ((sfd->unlink_close = strdup(pipename)) == NULL) { Error1("strdup(\"%s\"): out of memory", pipename); } - fd->stream.opt_unlink_close = true; + sfd->opt_unlink_close = true; } } else { /* exists */ @@ -160,19 +161,18 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof Notice3("opening %s \"%s\" for %s", filetypenames[(pipstat.st_mode&S_IFMT)>>12], pipename, ddirection[rw]); - /*applyopts_early(pipename, opts);*/ applyopts_named(pipename, opts, PH_EARLY); } if ((result = _xioopen_open(pipename, rw, opts)) < 0) { return result; } - fd->stream.fd = result; + sfd->fd = result; applyopts_named(pipename, opts, PH_FD); - applyopts(fd->stream.fd, opts, PH_FD); - applyopts_cloexec(fd->stream.fd, opts); - return _xio_openlate(&fd->stream, opts); + applyopts(sfd, -1, opts, PH_FD); + applyopts_cloexec(sfd->fd, opts); + return _xio_openlate(sfd, opts); } #endif /* WITH_PIPE */ diff --git a/xio-posixmq.c b/xio-posixmq.c index c88dba1..4a4b504 100644 --- a/xio-posixmq.c +++ b/xio-posixmq.c @@ -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); diff --git a/xio-progcall.c b/xio-progcall.c index 337db1f..e5ec2e5 100644 --- a/xio-progcall.c +++ b/xio-progcall.c @@ -47,12 +47,14 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P return<0: error occurred, assume parent process and no child exists !!! */ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ - struct single *fd, + struct single *sfd, groups_t groups, - struct opt **copts, /* in: opts; out: opts for child */ + struct opt **optsp, /* in: opts; out: opts for parent/child */ int *duptostderr /* out: redirect stderr to output fd */ ) { - struct opt *popts; /* parent process options */ + struct opt *opts; /* common options */ + struct opt *popts; /* parent options */ + struct opt *copts; /* child options */ int numleft; int d, sv[2], rdpip[2], wrpip[2]; int rw = (xioflags & XIO_ACCMODE); @@ -78,21 +80,21 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ char *tn = NULL; int trigger[2]; /* [0] watched by parent, [1] closed by child when ready */ - popts = moveopts(*copts, GROUP_ALL); - if (applyopts_single(fd, popts, PH_INIT) < 0) return -1; - applyopts2(-1, popts, PH_INIT, PH_EARLY); + opts = *optsp; + if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; + applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY); - retropt_bool(popts, OPT_NOFORK, &nofork); + retropt_bool(opts, OPT_NOFORK, &nofork); withfork = !nofork; - retropt_bool(popts, OPT_PIPES, &usepipes); + retropt_bool(opts, OPT_PIPES, &usepipes); #if HAVE_PTY - retropt_bool(popts, OPT_PTY, &usebestpty); + retropt_bool(opts, OPT_PTY, &usebestpty); #if HAVE_OPENPTY - retropt_bool(popts, OPT_OPENPTY, &useopenpty); + retropt_bool(opts, OPT_OPENPTY, &useopenpty); #endif #if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC) - retropt_bool(popts, OPT_PTMX, &useptmx); + retropt_bool(opts, OPT_PTMX, &useptmx); #endif usepty = (usebestpty #if HAVE_OPENPTY @@ -108,12 +110,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } #endif /* HAVE_PTY */ - if (retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi) >= 0) { + if (retropt_ushort(opts, OPT_FDIN, (unsigned short *)&fdi) >= 0) { if ((xioflags&XIO_ACCMODE) == XIO_RDONLY) { Error("_xioopen_foxec(): option fdin is useless in read-only mode"); } } - if (retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) { + if (retropt_ushort(opts, OPT_FDOUT, (unsigned short *)&fdo) >= 0) { if ((xioflags&XIO_ACCMODE) == XIO_WRONLY) { Error("_xioopen_foxec(): option fdout is useless in write-only mode"); } @@ -125,7 +127,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /*!! free something */ return -1; } - fd->flags |= XIO_DOESCHILD; + sfd->flags |= XIO_DOESCHILD; #if HAVE_PTY Notice2("forking off child, using %s for %s", @@ -137,7 +139,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ ddirection[rw]); #endif /* HAVE_PTY */ } - applyopts(-1, popts, PH_PREBIGEN); + applyopts(sfd, -1, opts, PH_PREBIGEN); if (!withfork) { /*0 struct single *stream1, *stream2;*/ @@ -147,10 +149,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /*!! free something */ return -1; } - fd->flags |= XIO_DOESEXEC; + sfd->flags |= XIO_DOESEXEC; - free(*copts); - *copts = moveopts(popts, GROUP_ALL); + /* Only one process, no parent,child */ + if ((copts = moveopts(opts, GROUP_ALL)) == NULL) { + /*!! free something */ + return -1; + } #if 0 /*!! */ if (sock1->tag == XIO_TAG_DUAL) { @@ -207,7 +212,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/ } } - } else + /* !withfork */ + } else /* withfork */ #if HAVE_PTY if (usepty) { @@ -216,7 +222,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ #elif HAVE_DEV_PTC # define PTMX "/dev/ptc" /* AIX 4.3.3 */ #endif - fd->dtype = XIODATA_PTY; + sfd->dtype = XIODATA_PTY; #if HAVE_DEV_PTMX || HAVE_DEV_PTC if (usebestpty || useptmx) { if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) { @@ -264,30 +270,30 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } } #endif /* HAVE_OPENPTY */ - free(*copts); - if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) { + /* withfork use_pty */ + if ((copts = moveopts(opts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS|GROUP_NAMED)) == NULL) { return -1; } + popts = opts; applyopts_cloexec(ptyfd, popts);/*!*/ /* exec:...,pty did not kill child process under some circumstances */ - if (fd->howtoend == END_UNSPEC) { - fd->howtoend = END_CLOSE_KILL; + if (sfd->howtoend == END_UNSPEC) { + sfd->howtoend = END_CLOSE_KILL; } /* this for parent, was after fork */ - applyopts(ptyfd, popts, PH_FD); - applyopts(ptyfd, popts, PH_LATE); - if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; + applyopts(sfd, ptyfd, popts, PH_FD); + sfd->fd = ptyfd; - fd->fd = ptyfd; - - } else + /* end withfork, use_pty */ + } else /* end withfork, use_pty */ #endif /* HAVE_PTY */ + if (usepipes) { - struct opt *popts2, *copts2; + /* withfork usepipes */ if (rw == XIO_RDWR) - fd->dtype = XIODATA_2PIPE; + sfd->dtype = XIODATA_2PIPE; if (rw != XIO_WRONLY) { if (Pipe(rdpip) < 0) { Error2("pipe(%p): %s", rdpip, strerror(errno)); @@ -296,19 +302,18 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } /*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/ /* rdpip[0]: read by socat; rdpip[1]: write by child */ - free(*copts); - if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) + + /* withfork usepipes */ + if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { return -1; } - - popts2 = copyopts(popts, GROUP_ALL); - copts2 = copyopts(*copts, GROUP_ALL); + popts = opts; if (rw != XIO_WRONLY) { applyopts_cloexec(rdpip[0], popts); - applyopts(rdpip[0], popts, PH_FD); - applyopts(rdpip[1], *copts, PH_FD); + applyopts(NULL, rdpip[0], popts, PH_FD); + applyopts(NULL, rdpip[1], copts, PH_FD); } if (rw != XIO_RDONLY) { @@ -317,65 +322,70 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ return -1; } } - /*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/ /* wrpip[1]: write by socat; wrpip[0]: read by child */ if (rw != XIO_RDONLY) { - applyopts_cloexec(wrpip[1], popts2); - applyopts(wrpip[1], popts2, PH_FD); - applyopts(wrpip[0], copts2, PH_FD); + applyopts_cloexec(wrpip[1], popts); + applyopts(NULL, wrpip[1], popts, PH_FD); + applyopts(NULL, wrpip[0], copts, PH_FD); } - if (fd->howtoend == END_UNSPEC) { - fd->howtoend = END_CLOSE_KILL; + if (sfd->howtoend == END_UNSPEC) { + sfd->howtoend = END_CLOSE_KILL; } /* this for parent, was after fork */ switch (rw) { - case XIO_RDONLY: fd->fd = rdpip[0]; break; - case XIO_WRONLY: fd->fd = wrpip[1]; break; - case XIO_RDWR: fd->fd = rdpip[0]; - fd->para.exec.fdout = wrpip[1]; + case XIO_RDONLY: sfd->fd = rdpip[0]; break; + case XIO_WRONLY: sfd->fd = wrpip[1]; break; + case XIO_RDWR: sfd->fd = rdpip[0]; + sfd->para.exec.fdout = wrpip[1]; break; } - applyopts(fd->fd, popts, PH_FD); - applyopts(fd->fd, popts, PH_LATE); - if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; + applyopts(sfd, -1, popts, PH_FD); + applyopts(sfd, -1, popts, PH_LATE); + if (applyopts_single(sfd, popts, PH_LATE) < 0) + return -1; + + /* end withfork, use_pipes */ } else { + /* withfork, socketpair */ + d = AF_UNIX; - retropt_int(popts, OPT_PROTOCOL_FAMILY, &d); - result = xiosocketpair(popts, d, SOCK_STREAM, 0, sv); + retropt_int(opts, OPT_PROTOCOL_FAMILY, &d); + result = xiosocketpair(opts, d, SOCK_STREAM, 0, sv); if (result < 0) { return -1; } - /*0 Info5("socketpair(%d, %d, %d, {%d,%d})", - d, type, protocol, sv[0], sv[1]);*/ - free(*copts); - if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { + + /* withfork socketpair */ + if ((copts = moveopts(opts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) { return -1; } - applyopts(sv[0], *copts, PH_PASTSOCKET); - applyopts(sv[1], popts, PH_PASTSOCKET); + popts = opts; + applyopts(NULL, sv[0], copts, PH_PASTSOCKET); + applyopts(NULL, sv[1], popts, PH_PASTSOCKET); - applyopts_cloexec(sv[0], *copts); - applyopts(sv[0], *copts, PH_FD); - applyopts(sv[1], popts, PH_FD); + applyopts_cloexec(sv[0], copts); + applyopts(NULL, sv[0], copts, PH_FD); + applyopts(NULL, sv[1], popts, PH_FD); - applyopts(sv[0], *copts, PH_PREBIND); - applyopts(sv[0], *copts, PH_BIND); - applyopts(sv[0], *copts, PH_PASTBIND); - applyopts(sv[1], popts, PH_PREBIND); - applyopts(sv[1], popts, PH_BIND); - applyopts(sv[1], popts, PH_PASTBIND); + applyopts(NULL, sv[0], copts, PH_PREBIND); + applyopts(NULL, sv[0], copts, PH_BIND); + applyopts(NULL, sv[0], copts, PH_PASTBIND); + applyopts(NULL, sv[1], popts, PH_PREBIND); + applyopts(NULL, sv[1], popts, PH_BIND); + applyopts(NULL, sv[1], popts, PH_PASTBIND); - if (fd->howtoend == END_UNSPEC) { - fd->howtoend = END_SHUTDOWN_KILL; + if (sfd->howtoend == END_UNSPEC) { + sfd->howtoend = END_SHUTDOWN_KILL; } /* this for parent, was after fork */ - fd->fd = sv[0]; - applyopts(fd->fd, popts, PH_FD); + sfd->fd = sv[0]; + applyopts(sfd, -1, popts, PH_FD); + /* end withfork, socketpair */ } - retropt_bool(*copts, OPT_STDERR, &withstderr); + retropt_bool(copts, OPT_STDERR, &withstderr); xiosetchilddied(); /* set SIGCHLD handler */ @@ -387,7 +397,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } } if (!withfork || pid == 0) { /* in single process, or in child */ - applyopts_optgroup(-1, *copts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS); + applyopts_optgroup(sfd, -1, copts, GROUP_PROCESS); if (withfork) { Close(trigger[0]); /* in child: not needed here */ /* The child should have default handling for SIGCHLD. */ @@ -398,9 +408,9 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ #if HAVE_PTY if (usepty) { - applyopts_named(tn, *copts, PH_PREOPEN); - applyopts_named(tn, *copts, PH_EARLY); - applyopts_named(tn, *copts, PH_FD); + applyopts_named(tn, copts, PH_PREOPEN); + applyopts_named(tn, copts, PH_EARLY); + applyopts_named(tn, copts, PH_FD); if (ttyfd < 0) { if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) { @@ -427,7 +437,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ #endif /* this for child, was after fork */ - applyopts(ttyfd, *copts, PH_FD); + applyopts(NULL, ttyfd, copts, PH_FD); Info1("opened pseudo terminal %s", tn); Close(ptyfd); @@ -451,11 +461,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } if ((rw == XIO_RDONLY || fdi != ttyfd) && (rw == XIO_WRONLY || fdo != ttyfd)) { - applyopts_cloexec(ttyfd, *copts); + applyopts_cloexec(ttyfd, copts); } - applyopts(ttyfd, *copts, PH_LATE); - applyopts(ttyfd, *copts, PH_LATE2); + applyopts(NULL, ttyfd, copts, PH_LATE); + applyopts(NULL, ttyfd, copts, PH_LATE2); } else #endif /* HAVE_PTY */ if (usepipes) { @@ -492,8 +502,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ return -1; } Close(rdpip[1]); - /*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/ - /*0 applyopts_cloexec(fdo, *copts);*/ } if (rw != XIO_RDONLY && wrpip[0] != fdi) { /* make sure that the internal diagnostic socket pair fds do not conflict @@ -504,15 +512,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ return -1; } Close(wrpip[0]); - /*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/ - /*0 applyopts_cloexec(wrpip[0], *copts);*/ /* option is already consumed! */ /* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */ } - applyopts(fdi, *copts, PH_LATE); - applyopts(fdo, *copts, PH_LATE); - applyopts(fdi, *copts, PH_LATE2); - applyopts(fdo, *copts, PH_LATE2); + applyopts(NULL, fdi, copts, PH_LATE); + applyopts(NULL, fdo, copts, PH_LATE); + applyopts(NULL, fdi, copts, PH_LATE2); + applyopts(NULL, fdo, copts, PH_LATE2); } else { /* socketpair */ Close(sv[0]); @@ -535,12 +541,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ /*0 Info2("dup2(%d, %d)", sv[1], fdo);*/ } if (fdi != sv[1] && fdo != sv[1]) { - applyopts_cloexec(sv[1], *copts); + applyopts_cloexec(sv[1], copts); Close(sv[1]); } - applyopts(fdi, *copts, PH_LATE); - applyopts(fdi, *copts, PH_LATE2); + applyopts(NULL, fdi, copts, PH_LATE); + applyopts(NULL, fdi, copts, PH_LATE2); } if (withfork) { Info("notifying parent that child process is ready"); @@ -548,8 +554,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } } /* withfork */ else { - applyopts(-1, *copts, PH_LATE); - applyopts(-1, *copts, PH_LATE2); + applyopts(NULL, -1, copts, PH_LATE); + applyopts(NULL, -1, copts, PH_LATE2); } _xioopen_setdelayeduser(); if (withstderr) { @@ -558,6 +564,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ *duptostderr = -1; } + *optsp = copts; return 0; /* indicate child process */ } @@ -565,12 +572,6 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ Notice1("forked off child process "F_pid, pid); Close(trigger[1]); /* in parent */ -#if 0 - if ((popts = copyopts(*copts, - GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL) - return STAT_RETRYLATER; -#endif - #if HAVE_PTY if (usepty) { # if 0 @@ -586,13 +587,12 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ } else { Close(sv[1]); } - fd->para.exec.pid = pid; + sfd->para.exec.pid = pid; - if (applyopts_single(fd, popts, PH_LATE) < 0) return -1; - applyopts_signal(fd, popts); - applyopts(-1, popts, PH_LATE); - applyopts(-1, popts, PH_LATE2); - applyopts(-1, popts, PH_PASTEXEC); + if (applyopts_single(sfd, popts, PH_LATE) < 0) return -1; + applyopts(sfd, -1, popts, PH_LATE); + applyopts(sfd, -1, popts, PH_LATE2); + applyopts(sfd, -1, popts, PH_PASTEXEC); if ((numleft = leftopts(popts)) > 0) { showleft(popts); Error1("INTERNAL: %d option(s) remained unused", numleft); @@ -607,6 +607,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */ Info("child process notified parent that it is ready"); } + applyopts(sfd, ptyfd, popts, PH_LATE); + if (applyopts_single(sfd, popts, PH_LATE) < 0) + return -1; + + *optsp = popts; return pid; /* indicate parent (main) process */ } #endif /* WITH_EXEC || WITH_SYSTEM */ diff --git a/xio-proxy.c b/xio-proxy.c index a14c70f..80fe29a 100644 --- a/xio-proxy.c +++ b/xio-proxy.c @@ -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; diff --git a/xio-pty.c b/xio-pty.c index 8e35e91..49a2418 100644 --- a/xio-pty.c +++ b/xio-pty.c @@ -30,6 +30,7 @@ const struct optdesc opt_pty_intervall = { "pty-interval", NULL, OPT_P static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { /* we expect the form: filename */ + struct single *sfd = &xfd->stream; int ptyfd = -1, ttyfd = -1; #if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC) bool useptmx = false; /* use /dev/ptmx or equivalent */ @@ -51,10 +52,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl Error2("%s: wrong number of parameters (%d instead of 0)", argv[0], argc-1); } - xfd->stream.howtoend = END_CLOSE; + sfd->howtoend = END_CLOSE; - if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); + if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; + applyopts(sfd, -1, opts, PH_INIT); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); @@ -88,10 +89,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl retropt_timespec(opts, OPT_PTY_INTERVALL, &pollintv); #endif /* HAVE_POLL */ - if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; - applyopts2(-1, opts, PH_INIT, PH_EARLY); + if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1; + applyopts2(sfd, -1, opts, PH_INIT, PH_EARLY); - applyopts(-1, opts, PH_PREBIGEN); + applyopts(sfd, -1, opts, PH_PREBIGEN); #if defined(HAVE_DEV_PTMX) # define PTMX "/dev/ptmx" /* Linux */ @@ -155,10 +156,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl ptyname, linkname, strerror(errno)); } if (opt_unlink_close) { - if ((xfd->stream.unlink_close = strdup(linkname)) == NULL) { + if ((sfd->unlink_close = strdup(linkname)) == NULL) { Error1("strdup(\"%s\"): out of memory", linkname); } - xfd->stream.opt_unlink_close = true; + sfd->opt_unlink_close = true; } } @@ -166,9 +167,9 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl applyopts_named(ptyname, opts, PH_FD); applyopts_cloexec(ptyfd, opts);/*!*/ - xfd->stream.dtype = XIODATA_PTY; + sfd->dtype = XIODATA_PTY; - applyopts(ptyfd, opts, PH_FD); + applyopts(sfd, ptyfd, opts, PH_FD); { /* special handling of user-late etc.; with standard behaviour (up to @@ -196,9 +197,10 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl } - xfd->stream.fd = ptyfd; - applyopts(ptyfd, opts, PH_LATE); - if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1; + sfd->fd = ptyfd; + applyopts(sfd, -1, opts, PH_LATE); + if (applyopts_single(sfd, opts, PH_LATE) < 0) + return -1; #if HAVE_POLL /* if you can and wish: */ diff --git a/xio-rawip.c b/xio-rawip.c index fe05e95..467e088 100644 --- a/xio-rawip.c +++ b/xio-rawip.c @@ -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 = diff --git a/xio-readline.c b/xio-readline.c index 233366b..42b076d 100644 --- a/xio-readline.c +++ b/xio-readline.c @@ -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); diff --git a/xio-socket.c b/xio-socket.c index fff32d3..ba0960c 100644 --- a/xio-socket.c +++ b/xio-socket.c @@ -167,32 +167,32 @@ const struct optdesc opt_so_peercred = { "so-peercred", "peercred", OPT_SO_PEERC const struct optdesc opt_so_priority = { "so-priority", "priority", OPT_SO_PRIORITY, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_PRIORITY}; #endif #ifdef SO_REUSEPORT /* AIX 4.3.3, BSD, HP-UX, Linux >=3.9 */ -const struct optdesc opt_so_reuseport= { "so-reuseport","reuseport",OPT_SO_REUSEPORT,GROUP_SOCKET, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEPORT }; +const struct optdesc opt_so_reuseport = { "so-reuseport","reuseport",OPT_SO_REUSEPORT,GROUP_SOCKET, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEPORT }; #endif /* defined(SO_REUSEPORT) */ #ifdef SO_SECURITY_AUTHENTICATION const struct optdesc opt_so_security_authentication={"so-security-authentication","securityauthentication",OPT_SO_SECURITY_AUTHENTICATION,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_AUTHENTICATION}; #endif #ifdef SO_SECURITY_ENCRYPTION_NETWORK -const struct optdesc opt_so_security_encryption_network={"so-security-encryption-network","securityencryptionnetwork",OPT_SO_SECURITY_ENCRYPTION_NETWORK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_NETWORK}; +const struct optdesc opt_so_security_encryption_network= { "so-security-encryption-network","securityencryptionnetwork",OPT_SO_SECURITY_ENCRYPTION_NETWORK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_NETWORK}; #endif #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT -const struct optdesc opt_so_security_encryption_transport={"so-security-encryption-transport","securityencryptiontransport",OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_TRANSPORT}; +const struct optdesc opt_so_security_encryption_transport= { "so-security-encryption-transport","securityencryptiontransport",OPT_SO_SECURITY_ENCRYPTION_TRANSPORT,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_SECURITY_ENCRYPTION_TRANSPORT}; #endif #ifdef SO_USE_IFBUFS -const struct optdesc opt_so_use_ifbufs={ "so-use-ifbufs","useifbufs",OPT_SO_USE_IFBUFS,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_USE_IFBUFS}; +const struct optdesc opt_so_use_ifbufs= { "so-use-ifbufs","useifbufs",OPT_SO_USE_IFBUFS,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_USE_IFBUFS}; #endif /* SO_USE_IFBUFS */ #ifdef SO_USELOOPBACK /* AIX433, Solaris, HP-UX */ -const struct optdesc opt_so_useloopback={"so-useloopback","useloopback",OPT_SO_USELOOPBACK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT, SOL_SOCKET, SO_USELOOPBACK}; +const struct optdesc opt_so_useloopback= { "so-useloopback","useloopback",OPT_SO_USELOOPBACK,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT, SOL_SOCKET, SO_USELOOPBACK}; #endif /* SO_USELOOPBACK */ #ifdef SO_DGRAM_ERRIND /* Solaris */ -const struct optdesc opt_so_dgram_errind={"so-dgram-errind","dgramerrind",OPT_SO_DGRAM_ERRIND,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DGRAM_ERRIND}; +const struct optdesc opt_so_dgram_errind= { "so-dgram-errind","dgramerrind",OPT_SO_DGRAM_ERRIND,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DGRAM_ERRIND}; #endif /* SO_DGRAM_ERRIND */ #ifdef SO_DONTLINGER /* Solaris */ -const struct optdesc opt_so_dontlinger = {"so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER }; +const struct optdesc opt_so_dontlinger = { "so-dontlinger", "dontlinger", OPT_SO_DONTLINGER, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT,OFUNC_SOCKOPT,SOL_SOCKET,SO_DONTLINGER }; #endif /* the SO_PROTOTYPE is OS defined on Solaris, HP-UX; we lend this for a more general purpose */ -const struct optdesc opt_so_prototype = {"so-protocol", "protocol", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOCOL }; +const struct optdesc opt_so_prototype = { "so-protocol", "protocol", OPT_SO_PROTOTYPE, GROUP_SOCKET,PH_SOCKET, TYPE_INT,OFUNC_SPEC, SOL_SOCKET,SO_PROTOCOL }; #ifdef FIOSETOWN const struct optdesc opt_fiosetown = { "fiosetown", NULL, OPT_FIOSETOWN, GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_IOCTL, FIOSETOWN }; #endif @@ -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; } diff --git a/xio-socketpair.c b/xio-socketpair.c index 49396af..8b3f3cd 100644 --- a/xio-socketpair.c +++ b/xio-socketpair.c @@ -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(":") }; -/* 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); diff --git a/xio-socks.c b/xio-socks.c index 9795617..3885b36 100644 --- a/xio-socks.c +++ b/xio-socks.c @@ -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; diff --git a/xio-socks5.c b/xio-socks5.c index 30feb23..4f78b96 100644 --- a/xio-socks5.c +++ b/xio-socks5.c @@ -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; diff --git a/xio-stdio.c b/xio-stdio.c index 6c8d6dc..92bbb93 100644 --- a/xio-stdio.c +++ b/xio-stdio.c @@ -89,16 +89,16 @@ int xioopen_stdio_bi(xiofile_t *sock) { sock->dual.stream[1]->opts, PH_INIT) < 0) return -1; - applyopts(-1, sock->dual.stream[0]->opts, PH_INIT); - applyopts(-1, sock->dual.stream[1]->opts, PH_INIT); - if ((result = applyopts(-1, optspr, PH_EARLY)) < 0) + applyopts(sock->dual.stream[0], -1, sock->dual.stream[0]->opts, PH_INIT); + applyopts(sock->dual.stream[1], -1, sock->dual.stream[1]->opts, PH_INIT); + if ((result = applyopts(NULL, -1, optspr, PH_EARLY)) < 0) return result; - if ((result = applyopts(-1, optspr, PH_PREOPEN)) < 0) + if ((result = applyopts(NULL, -1, optspr, PH_PREOPEN)) < 0) return result; /* apply options to first FD */ if ((result = - applyopts(sock->dual.stream[0]->fd, + applyopts(sock->dual.stream[0], -1, sock->dual.stream[0]->opts, PH_ALL)) < 0) { return result; @@ -113,7 +113,7 @@ int xioopen_stdio_bi(xiofile_t *sock) { #endif /* apply options to second FD */ - if ((result = applyopts(sock->dual.stream[1]->fd, + if ((result = applyopts(sock->dual.stream[1], -1, sock->dual.stream[1]->opts, PH_ALL)) < 0) { return result; } diff --git a/xio-streams.c b/xio-streams.c index 298959c..e470f3e 100644 --- a/xio-streams.c +++ b/xio-streams.c @@ -43,18 +43,20 @@ void dummy(void) { if (0) { { ; #endif #ifdef I_POP - } else if (opt->desc->func == OFUNC_STREAMS_I_POP_ALL) { - while (Ioctl(fd, I_POP, 0) >= 0) { - Warn2("ioctl(%d, I_POP, 0): %s", fd, strerror(errno)); - } + 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) { - 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; - } + 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)); + rc = -1; + } + break; #endif #if 0 } } } diff --git a/xio-system.c b/xio-system.c index fe42473..e9f6b9e 100644 --- a/xio-system.c +++ b/xio-system.c @@ -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; } diff --git a/xio-termios.c b/xio-termios.c index 6edcea4..60209f7 100644 --- a/xio-termios.c +++ b/xio-termios.c @@ -12,7 +12,7 @@ /****** TERMIOS addresses ******/ #if _WITH_TERMIOS #if WITH_TERMIOS -const struct optdesc opt_tiocsctty={ "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC }; +const struct optdesc opt_tiocsctty = { "tiocsctty", "ctty",OPT_TIOCSCTTY, GROUP_TERMIOS, PH_LATE2, TYPE_BOOL, OFUNC_SPEC }; /* it is important for handling of these options that they have PH_FD */ const struct optdesc opt_brkint = { "brkint", NULL, OPT_BRKINT, GROUP_TERMIOS, PH_FD, TYPE_BOOL, OFUNC_TERMIOS_FLAG, 0, BRKINT }; diff --git a/xio-tun.c b/xio-tun.c index 718272b..4dc3bb6 100644 --- a/xio-tun.c +++ b/xio-tun.c @@ -46,6 +46,7 @@ static const struct optname xio_route_options[] = { #endif static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int dummy1, int dummy2, int dummy3) { + struct single *sfd = &xfd->stream; char *tundevice = NULL; char *tunname = NULL, *tuntype = NULL; int pf = /*! PF_UNSPEC*/ PF_INET; @@ -79,10 +80,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl /*========================= the tunnel interface =========================*/ Notice("creating tunnel network interface"); - applyopts_optgroup(-1, opts, PH_PRESOCKET, PH_PRESOCKET, GROUP_PROCESS); + applyopts_optgroup(&xfd->stream, -1, opts, GROUP_PROCESS); if ((result = _xioopen_open(tundevice, rw, opts)) < 0) return result; - xfd->stream.fd = result; + sfd->fd = result; /* prepare configuration of the new network interface */ memset(&ifr, 0, sizeof(ifr)); @@ -113,10 +114,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl } } - if (Ioctl(xfd->stream.fd, TUNSETIFF, &ifr) < 0) { + if (Ioctl(sfd->fd, TUNSETIFF, &ifr) < 0) { Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s", - xfd->stream.fd, ifr.ifr_name, strerror(errno)); - Close(xfd->stream.fd); + sfd->fd, ifr.ifr_name, strerror(errno)); + Close(sfd->fd); } Notice1("TUN: new device \"%s\"", ifr.ifr_name); @@ -125,7 +126,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl /* we seem to need a socket for manipulating the interface */ if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) { Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno)); - sockfd = xfd->stream.fd; /* desparate fallback attempt */ + sockfd = sfd->fd; /* desparate fallback attempt */ } /*--------------------- setting interface address and netmask ------------*/ @@ -135,7 +136,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl return STAT_RETRYLATER; } if ((result = xioparsenetwork(ifaddr, pf, &network, - xfd->stream.para.socket.ip.ai_flags)) + sfd->para.socket.ip.ai_flags)) != STAT_OK) { /*! recover */ return result; @@ -157,16 +158,16 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl free(ifaddr); } /*--------------------- setting interface flags --------------------------*/ - applyopts_single(&xfd->stream, opts, PH_FD); + applyopts_single(sfd, opts, PH_FD); - _xiointerface_apply_iff(sockfd, ifr.ifr_name, xfd->stream.para.interface.iff_opts); + _xiointerface_apply_iff(sockfd, ifr.ifr_name, sfd->para.interface.iff_opts); - applyopts(xfd->stream.fd, opts, PH_FD); - applyopts_cloexec(xfd->stream.fd, opts); + applyopts(sfd, -1, opts, PH_FD); + applyopts_cloexec(sfd->fd, opts); - applyopts_fchown(xfd->stream.fd, opts); + applyopts_fchown(sfd->fd, opts); - if ((result = _xio_openlate(&xfd->stream, opts)) < 0) + if ((result = _xio_openlate(sfd, opts)) < 0) return result; return 0; diff --git a/xio-udp.c b/xio-udp.c index 6c4d4c6..8c75ba9 100644 --- a/xio-udp.c +++ b/xio-udp.c @@ -149,7 +149,7 @@ int _xioopen_ipdgram_listen(struct single *sfd, } doreuseaddr |= (retropt_2integrals(opts, OPT_SO_REUSEADDR, &reuseaddr, ¬null) >= 0); - applyopts(sfd->fd, opts, PH_PASTSOCKET); + applyopts(sfd, -1, opts, PH_PASTSOCKET); /* SO_REUSEADDR handling of UDP sockets is helpful on Solaris */ if (doreuseaddr) { @@ -163,8 +163,8 @@ int _xioopen_ipdgram_listen(struct single *sfd, } } applyopts_cloexec(sfd->fd, opts); - applyopts(sfd->fd, opts, PH_PREBIND); - applyopts(sfd->fd, opts, PH_BIND); + applyopts(sfd, -1, opts, PH_PREBIND); + applyopts(sfd, -1, opts, PH_BIND); if (Bind(sfd->fd, &us->soa, uslen) < 0) { Error4("bind(%d, {%s}, "F_socklen"): %s", sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)), @@ -176,7 +176,7 @@ int _xioopen_ipdgram_listen(struct single *sfd, Error4("getsockname(%d, %p, {%d}): %s", sfd->fd, &us->soa, uslen, strerror(errno)); } - applyopts(sfd->fd, opts, PH_PASTBIND); + applyopts(sfd, -1, opts, PH_PASTBIND); if (ipproto == IPPROTO_UDP) { Notice1("listening on UDP %s", @@ -255,7 +255,7 @@ int _xioopen_ipdgram_listen(struct single *sfd, break; } /* end of the big while loop */ - applyopts(sfd->fd, opts, PH_CONNECT); + applyopts(sfd, -1, opts, PH_CONNECT); if ((result = Connect(sfd->fd, &them->soa, themlen)) < 0) { Error4("connect(%d, {%s}, "F_socklen"): %s", sfd->fd, @@ -274,7 +274,7 @@ int _xioopen_ipdgram_listen(struct single *sfd, sfd->howtoend = END_SHUTDOWN; applyopts_fchown(sfd->fd, opts); - applyopts(sfd->fd, opts, PH_LATE); + applyopts(sfd, -1, opts, PH_LATE); if ((result = _xio_openlate(sfd, opts)) < 0) return result; @@ -287,6 +287,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, groups_t groups, int pf, int ipproto, int protname) { + struct single *sfd = &xfd->stream; const char *portname = argv[1]; union sockaddr_union us; int socktype = SOCK_DGRAM; @@ -314,8 +315,9 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts, retropt_socket_pf(opts, &pf); retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto); - if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); + if (applyopts_single(sfd, opts, PH_INIT) < 0) + return -1; + applyopts(sfd, -1, opts, PH_INIT); uslen = socket_init(pf, &us); retropt_bind(opts, pf, socktype, ipproto, @@ -383,7 +385,7 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname, xfd->howtoend = END_SHUTDOWN; if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); xfd->salen = sizeof(xfd->peersa); if ((result = diff --git a/xio-unix.c b/xio-unix.c index f5d6263..453c592 100644 --- a/xio-unix.c +++ b/xio-unix.c @@ -148,10 +148,10 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i } if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_offset(xfd, opts); - applyopts(-1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_EARLY); uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); @@ -229,9 +229,9 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts, retropt_socket_pf(opts, &pf); xfd->howtoend = END_SHUTDOWN; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); applyopts_offset(xfd, opts); - applyopts(-1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_EARLY); themlen = xiosetunix(pf, &them, name, abstract, xfd->para.socket.un.tight); @@ -361,6 +361,7 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i socklen_t uslen = sizeof(us); bool needbind = false; bool opt_unlink_close = (abstract != 1); + int result; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", @@ -394,20 +395,24 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i Error1("Option \"%s\" only with bind option", namedopt->desc->defname); } + if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; + applyopts(xfd, -1, opts, PH_INIT); + + result = + _xioopen_dgram_sendto(needbind?(union sockaddr_union *)&us:NULL, uslen, + opts, xioflags, xfd, groups, + pf, socktype, protocol, 0); + if (result != 0) { + return result; + } + if (opt_unlink_close && needbind) { if ((xfd->unlink_close = strdup(us.un.sun_path)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } - - if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1; - applyopts(-1, opts, PH_INIT); - - return - _xioopen_dgram_sendto(needbind?&us:NULL, uslen, - opts, xioflags, xfd, groups, - pf, socktype, protocol, 0); + return STAT_OK; } @@ -438,7 +443,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, retropt_socket_pf(opts, &pf); xfd->howtoend = END_NONE; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_offset(xfd, opts); @@ -447,7 +452,7 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); } - applyopts(-1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_EARLY); uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); @@ -519,7 +524,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, retropt_socket_pf(opts, &pf); xfd->howtoend = END_SHUTDOWN; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_offset(xfd, opts); @@ -528,7 +533,7 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts, retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); } - applyopts(-1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_EARLY); uslen = xiosetunix(pf, &us.un, name, abstract, xfd->para.socket.un.tight); @@ -607,11 +612,11 @@ _xioopen_unix_client(xiosingle_t *xfd, int xioflags, groups_t groups, retropt_socket_pf(opts, &pf); xfd->howtoend = END_SHUTDOWN; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; - applyopts(-1, opts, PH_INIT); + applyopts(xfd, -1, opts, PH_INIT); applyopts_offset(xfd, opts); retropt_int(opts, OPT_SO_TYPE, &socktype); retropt_int(opts, OPT_SO_PROTOTYPE, &protocol); - applyopts(-1, opts, PH_EARLY); + applyopts(xfd, -1, opts, PH_EARLY); themlen = xiosetunix(pf, &them.un, name, abstract, xfd->para.socket.un.tight); if (!(ABSTRACT && abstract)) { diff --git a/xio-vsock.c b/xio-vsock.c index ae86d6b..8fc4a90 100644 --- a/xio-vsock.c +++ b/xio-vsock.c @@ -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; diff --git a/xio.h b/xio.h index 8d1cb05..efd5e99 100644 --- a/xio.h +++ b/xio.h @@ -172,7 +172,7 @@ typedef struct single { size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/ xiolock_t lock; /* parameters of lockfile */ bool havelock; /* we are happy owner of the above lock */ - int triggerfd; /* close this FD in child process to notify parent */ + int triggerfd; /* in child process close this FD to notify parent */ bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */ /* until here, keep consistent with bipipe.dual ! */ int argc; /* number of fields in argv */ diff --git a/xiohelp.c b/xiohelp.c index 60689e2..fc276c9 100644 --- a/xiohelp.c +++ b/xiohelp.c @@ -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 ""; + } + return optiontypenames[typnum]; +} + int xioopenhelp(FILE *of, int level /* 0..only addresses, 1..and options */ ) { diff --git a/xiohelp.h b/xiohelp.h index c6767bf..cd3fa5b 100644 --- a/xiohelp.h +++ b/xiohelp.h @@ -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 */ ); diff --git a/xioopts.c b/xioopts.c index 5aca01f..4ba3058 100644 --- a/xioopts.c +++ b/xioopts.c @@ -12,6 +12,7 @@ #include "xiomodes.h" #include "xiolockfile.h" #include "nestlex.h" +#include "xiohelp.h" bool xioopts_ignoregroups; @@ -151,6 +152,7 @@ bool xioopts_ignoregroups; static int applyopt_offset(struct single *xfd, struct opt *opt); +static int applyopt(struct single *sfd, int fd, struct opt *opt); /* address options - keep this array strictly alphabetically sorted for @@ -3253,606 +3255,684 @@ 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 (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 (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; - } #if HAVE_LSEEK64 - } else if (opt->desc->func == OFUNC_SEEK64) { - /*! 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)); - return -1; - } +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)); + return -1; + } + return 0; +} #endif /* HAVE_LSEEK64 */ - } else if (opt->desc->func == OFUNC_FCNTL) { - int flag; +int applyopt_fcntl( + int fd, + struct opt *opt) +{ + int flag; - /* retrieve existing flag setttings */ - if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) { - Error3("fcntl(%d, %d): %s", - fd, opt->desc->major, strerror(errno)); - return -1; - } else { - if (opt->value.u_bool) { - flag |= opt->desc->minor; - } else { - flag &= ~opt->desc->minor; - } - if (Fcntl_l(fd, opt->desc->major, flag) < 0) { - Error4("fcntl(%d, %d, %d): %s", - fd, opt->desc->major, flag, strerror(errno)); - return -1; - } - } + /* retrieve existing flag setttings */ + if ((flag = Fcntl(fd, opt->desc->major-1)) < 0) { + Error3("fcntl(%d, %d): %s", + fd, opt->desc->major, strerror(errno)); + return -1; + } else { + if (opt->value.u_bool) { + flag |= opt->desc->minor; + } else { + flag &= ~opt->desc->minor; + } + if (Fcntl_l(fd, opt->desc->major, flag) < 0) { + Error4("fcntl(%d, %d, %d): %s", + fd, opt->desc->major, flag, + strerror(errno)); + return -1; + } + } + return 0; +} - } else if (opt->desc->func == OFUNC_IOCTL) { - 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; - } +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) { - long val; - int getreq = opt->desc->major; - int setreq = opt->desc->minor; - long mask = opt->desc->arg3; +int applyopt_ioctl_mask_long( + int fd, + struct opt *opt) +{ + long val; + int getreq = opt->desc->major; + int setreq = opt->desc->minor; + long mask = opt->desc->arg3; - if (Ioctl(fd, getreq, (void *)&val) < 0) { - Error4("ioctl(%d, 0x%x, %p): %s", - fd, opt->desc->major, (void *)&val, strerror(errno)); - return -1; - } - 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; - } + if (Ioctl(fd, getreq, (void *)&val) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->desc->major, (void *)&val, strerror(errno)); + return -1; + } + 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) { - switch (opt->desc->type) { - case TYPE_INT: - if (Ioctl(fd, opt->value.u_int, NULL) < 0) { - Error3("ioctl(%d, 0x%x, NULL): %s", - fd, opt->value.u_int, strerror(errno)); - return -1; - } - break; - case TYPE_INT_INT: - if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) { - Error4("ioctl(%d, 0x%x, 0x%x): %s", - fd, opt->value.u_int, opt->value2.u_int, strerror(errno)); - return -1; - } - break; - case TYPE_INT_INTP: - if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) { - Error4("ioctl(%d, 0x%x, %p): %s", - fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno)); - return -1; - } - break; - case TYPE_INT_BIN: - if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) { - Error4("ioctl(%d, 0x%x, %p): %s", - fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno)); - return -1; - } - break; - case TYPE_INT_STRING: - if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) { - Error4("ioctl(%d, 0x%x, %p): %s", - fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno)); - return -1; - } - break; - default: - Error1("ioctl() data type %d not implemented", - opt->desc->type); - return -1; - } +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) { + Error3("ioctl(%d, 0x%x, NULL): %s", + fd, opt->value.u_int, strerror(errno)); + return -1; + } + break; + case TYPE_INT_INT: + if (Ioctl_int(fd, opt->value.u_int, opt->value2.u_int) < 0) { + Error4("ioctl(%d, 0x%x, 0x%x): %s", + fd, opt->value.u_int, opt->value2.u_int, strerror(errno)); + return -1; + } + break; + case TYPE_INT_INTP: + if (Ioctl(fd, opt->value.u_int, (void *)&opt->value2.u_int) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)&opt->value2.u_int, strerror(errno)); + return -1; + } + break; + case TYPE_INT_BIN: + if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)opt->value2.u_bin.b_data, strerror(errno)); + return -1; + } + break; + case TYPE_INT_STRING: + if (Ioctl(fd, opt->value.u_int, (void *)opt->value2.u_string) < 0) { + Error4("ioctl(%d, 0x%x, %p): %s", + fd, opt->value.u_int, (void *)opt->value2.u_string, strerror(errno)); + return -1; + } + break; + default: + 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) { - struct linger lingstru; - lingstru.l_onoff = (opt->value.u_int>=0 ? 1 : 0); - lingstru.l_linger = opt->value.u_int; - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru, - sizeof(lingstru)) < 0) { - Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu, - fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff, - lingstru.l_linger, sizeof(lingstru)); - return -1; - } + 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; + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, &lingstru, + sizeof(lingstru)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d,%d}, "F_Zu, + fd, opt->desc->major, opt->desc->minor, lingstru.l_onoff, + 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, - opt->value.u_bin.b_data, opt->value.u_bin.b_len) - < 0) { - Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_bin.b_data, opt->value.u_bin.b_len, - strerror(errno)); - return -1; - } - break; - case TYPE_BOOL: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_bool, sizeof(opt->value.u_bool)) - < 0) { - Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd, - opt->desc->major, opt->desc->minor, - opt->value.u_bool, sizeof(opt->value.u_bool), - strerror(errno)); - return -1; - } - break; - case TYPE_BYTE: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_byte, sizeof(uint8_t)) < 0) { - Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_byte, sizeof(uint8_t), strerror(errno)); - return -1; - } - break; - case TYPE_INT: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_int, sizeof(int)) < 0) { - Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_int, sizeof(int), strerror(errno)); - return -1; - } - break; - case TYPE_INT_NULL: - if (opt->value2.u_bool && - Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_int, sizeof(int)) < 0) { - Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_int, sizeof(int), strerror(errno)); - return -1; - } - break; - case TYPE_LONG: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_long, sizeof(long)) < 0) { - Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_long, sizeof(long), strerror(errno)); - return -1; - } - break; - case TYPE_STRING: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - opt->value.u_string, - strlen(opt->value.u_string)+1) < 0) { - Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_string, strlen(opt->value.u_string)+1, - strerror(errno)); - return -1; - } - break; - case TYPE_UINT: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_uint, sizeof(unsigned int)) < 0) { - Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_uint, sizeof(unsigned int), - strerror(errno)); - return -1; - } - break; - case TYPE_TIMEVAL: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_timeval, sizeof(struct timeval)) < 0) { - Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec, - sizeof(struct timeval), strerror(errno)); - return -1; - } - break; + + switch (opt->desc->type) { + case TYPE_BIN: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + opt->value.u_bin.b_data, opt->value.u_bin.b_len) + < 0) { + Error6("setsockopt(%d, %d, %d, %p, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_bin.b_data, opt->value.u_bin.b_len, + strerror(errno)); + return -1; + } + break; + case TYPE_BOOL: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_bool, sizeof(opt->value.u_bool)) + < 0) { + Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", fd, + opt->desc->major, opt->desc->minor, + opt->value.u_bool, sizeof(opt->value.u_bool), + strerror(errno)); + return -1; + } + break; + case TYPE_BYTE: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_byte, sizeof(uint8_t)) < 0) { + Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_byte, sizeof(uint8_t), strerror(errno)); + return -1; + } + break; + case TYPE_INT: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_int, sizeof(int)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_int, sizeof(int), strerror(errno)); + return -1; + } + break; + case TYPE_INT_NULL: + if (opt->value2.u_bool && + Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_int, sizeof(int)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_int, sizeof(int), strerror(errno)); + return -1; + } + break; + case TYPE_LONG: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_long, sizeof(long)) < 0) { + Error6("setsockopt(%d, %d, %d, {%ld}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_long, sizeof(long), strerror(errno)); + return -1; + } + break; + case TYPE_STRING: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + opt->value.u_string, + strlen(opt->value.u_string)+1) < 0) { + Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_string, strlen(opt->value.u_string)+1, + strerror(errno)); + return -1; + } + break; + case TYPE_UINT: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_uint, sizeof(unsigned int)) < 0) { + Error6("setsockopt(%d, %d, %d, {%u}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_uint, sizeof(unsigned int), + strerror(errno)); + return -1; + } + break; + case TYPE_TIMEVAL: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_timeval, sizeof(struct timeval)) < 0) { + Error7("setsockopt(%d, %d, %d, {%ld,%ld}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + opt->value.u_timeval.tv_sec, opt->value.u_timeval.tv_usec, + sizeof(struct timeval), strerror(errno)); + return -1; + } + break; #if HAVE_STRUCT_LINGER - case TYPE_LINGER: - { - struct linger lingstru; - lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0); - lingstru.l_linger = opt->value.u_linger.l_linger; - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &lingstru, sizeof(lingstru)) < 0) { - Error6("setsockopt(%d, %d, %d, {%d,%d}): %s", - fd, opt->desc->major, opt->desc->minor, - lingstru.l_onoff, lingstru.l_linger, - strerror(errno)); - return -1; - } - } - break; + case TYPE_LINGER: + { + struct linger lingstru; + lingstru.l_onoff = (opt->value.u_linger.l_onoff>=0 ? 1 : 0); + lingstru.l_linger = opt->value.u_linger.l_linger; + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &lingstru, sizeof(lingstru)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d,%d}): %s", + fd, opt->desc->major, opt->desc->minor, + lingstru.l_onoff, lingstru.l_linger, + strerror(errno)); + return -1; + } + } + break; #endif /* HAVE_STRUCT_LINGER */ #if defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) - case TYPE_IP_MREQN: - /* handled in applyopts_single */ - break; + case TYPE_IP_MREQN: + /* handled in applyopts_single */ + break; #endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */ #if defined(HAVE_STRUCT_GROUP_SOURCE_REQ) - case TYPE_GROUP_SOURCE_REQ: - /* handled in applyopts_single */ - break; + case TYPE_GROUP_SOURCE_REQ: + /* handled in applyopts_single */ + break; #endif /* defined(HAVE_STRUCT_GROUP_SOURCE_REQ) */ - /*! still many types missing; implement on demand */ + /*! still many types missing; implement on demand */ #if WITH_IP4 - case TYPE_IP4NAME: - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) { - Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s", - fd, opt->desc->major, opt->desc->minor, - *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr), - strerror(errno)); - return -1; - } - break; + case TYPE_IP4NAME: + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + &opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr)) < 0) { + Error6("setsockopt(%d, %d, %d, {0x%x}, "F_Zu"): %s", + fd, opt->desc->major, opt->desc->minor, + *(uint32_t *)&opt->value.u_ip4addr, sizeof(opt->value.u_ip4addr), + strerror(errno)); + return -1; + } + break; #endif /* defined(WITH_IP4) */ - default: + 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 -1; + } + return 0; +} - } else if (opt->desc->func == OFUNC_SOCKOPT_APPEND) { - switch (opt->desc->type) { - uint8_t data[256]; - socklen_t oldlen, newlen; - case TYPE_BIN: - oldlen = sizeof(data); - if (Getsockopt(fd, opt->desc->major, opt->desc->minor, - data, &oldlen) - < 0) { - Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s", - fd, opt->desc->major, opt->desc->minor, data, oldlen, - strerror(errno)); - return -1; - } - memcpy(&data[oldlen], opt->value.u_bin.b_data, - MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen)); - newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen); - if (Setsockopt(fd, opt->desc->major, opt->desc->minor, - data, newlen) - < 0) { - Error6("setsockopt(%d, %d, %d, %p, %d): %s", - fd, opt->desc->major, opt->desc->minor, data, newlen, - strerror(errno)); - return -1; - } - break; - default: - Error2("internal: option \"%s\": unimplemented type %d", - opt->desc->defname, opt->desc->type); - break; - } - } else if (opt->desc->func == OFUNC_SOCKOPT_GENERIC) { - switch (opt->desc->type) { - case TYPE_INT_INT_INT: - if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, - &opt->value3.u_int, sizeof(int)) < 0) { - Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", - fd, opt->value.u_int, opt->value2.u_int, - opt->value3.u_int, sizeof(int), strerror(errno)); - return -1; - } - break; - case TYPE_INT_INT_BIN: - if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, - opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) { - Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s", - fd, opt->value.u_int, opt->value2.u_int, - opt->value3.u_bin.b_len, strerror(errno)); - return -1; - } - break; - case TYPE_INT_INT_STRING: - if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, - opt->value3.u_string, - strlen(opt->value3.u_string)+1) < 0) { - Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", - fd, opt->value.u_int, opt->value2.u_int, - opt->value3.u_string, strlen(opt->value3.u_string)+1, - strerror(errno)); - return -1; - } - break; - default: - Error1("setsockopt() data type %d not implemented", - opt->desc->type); - return -1; - } +/* 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; + case TYPE_BIN: + oldlen = sizeof(data); + if (Getsockopt(fd, opt->desc->major, opt->desc->minor, + data, &oldlen) + < 0) { + Error6("getsockopt(%d, %d, %d, %p, {"F_socklen"}): %s", + fd, opt->desc->major, opt->desc->minor, data, oldlen, + strerror(errno)); + return -1; + } + memcpy(&data[oldlen], opt->value.u_bin.b_data, + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen)); + newlen = oldlen + MIN(opt->value.u_bin.b_len, sizeof(data)-oldlen); + if (Setsockopt(fd, opt->desc->major, opt->desc->minor, + data, newlen) + < 0) { + Error6("setsockopt(%d, %d, %d, %p, %d): %s", + fd, opt->desc->major, opt->desc->minor, data, newlen, + strerror(errno)); + return -1; + } + break; + default: + Error2("internal: option \"%s\": unimplemented type %d", + opt->desc->defname, opt->desc->type); + break; + } + 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, + &opt->value3.u_int, sizeof(int)) < 0) { + Error6("setsockopt(%d, %d, %d, {%d}, "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_int, sizeof(int), strerror(errno)); + return -1; + } + break; + case TYPE_INT_INT_BIN: + if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_bin.b_data, opt->value3.u_bin.b_len) < 0) { + Error5("setsockopt(%d, %d, %d, {...}, "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_bin.b_len, strerror(errno)); + return -1; + } + break; + case TYPE_INT_INT_STRING: + if (Setsockopt(fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_string, + strlen(opt->value3.u_string)+1) < 0) { + Error6("setsockopt(%d, %d, %d, \"%s\", "F_Zu"): %s", + fd, opt->value.u_int, opt->value2.u_int, + opt->value3.u_string, strlen(opt->value3.u_string)+1, + strerror(errno)); + return -1; + } + break; + default: + Error3("%s(opt:\"%s\"): INTERNAL: data type %d not implemented", + __func__, opt->desc->defname, opt->desc->type); + return -1; + } + return 0; +} + +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; + } + 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; + + switch (opt->desc->optcode) { + case OPT_USER: + case OPT_USER_LATE: + if (Fchown(fd, opt->value.u_uidt, -1) < 0) { + Error3("fchown(%d, "F_uid", -1): %s", + fd, opt->value.u_uidt, strerror(errno)); + return -1; + } + break; + case OPT_GROUP: + case OPT_GROUP_LATE: + if (Fchown(fd, -1, opt->value.u_gidt) < 0) { + Error3("fchown(%d, -1, "F_gid"): %s", + fd, opt->value.u_gidt, strerror(errno)); + return -1; + } + break; + case OPT_PERM: + case OPT_PERM_LATE: + if (Fchmod(fd, opt->value.u_modet) < 0) { + Error3("fchmod(%d, %u): %s", + fd, opt->value.u_modet, strerror(errno)); + return -1; + } + break; + case OPT_FTRUNCATE32: + if (Ftruncate(fd, opt->value.u_off) < 0) { + Error3("ftruncate(%d, "F_off"): %s", + fd, opt->value.u_off, strerror(errno)); + return -1; + } + break; +#if HAVE_FTRUNCATE64 + case OPT_FTRUNCATE64: + if (Ftruncate64(fd, opt->value.u_off64) < 0) { + Error3("ftruncate64(%d, "F_off64"): %s", + fd, opt->value.u_off64, strerror(errno)); + return -1; + } +#endif /* HAVE_FTRUNCATE64 */ + break; + case OPT_F_SETLK_RD: + case OPT_F_SETLK_WR: + case OPT_F_SETLKW_RD: + case OPT_F_SETLKW_WR: + { + struct flock l; /* Linux: */ + l.l_type = opt->desc->minor; + l.l_whence = SEEK_SET; + l.l_start = 0; + l.l_len = LONG_MAX; + l.l_pid = 0; /* hope this uses our current process */ + if (Fcntl_lock(fd, opt->desc->major, &l) < 0) { + Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno)); + return -1; + } + } + break; + case OPT_SETUID_EARLY: + case OPT_SETUID: + if (Setuid(opt->value.u_uidt) < 0) { + Error2("setuid("F_uid"): %s", opt->value.u_uidt, + strerror(errno)); + return -1; + } + break; + case OPT_SETGID_EARLY: + case OPT_SETGID: + if (Setgid(opt->value.u_gidt) < 0) { + Error2("setgid("F_gid"): %s", opt->value.u_gidt, + strerror(errno)); + return -1; + } + break; + case OPT_SUBSTUSER_EARLY: + case OPT_SUBSTUSER: + { + struct passwd *pwd; + if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { + Error1("getpwuid("F_uid"): no such user", + opt->value.u_uidt); + return -1; + } + if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) { + Error3("initgroups(%s, "F_gid"): %s", + pwd->pw_name, pwd->pw_gid, strerror(errno)); + return -1; + } + if (Setgid(pwd->pw_gid) < 0) { + Error2("setgid("F_gid"): %s", pwd->pw_gid, + strerror(errno)); + return -1; + } + if (Setuid(opt->value.u_uidt) < 0) { + Error2("setuid("F_uid"): %s", opt->value.u_uidt, + strerror(errno)); + return -1; + } +#if 1 + if (setenv("USER", pwd->pw_name, 1) < 0) { + Error1("setenv(\"USER\", \"%s\", 1): insufficient space", + pwd->pw_name); + return -1; + } + if (setenv("LOGNAME", pwd->pw_name, 1) < 0) { + Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space", + pwd->pw_name); + return -1; + } + if (setenv("HOME", pwd->pw_dir, 1) < 0) { + Error1("setenv(\"HOME\", \"%s\", 1): insufficient space", + pwd->pw_dir); + return -1; + } + if (setenv("SHELL", pwd->pw_shell, 1) < 0) { + Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space", + pwd->pw_shell); + return -1; + } +#endif + } + break; +#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) + case OPT_SUBSTUSER_DELAYED: + { + struct passwd *pwd; + + if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { + Error1("getpwuid("F_uid"): no such user", + opt->value.u_uidt); + return -1; + } + delayeduser_uid = opt->value.u_uidt; + delayeduser_gid = pwd->pw_gid; + if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) { + Error1("strdup("F_Zu"): out of memory", + strlen(pwd->pw_name)+1); + return -1; + } + if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) { + Error1("strdup("F_Zu"): out of memory", + strlen(pwd->pw_dir)+1); + return -1; + } + if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) { + Error1("strdup("F_Zu"): out of memory", + strlen(pwd->pw_shell)+1); + return -1; + } + /* function to get all supplementary groups of user */ + delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t); + getusergroups(delayeduser_name, delayeduser_gids, + &delayeduser_ngids); + delayeduser = true; + } + break; +#endif + case OPT_CHROOT_EARLY: + case OPT_CHROOT: + if (Chroot(opt->value.u_string) < 0) { + Error2("chroot(\"%s\"): %s", opt->value.u_string, + strerror(errno)); + return -1; + } + if (Chdir("/") < 0) { + Error1("chdir(\"/\"): %s", strerror(errno)); + return -1; + } + break; + case OPT_SETSID: + if (Setsid() < 0) { + Warn1("setsid(): %s", strerror(errno)); + if (Setpgid(getpid(), getppid()) < 0) { + Warn3("setpgid(%d, %d): %s", + getpid(), getppid(), strerror(errno)); + } else { + if (Setsid() < 0) { + Error1("setsid(): %s", strerror(errno)); + return -1; + } + } + } + break; + case OPT_SETPGID: + if (Setpgid(0, opt->value.u_int) < 0) { + Warn2("setpgid(0, "F_pid"): %s", + opt->value.u_int, strerror(errno)); + } + break; + case OPT_TIOCSCTTY: + { + int mytty; + /* this code idea taken from ssh/pty.c: make pty controlling term. */ + if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) { + Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno)); + } else { + /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/ +#ifdef TIOCNOTTY + if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) { + Warn2("ioctl(%d, TIOCNOTTY, NULL): %s", + mytty, strerror(errno)); + } +#endif + if (Close(mytty) < 0) { + Info2("close(%d): %s", + mytty, strerror(errno)); + } + } +#ifdef TIOCSCTTY + if (Ioctl(fd, TIOCSCTTY, NULL) < 0) { + Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno)); + } +#endif + if (Tcsetpgrp(0, getpid()) < 0) { + Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno)); + } + } + 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 HAVE_FLOCK - } else if (opt->desc->func == OFUNC_FLOCK) { - if (Flock(fd, opt->desc->major) < 0) { - Error3("flock(%d, %d): %s", - fd, opt->desc->major, strerror(errno)); - return -1; - } -#endif /* defined(HAVE_FLOCK) */ - - } else if (opt->desc->func == OFUNC_SPEC || - opt->desc->func == OFUNC_FLAG) { - switch (opt->desc->optcode) { - case OPT_USER: - case OPT_USER_LATE: - if (Fchown(fd, opt->value.u_uidt, -1) < 0) { - Error3("fchown(%d, "F_uid", -1): %s", - fd, opt->value.u_uidt, strerror(errno)); - return -1; - } - break; - case OPT_GROUP: - case OPT_GROUP_LATE: - if (Fchown(fd, -1, opt->value.u_gidt) < 0) { - Error3("fchown(%d, -1, "F_gid"): %s", - fd, opt->value.u_gidt, strerror(errno)); - return -1; - } - break; - case OPT_PERM: - case OPT_PERM_LATE: - if (Fchmod(fd, opt->value.u_modet) < 0) { - Error3("fchmod(%d, %u): %s", - fd, opt->value.u_modet, strerror(errno)); - return -1; - } - break; - case OPT_FTRUNCATE32: - if (Ftruncate(fd, opt->value.u_off) < 0) { - Error3("ftruncate(%d, "F_off"): %s", - fd, opt->value.u_off, strerror(errno)); - return -1; - } - break; -#if HAVE_FTRUNCATE64 - case OPT_FTRUNCATE64: - if (Ftruncate64(fd, opt->value.u_off64) < 0) { - Error3("ftruncate64(%d, "F_off64"): %s", - fd, opt->value.u_off64, strerror(errno)); - return -1; - } -#endif /* HAVE_FTRUNCATE64 */ - break; - case OPT_F_SETLK_RD: - case OPT_F_SETLK_WR: - case OPT_F_SETLKW_RD: - case OPT_F_SETLKW_WR: - { - struct flock l; /* Linux: */ - l.l_type = opt->desc->minor; - l.l_whence = SEEK_SET; - l.l_start = 0; - l.l_len = LONG_MAX; - l.l_pid = 0; /* hope this uses our current process */ - if (Fcntl_lock(fd, opt->desc->major, &l) < 0) { - Error3("fcntl(%d, %d, {type=F_WRLCK,whence=SEEK_SET,start=0,len=LONG_MAX,pid=0}): %s", fd, opt->desc->major, strerror(errno)); - return -1; - } - } - break; - case OPT_SETUID_EARLY: - case OPT_SETUID: - if (Setuid(opt->value.u_uidt) < 0) { - Error2("setuid("F_uid"): %s", opt->value.u_uidt, - strerror(errno)); - return -1; - } - break; - case OPT_SETGID_EARLY: - case OPT_SETGID: - if (Setgid(opt->value.u_gidt) < 0) { - Error2("setgid("F_gid"): %s", opt->value.u_gidt, - strerror(errno)); - return -1; - } - break; - case OPT_SUBSTUSER_EARLY: - case OPT_SUBSTUSER: - { - struct passwd *pwd; - if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { - Error1("getpwuid("F_uid"): no such user", - opt->value.u_uidt); - return -1; - } - if (Initgroups(pwd->pw_name, pwd->pw_gid) < 0) { - Error3("initgroups(%s, "F_gid"): %s", - pwd->pw_name, pwd->pw_gid, strerror(errno)); - return -1; - } - if (Setgid(pwd->pw_gid) < 0) { - Error2("setgid("F_gid"): %s", pwd->pw_gid, - strerror(errno)); - return -1; - } - if (Setuid(opt->value.u_uidt) < 0) { - Error2("setuid("F_uid"): %s", opt->value.u_uidt, - strerror(errno)); - return -1; - } -#if 1 - if (setenv("USER", pwd->pw_name, 1) < 0) { - Error1("setenv(\"USER\", \"%s\", 1): insufficient space", - pwd->pw_name); - return -1; - } - if (setenv("LOGNAME", pwd->pw_name, 1) < 0) { - Error1("setenv(\"LOGNAME\", \"%s\", 1): insufficient space", - pwd->pw_name); - return -1; - } - if (setenv("HOME", pwd->pw_dir, 1) < 0) { - Error1("setenv(\"HOME\", \"%s\", 1): insufficient space", - pwd->pw_dir); - return -1; - } - if (setenv("SHELL", pwd->pw_shell, 1) < 0) { - Error1("setenv(\"SHELL\", \"%s\", 1): insufficient space", - pwd->pw_shell); - return -1; - } -#endif - } - break; -#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT) - case OPT_SUBSTUSER_DELAYED: - { - struct passwd *pwd; - - if ((pwd = getpwuid(opt->value.u_uidt)) == NULL) { - Error1("getpwuid("F_uid"): no such user", - opt->value.u_uidt); - return -1; - } - delayeduser_uid = opt->value.u_uidt; - delayeduser_gid = pwd->pw_gid; - if ((delayeduser_name = strdup(pwd->pw_name)) == NULL) { - Error1("strdup("F_Zu"): out of memory", - strlen(pwd->pw_name)+1); - return -1; - } - if ((delayeduser_dir = strdup(pwd->pw_dir)) == NULL) { - Error1("strdup("F_Zu"): out of memory", - strlen(pwd->pw_dir)+1); - return -1; - } - if ((delayeduser_shell = strdup(pwd->pw_shell)) == NULL) { - Error1("strdup("F_Zu"): out of memory", - strlen(pwd->pw_shell)+1); - return -1; - } - /* function to get all supplementary groups of user */ - delayeduser_ngids = sizeof(delayeduser_gids)/sizeof(gid_t); - getusergroups(delayeduser_name, delayeduser_gids, - &delayeduser_ngids); - delayeduser = true; - } - break; -#endif - case OPT_CHROOT_EARLY: - case OPT_CHROOT: - if (Chroot(opt->value.u_string) < 0) { - Error2("chroot(\"%s\"): %s", opt->value.u_string, - strerror(errno)); - return -1; - } - if (Chdir("/") < 0) { - Error1("chdir(\"/\"): %s", strerror(errno)); - return -1; - } - break; - case OPT_SETSID: - if (Setsid() < 0) { - Warn1("setsid(): %s", strerror(errno)); - if (Setpgid(getpid(), getppid()) < 0) { - Warn3("setpgid(%d, %d): %s", - getpid(), getppid(), strerror(errno)); - } else { - if (Setsid() < 0) { - Error1("setsid(): %s", strerror(errno)); - return -1; - } - } - } - break; - case OPT_SETPGID: - if (Setpgid(0, opt->value.u_int) < 0) { - Warn2("setpgid(0, "F_pid"): %s", - opt->value.u_int, strerror(errno)); - } - break; - case OPT_TIOCSCTTY: - { - int mytty; - /* this code idea taken from ssh/pty.c: make pty controlling term. */ - if ((mytty = Open("/dev/tty", O_NOCTTY, 0640)) < 0) { - Warn1("open(\"/dev/tty\", O_NOCTTY, 0640): %s", strerror(errno)); - } else { - /*0 Info1("open(\"/dev/tty\", O_NOCTTY, 0640) -> %d", mytty);*/ -#ifdef TIOCNOTTY - if (Ioctl(mytty, TIOCNOTTY, NULL) < 0) { - Warn2("ioctl(%d, TIOCNOTTY, NULL): %s", - mytty, strerror(errno)); - } -#endif - if (Close(mytty) < 0) { - Info2("close(%d): %s", - mytty, strerror(errno)); - } - } -#ifdef TIOCSCTTY - if (Ioctl(fd, TIOCSCTTY, NULL) < 0) { - Warn2("ioctl(%d, TIOCSCTTY, NULL): %s", fd, strerror(errno)); - } -#endif - if (Tcsetpgrp(0, getpid()) < 0) { - Warn2("tcsetpgrp("F_pid"): %s", getpid(), strerror(errno)); - } - } - break; - #if _WITH_INTERFACE - case OPT_RETRIEVE_VLAN: - if (!xioparms.experimental) { - Warn1("option %s is experimental", opt->desc->defname); - } - if (_interface_setsockopt_auxdata(fd, 1) < 0) { - return -1; - } - break; + case OPT_RETRIEVE_VLAN: + if (!xioparms.experimental) { + Warn1("option %s is experimental", opt->desc->defname); + } + if (_interface_setsockopt_auxdata(fd, 1) < 0) { + return -1; + } + break; #endif /* _WITH_INTERFACE */ - default: Error1("INTERNAL: applyopts(): option \"%s\" not implemented", - opt->desc->defname); - return -1; - } + default: Error1("applyopt_spec(opt:%s): INTERNAL option not implemented", + opt->desc->defname); + return -1; + } + return 0; +} -#if WITH_TERMIOS - } else if (opt->desc->func == OFUNC_TERMIOS_FLAG) { - if (xiotermiosflag_applyopt(fd, opt) < 0) { - return -1; - } - - } 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; + 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) - 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; + i = 0; + while (opts[i].desc != ODESC_END) { + if (opts[i].desc == ODESC_DONE && + opts[i].desc == ODESC_ERROR) { + ++i; + continue; } - } - - /* 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 */ - } - ++opt; + if (opts[i].desc->group & groups) { + rc |= applyopt(sfd, sfd->fd, &opts[i]); } + ++i; } - 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,91 +4136,233 @@ 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; - } else { - switch (opt->desc->func) { + 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; + case OFUNC_OFFSET_MASKS: /* An external (e.g. library) variable with independent bits is to be manipulated. Here the data target is an array with size 2, the first 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; - } - break; -#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */ + case OFUNC_SIGNAL: + rc = xio_opt_signal(sfd->para.exec.pid, opt->desc->major); + break; -#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; - } + default: + Error2("applyopt(opt:%s): INTERNAL: ofunc %d not implemented", + opt->desc->defname, opt->desc->func); + rc = -1; break; -#endif /* _WITH_SOCKET */ - - default: - ++opt; - continue; - } - opt->desc = ODESC_DONE; - ++opt; - } } - 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; - } + if (rc == 0) opt->desc = ODESC_DONE; - ++opt; - } + else if (rc < 0) + opt->desc = ODESC_ERROR; + /* rc > 0: no action */ + 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; +} diff --git a/xioopts.h b/xioopts.h index 7211322..99a0708 100644 --- a/xioopts.h +++ b/xioopts.h @@ -82,10 +82,12 @@ enum e_types { #endif TYPE_GENERIC, /* type is determined from (text) data provided (dalan syntax) */ + TYPE_OVERFLOW /* marker: beyond last type */ } ; enum e_func { OFUNC_NONE, /* no function - should not occur */ + /* Options to be applied to FD directly */ OFUNC_FLAG, /* no function, but bitposition, only with bool; arg1 is mask */ OFUNC_FLAG_PATTERN, /* no function, but bitpattern: arg1 is pattern, arg2 is mask */ OFUNC_SEEK32, /* lseek(): arg1 is whence (SEEK_SET etc.) */ @@ -100,12 +102,6 @@ enum e_func { OFUNC_SOCKOPT_APPEND,/* getsockopt(), append data, setsockopt() */ OFUNC_SOCKOPT_GENERIC,/* generic setsockopt() (level, optname on cmdline) */ OFUNC_FLOCK, /* flock() */ - OFUNC_TERMIO, /* termio() ? */ - OFUNC_SPEC, /* special, i.e. no generalizable function call */ - OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */ - OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */ - /*OFUNC_APPL,*/ /* special, i.e. application must know which f. */ - OFUNC_EXT, /* with extended file descriptors only */ OFUNC_TERMIOS_FLAG, /* a flag in struct termios: major..tcflag, minor..bit */ OFUNC_TERMIOS_PATTERN, /* a multibit: major..tcflag, minor..pattern, @@ -114,14 +110,23 @@ enum e_func { OFUNC_TERMIOS_CHAR, /* a termios functional character: major..c_cc index */ OFUNC_TERMIOS_SPEED, /* termios c_ispeed etc on FreeBSD */ OFUNC_TERMIOS_SPEC, /* termios combined modes */ + + OFUNC_EXT, /* with extended file descriptors only */ +# define OFUNC_XIO OFUNC_EXT + OFUNC_SPEC, /* special, i.e. no generalizable function call */ + OFUNC_OFFSET, /* put a value into xiofile struct; major is offset */ + OFUNC_OFFSET_MASK, /* set/unset bit pattern in variable */ + OFUNC_OFFSET_MASKS, /* set pos or neg bit pattern in array[2] */ + /*OFUNC_APPL,*/ /* special, i.e. application must know which f. */ OFUNC_SIGNAL, /* a signal that should be passed to child process */ OFUNC_RESOLVER, /* a bit position used on _res.options */ - OFUNC_IFFLAG, /* interface flag: locical-or a 1bit mask */ + OFUNC_IFFLAG, /* interface flag: logical-or a 1bit mask */ + OFUNC_SET_NAMESPACE, /* set/change Linux namespace */ + OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */ # define ENABLE_OFUNC # include "xio-streams.h" /* push a POSIX STREAMS module */ # undef ENABLE_OFUNC - OFUNC_SET_NAMESPACE, /* set/change Linux namespace */ - OFUNC_RESET_NAMESPACE, /* set Linux namespace back to default */ + OFUNC_OVERFLOW /* marker: beyond last func */ } ; /* for simpler handling of option-to-connection-type relations we define @@ -980,12 +985,13 @@ extern int retropt_flag(struct opt *opts, int optcode, flags_t *result); extern int retropt_string(struct opt *opts, int optcode, char **result); extern int retropt_timespec(struct opt *opts, int optcode, struct timespec *result); extern int retropt_bind(struct opt *opts, int af, int socktype, int ipproto, struct sockaddr *sa, socklen_t *salen, int feats, const int ai_flags[2]); -extern int applyopts(int fd, struct opt *opts, enum e_phase phase); -extern int applyopts2(int fd, struct opt *opts, unsigned int from, unsigned int to); -extern int applyopts_optgroup(int fd, struct opt *opts, int from, int to, groups_t groups); +extern int applyopt_fd(int fd, struct opt *opt); +extern int applyopt_single(struct single *sfd, struct opt *opt); +extern int applyopts(struct single *sfd, int fd, struct opt *opts, enum e_phase phase); +extern int applyopts2(struct single *sfd, int fd, struct opt *opts, unsigned int from, unsigned int to); +extern int applyopts_optgroup(struct single *sfd, int fd, struct opt *opts, groups_t groups); extern int applyopts_flags(struct opt *opts, groups_t group, flags_t *result); extern int applyopts_cloexec(int fd, struct opt *opts); -extern int applyopts_early(const char *path, struct opt *opts); extern int applyopts_fchown(int fd, struct opt *opts); extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase phase); extern int applyopts_offset(struct single *xfd, struct opt *opts); @@ -1005,6 +1011,7 @@ extern groups_t groupbits(int fd); extern groups_t _groupbits(mode_t mode); extern int dropopts(struct opt *opts, unsigned int phase); extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to); +extern int dumpopts(struct opt *opts); #if HAVE_BASIC_UID_T==1 # define retropt_uid(o,c,r) retropt_short(o,c,r) diff --git a/xiosignal.c b/xiosignal.c index 5a7b356..36d0595 100644 --- a/xiosignal.c +++ b/xiosignal.c @@ -62,14 +62,19 @@ void socatsignalpass(int sig) { return; } + { /*debug*/ + int n = 0; for (i=0; isig_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 */