With this patch, trap(1) is able to accept an existing PID as prog..., if given the new -P option.
I'm sending this as patch because the only scenario where this does something that isn't feasible with execline's current wait(1) command or the original interface to trap is if you use Linux or Free/DragonFly BSD's subreaper functionality to reuse trap as a turbo-fghack that forwards signals and tracks the exit code of the forked-off daemon instead of the short-lived daemonizer. The code may not be OS-specific, but the top use-case is. Signed-off-by: Carlos Eduardo <carana2...@gmail.com> --- src/execline/trap.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/execline/trap.c b/src/execline/trap.c index ba1b25a..1a4aa60 100644 --- a/src/execline/trap.c +++ b/src/execline/trap.c @@ -18,7 +18,7 @@ #include <execline/execline.h> -#define USAGE "trap [ -x ] { signal { cmdline } ... } prog..." +#define USAGE "trap [ -x ] [ -P ] { signal { cmdline } ... } prog..." #define dieusage() strerr_dieusage(100, USAGE) ; static inline void trap_action (unsigned int i, char const *const *envp, size_t envlen, pid_t *pids, char const *const **argvs) @@ -50,7 +50,7 @@ int main (int argc, char const **argv, char const *const *envp) size_t envlen = env_len(envp) ; iopause_fd x = { .events = IOPAUSE_READ } ; sigset_t full, set ; - int xfersigs = 0 ; + int xfersigs = 0, adopt = 0 ; unsigned int argc1 ; unsigned int i = 0 ; PROG = "trap" ; @@ -59,11 +59,12 @@ int main (int argc, char const **argv, char const *const *envp) subgetopt l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "xt:", &l) ; + int opt = subgetopt_r(argc, argv, "xP", &l) ; if (opt == -1) break ; switch (opt) { case 'x' : xfersigs = 1 ; break ; + case 'P' : adopt = 1 ; break ; default : dieusage() ; } } @@ -121,8 +122,23 @@ int main (int argc, char const **argv, char const *const *envp) if (x.fd == -1) strerr_diefu1sys(111, "selfpipe_init") ; if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ; - pids[SKALIBS_NSIG] = cspawn(argv[argc1 + 1], argv + argc1 + 1, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ; - if (!pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; + if (!adopt) + { + pids[SKALIBS_NSIG] = cspawn(argv[argc1 + 1], argv + argc1 + 1, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ; + if (!pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; + } else { + int status; + if (argc > argc1 + 2) + dieusage(); + if (!pid_scan(argv[argc1 + 1], &pids[SKALIBS_NSIG])) + strerr_dieinvalid(100, "PID"); + switch (waitpid_nointr(pids[SKALIBS_NSIG], &status, WNOHANG)) + { + case -1: strerr_dief2sys(111, "invalid ", "PID") ; + case 0 : break ; + default : return wait_estatus(status) ; + } + } loop: if (iopause_g(&x, 1, 0) < 0) strerr_diefu1sys(111, "iopause") ; -- 2.44.0