aboutsummaryrefslogtreecommitdiffstats
path: root/orphan-reaper.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--orphan-reaper.c78
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;
+}