ccx-utils

Miscellaneous utilities written in C
git clone https://ccx.te2000.cz/git/ccx-utils
Log | Files | Refs

commit 42f9a2d5eed3755f3bd7d5b9b489641739fa356b
parent c4575987bbb77e7130864577cbf87ce5e6e39f1d
Author: Jan Pobrislo <ccx@te2000.cz>
Date:   Mon, 29 Jul 2024 22:35:20 +0000

fdsend / fdrecvto

Diffstat:
Msrc/Makefile | 2+-
Asrc/fdrecv.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdrecvto.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/fdsend.c | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/pidns_run.c | 2+-
Asrc/socketpair.c | 32++++++++++++++++++++++++++++++++
Asrc/test-fdsend | 9+++++++++
7 files changed, 187 insertions(+), 2 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -1,5 +1,5 @@ -tools_simple:=argv0exec nosuid pidns_run safelink spawn-pty +tools_simple:=argv0exec nosuid pidns_run safelink spawn-pty fdsend fdrecv fdrecvto socketpair tools_libcap:=applyuidgid-caps tools=$(tools_simple) $(tools_libcap) diff --git a/src/fdrecv.c b/src/fdrecv.c @@ -0,0 +1,47 @@ +#include <errno.h> +#include <sys/select.h> + +#include <skalibs/types.h> +#include <skalibs/strerr.h> +#include <skalibs/djbunix.h> +#include <skalibs/exec.h> +#include <skalibs/ancil.h> + +#define USAGE "fdrecv socket_fd fd_env_var prog..." +#define PROG "fdrecv" + +void wait_readable(int fd) { + fd_set rfds, xfds; + int retval = 0; + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + FD_ZERO(&xfds); + FD_SET(fd, &xfds); + while(retval < 1) { + retval = select(fd+1, &rfds, NULL, &xfds, NULL); + if (retval == -1 && errno != EINTR) { + strerr_dief1sys(111, "select()"); + } + } +} + +int main (int argc, char const *const *argv) +{ + unsigned int socket_fd; + int fd; + if ((argc < 4)) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ; + + wait_readable(socket_fd); + fd = ancil_recv_fd(socket_fd, 42); + if(fd < 0) { + strerr_dief1sys(111, "recvmsg()"); + } + + size_t env_size = strlen(argv[2]) + uint_fmt(0, fd) + 2; + char envstr[env_size]; + char *p = stpncpy(envstr, argv[2], env_size); + *p++ = '='; + uint_fmt(p, fd); + xmexec_n(argv+3, envstr, env_size-1, 1); +} diff --git a/src/fdrecvto.c b/src/fdrecvto.c @@ -0,0 +1,55 @@ +#include <errno.h> +#include <unistd.h> +#include <sys/select.h> + +#include <skalibs/types.h> +#include <skalibs/strerr.h> +#include <skalibs/djbunix.h> +#include <skalibs/exec.h> +#include <skalibs/ancil.h> + +#define USAGE "fdrecv socket_fd fd_env_var prog..." +#define PROG "fdrecv" + +void wait_readable(int fd) { + fd_set rfds, xfds; + int retval = 0; + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + FD_ZERO(&xfds); + FD_SET(fd, &xfds); + while(retval < 1) { + retval = select(fd+1, &rfds, NULL, &xfds, NULL); + if (retval == -1 && errno != EINTR) { + strerr_dief1sys(111, "select()"); + } + } +} + +int main (int argc, char const *const *argv) +{ + unsigned int socket_fd, target_fd; + int fd; + if ((argc < 4)) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[2], &target_fd)) strerr_dieusage(100, USAGE) ; + + wait_readable(socket_fd); + fd = ancil_recv_fd(socket_fd, 42); + if(fd < 0) { + strerr_dief1sys(111, "recvmsg()"); + } + if(fd == target_fd) { + int tmp_fd = dup(fd); + if(tmp_fd < 0) { + strerr_dief1sys(111, "dup()"); + } + close(fd); + fd = tmp_fd; + } + if(dup2(fd, target_fd) < 0) { + strerr_dief1sys(111, "dup2()"); + } + + xexec(argv+3) ; +} diff --git a/src/fdsend.c b/src/fdsend.c @@ -0,0 +1,42 @@ +#include <errno.h> +#include <sys/select.h> + +#include <skalibs/types.h> +#include <skalibs/strerr.h> +#include <skalibs/djbunix.h> +#include <skalibs/exec.h> +#include <skalibs/ancil.h> + +#define USAGE "fdsend socket_fd fd_to_send prog..." +#define PROG "fdsend" + +void wait_writable(int fd) { + fd_set wfds, xfds; + int retval = 0; + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + FD_ZERO(&xfds); + FD_SET(fd, &xfds); + while(retval < 1) { + retval = select(fd+1, NULL, &wfds, &xfds, NULL); + if (retval == -1 && errno != EINTR) { + strerr_dief1sys(111, "select()"); + } + } +} + + +int main (int argc, char const *const *argv) +{ + unsigned int socket_fd, fd_to_send ; + if ((argc < 4)) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ; + if (!uint0_scan(argv[2], &fd_to_send)) strerr_dieusage(100, USAGE) ; + + wait_writable(socket_fd); + if(!ancil_send_fd(socket_fd, fd_to_send, 42)) { + strerr_dief1sys(111, "sendmsg()"); + } + + xexec(argv+3) ; +} diff --git a/src/pidns_run.c b/src/pidns_run.c @@ -74,7 +74,7 @@ int main(const int argc, const char **argv) { if (retval == -1 && errno != EINTR) { strerr_dief1sys(111, "select()"); } - if(retval) { + if(retval > 0) { const char term_msg[] = "pidns_run: parent died, terminating\n"; write(2, "pidns_run: parent died, terminating\n", sizeof(term_msg)); exit(111); diff --git a/src/socketpair.c b/src/socketpair.c @@ -0,0 +1,32 @@ +#include <unistd.h> + +#include <skalibs/types.h> +#include <skalibs/strerr.h> +#include <skalibs/djbunix.h> +#include <skalibs/exec.h> +#include <skalibs/socket.h> + +#define USAGE "socketpair fd0 fd1 prog..." +#define PROG "socketpair" + +int main (int argc, char const *const *argv) +{ + int fd0, fd1; + int sv[2]; + if ((argc < 4) + || !uint0_scan(argv[1], (unsigned int *)&fd0) + || !uint0_scan(argv[2], (unsigned int *)&fd1) + || (fd0 == fd1)) + strerr_dieusage(100, USAGE) ; + + if (ipc_pair_b(sv) != 0) { + strerr_diefu1sys(111, "create socketpair") ; + } + + if (sv[1] == fd0) sv[1] = dup(sv[1]) ; + if ((sv[1] == -1) + || (fd_move(fd0, sv[0]) == -1) + || (fd_move(fd1, sv[1]) == -1)) + strerr_diefu1sys(111, "move fds") ; + xexec(argv+3) ; +} diff --git a/src/test-fdsend b/src/test-fdsend @@ -0,0 +1,9 @@ +#!/bin/execlineb -P +./socketpair 3 4 +#if { filan } +background { + fdclose 4 + redirfd -r 0 ./fdsend.c ./fdsend 3 0 true +} +fdclose 3 +./fdrecvto 4 0 cat