diff options
Diffstat (limited to 'orphan-reaper.c')
-rw-r--r-- | orphan-reaper.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/orphan-reaper.c b/orphan-reaper.c new file mode 100644 index 0000000..07304ba --- /dev/null +++ b/orphan-reaper.c @@ -0,0 +1,78 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/prctl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "arg.h" + +#ifdef TEST +# define LIBEXECDIR "." +# define REAPD "reapd.test" +#else +# ifndef REAPD +# define REAPD "reapd" +# endif +#endif + +char *argv0; + +static +void usage(void) +{ + fprintf(stderr, "usage: %s [-f] command ...\n", argv0); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int fatal = 0; + + ARGBEGIN { + case 'f': + fatal = 1; + break; + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + if (access(LIBEXECDIR"/"REAPD, X_OK) < 0) { + fprintf(stderr, "%s: access %s: %s\n", argv0, LIBEXECDIR"/"REAPD, strerror(errno)); + return 2; + } + + if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0) { + fprintf(stderr, "%s: prctl PR_SET_CHILD_SUBREAPER: %s\n", argv0, strerror(errno)); + if (fatal) + return 2; + goto exec; + } + + switch (fork()) { + case -1: + fprintf(stderr, "%s: fork: %s\n", argv0, strerror(errno)); + if (fatal) + break; + /* fall through */ + + case 0: + (void) prctl(PR_SET_CHILD_SUBREAPER, 0); + exec: + execvp(*argv, argv); + fprintf(stderr, "%s: execvp %s: %s\n", argv0, *argv, strerror(errno)); + break; + + default: + execl(LIBEXECDIR"/"REAPD, LIBEXECDIR"/"REAPD, NULL); + fprintf(stderr, "%s: execl %s: %s\n", argv0, *argv, strerror(errno)); + break; + } + + return 2; +} |