+ if (!sigismember(&sigmask, i))
+ continue;
+ if ((i == SIGCHLD) || (i == SIGPIPE))
+ continue;
+
+ s.sa_handler = jail_handle_signal;
+ sigaction(i, &s, NULL);
+ }
+
+ if (opts.namespace) {
+ add_mount("/dev/full", 0, -1);
+ add_mount("/dev/null", 0, -1);
+ add_mount("/dev/urandom", 0, -1);
+ add_mount("/dev/zero", 0, -1);
+
+ int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | SIGCHLD;
+ if (opts.hostname)
+ flags |= CLONE_NEWUTS;
+ jail_process.pid = clone(exec_jail, child_stack + STACK_SIZE, flags, NULL);
+ } else {
+ jail_process.pid = fork();
+ }
+
+ if (jail_process.pid > 0) {
+ /* parent process */
+ uloop_process_add(&jail_process);
+ uloop_run();
+ if (jail_running) {
+ DEBUG("uloop interrupted, killing jail process\n");
+ kill(jail_process.pid, SIGTERM);
+ uloop_timeout_set(&jail_process_timeout, 1000);
+ uloop_run();
+ }
+ uloop_done();
+ return jail_return_code;
+ } else if (jail_process.pid == 0) {
+ /* fork child process */
+ return exec_jail(NULL);
+ } else {
+ ERROR("failed to clone/fork: %m\n");
+ return EXIT_FAILURE;
+ }