signal-relay.c (1860B)
1 /* (c) Copyright 2007 Daniel Hokka Zakrisson 2 Released under the terms of the GNU GPL v2 3 4 Build with gcc -lvserver ... -osignal-relay signal-relay 5 */ 6 7 #include <stdio.h> 8 #include <signal.h> 9 #include <sys/types.h> 10 #include <sys/wait.h> 11 #include <unistd.h> 12 13 #include <stdint.h> 14 typedef uint32_t xid_t; 15 typedef uint32_t nid_t; 16 typedef uint32_t tag_t; 17 #include <vserver.h> 18 19 #define PREFIX "signal-relay: " 20 21 static pid_t child; 22 23 static void signal_handler(int signal) 24 { 25 /* child exited, so should we */ 26 if (signal == SIGCHLD) { 27 int ret; 28 if (waitpid(child, &ret, 0) == -1) { 29 perror(PREFIX "waitpid"); 30 exit(111); 31 } 32 exit(WEXITSTATUS(ret)); 33 } 34 /* relay */ 35 else { 36 xid_t xid = vc_get_task_xid(child); 37 if (xid == VC_NOCTX) { 38 perror(PREFIX "vc_get_task_xid"); 39 return; 40 } 41 if (vc_ctx_kill(xid, child, signal) == -1) 42 perror(PREFIX "vc_ctx_kill"); 43 } 44 } 45 46 #define SETSIG(sig) if (signal(sig, signal_handler) == SIG_ERR) { \ 47 signal_handler(SIGTERM); \ 48 perror(PREFIX "signal(" #sig ")"); \ 49 exit(111); \ 50 } 51 int main(int argc, char *argv[]) 52 { 53 int opt, new_group = 0; 54 while ((opt = getopt(argc, argv, "+P")) != -1) { 55 switch (opt) { 56 case 'P': 57 new_group = 1; 58 break; 59 default: 60 fprintf(stderr, "Usage: %s [-P] <program> <args>*\n", argv[0]); 61 break; 62 } 63 } 64 65 if (argc == optind) 66 return 0; 67 68 SETSIG(SIGCHLD) 69 child = fork(); 70 if (child == 0) { 71 if (new_group && setsid() == -1) { 72 perror(PREFIX "setsid"); 73 exit(111); 74 } 75 execvp(argv[optind], argv+optind); 76 perror(PREFIX "execvp"); 77 exit(111); 78 } 79 else if (child == -1) { 80 perror(PREFIX "fork"); 81 exit(111); 82 } 83 SETSIG(SIGHUP) 84 SETSIG(SIGINT) 85 SETSIG(SIGSEGV) 86 SETSIG(SIGTERM) 87 SETSIG(SIGUSR1) 88 SETSIG(SIGUSR2) 89 SETSIG(SIGWINCH) 90 SETSIG(SIGALRM) 91 SETSIG(SIGPWR) 92 93 while (1) { 94 sleep(600); 95 } 96 /* never get here, signal handler exits */ 97 return 1; 98 }