Signal-relay.c

From Linix VServer
Jump to navigationJump to search

/* (c) Copyright 2007 Daniel Hokka Zakrisson Released under the terms of the GNU GPL v2 Build with gcc -lvserver ... -osignal-relay signal-relay */ #include #include #include #include #include typedef unsigned int xid_t; typedef unsigned int nid_t; #include #define PREFIX "signal-relay: " static pid_t child; static void signal_handler(int signal) { /* child exited, so should we */ if (signal == SIGCHLD) { int ret; if (waitpid(child, &ret, 0) == -1) { perror(PREFIX "waitpid"); exit(111); } exit(WEXITSTATUS(ret)); } /* relay */ else { xid_t xid = vc_get_task_xid(child); if (xid == VC_NOCTX) { perror(PREFIX "vc_get_task_xid"); return; } if (vc_ctx_kill(xid, child, signal) == -1) perror(PREFIX "vc_ctx_kill"); } } #define SETSIG(sig) if (signal(sig, signal_handler) == SIG_ERR) { \ signal_handler(SIGTERM); \ perror(PREFIX "signal(" #sig ")"); \ exit(111); \ } int main(int argc, char *argv[]) { int opt, new_group = 0; while ((opt = getopt(argc, argv, "+P")) != -1) { switch (opt) { case 'P': new_group = 1; break; default: fprintf(stderr, "Usage: %s [-P] *\n", argv[0]); break; } } if (argc == optind) return 0; SETSIG(SIGCHLD) child = fork(); if (child == 0) { if (new_group && setsid() == -1) { perror(PREFIX "setsid"); exit(111); } execvp(argv[optind], argv+optind); perror(PREFIX "execvp"); exit(111); } else if (child == -1) { perror(PREFIX "fork"); exit(111); } SETSIG(SIGHUP) SETSIG(SIGINT) SETSIG(SIGSEGV) SETSIG(SIGTERM) SETSIG(SIGUSR1) SETSIG(SIGUSR2) SETSIG(SIGWINCH) SETSIG(SIGALRM) SETSIG(SIGPWR) while (1) { sleep(600); } /* never get here, signal handler exits */ return 1; }