vkill.c (5346B)
1 // $Id$ --*- c -*-- 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // 5 // This program is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation; version 2 of the License. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 #include "vserver.h" 24 #include "util.h" 25 26 #include "lib/virtual.h" 27 28 #include <getopt.h> 29 #include <signal.h> 30 #include <stdlib.h> 31 #include <errno.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <unistd.h> 35 #include <sys/types.h> 36 #include <sys/resource.h> 37 #include <sys/wait.h> 38 39 #define ENSC_WRAPPERS_VSERVER 1 40 #define ENSC_WRAPPERS_UNISTD 1 41 #include <wrappers.h> 42 43 #define CMD_HELP 0x8000 44 #define CMD_VERSION 0x8001 45 46 int wrapper_exit_code = 1; 47 48 static struct option const 49 CMDLINE_OPTIONS[] = { 50 { "help", no_argument, 0, CMD_HELP }, 51 { "version", no_argument, 0, CMD_VERSION }, 52 { "xid", required_argument, 0, 'c' }, 53 { 0,0,0,0 } 54 }; 55 56 struct Arguments 57 { 58 xid_t xid; 59 int sig; 60 }; 61 62 static char const * const SIGNALS[] = { 63 // 0 1 2 3 4 5 6 7 64 "UNUSED", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "UNUSED", 65 "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", 66 "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "IO", 67 "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", 68 0, 69 }; 70 71 static void 72 showHelp(int fd, char const *cmd, int res) 73 { 74 WRITE_MSG(fd, "Usage: "); 75 WRITE_STR(fd, cmd); 76 WRITE_MSG(fd, 77 " [--xid|-c <xid>] [-s <signal>] [--] <pid>*\n" 78 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 79 exit(res); 80 } 81 82 static void 83 showVersion() 84 { 85 WRITE_MSG(1, 86 "vkill " VERSION " -- sends signals to processes within other contexts\n" 87 "This program is part of " PACKAGE_STRING "\n\n" 88 "Copyright (C) 2003 Enrico Scholz\n" 89 VERSION_COPYRIGHT_DISCLAIMER); 90 exit(0); 91 } 92 93 static int 94 str2sig(char const *str) 95 { 96 char *errptr; 97 int res = strtol(str, &errptr, 10); 98 99 if (*errptr!='\0') res=-1; 100 if (res==-1 && strncmp(str,"SIG",3)==0) str+=3; 101 if (res==-1) { 102 char const * const *ptr = SIGNALS; 103 for (;*ptr!=0; ++ptr) { 104 if (strcmp(*ptr,str)!=0) continue; 105 res = ptr-SIGNALS; 106 break; 107 } 108 } 109 110 return res; 111 } 112 113 #if defined(VC_ENABLE_API_LEGACY) 114 inline static ALWAYSINLINE int 115 kill_wrapper_legacy(xid_t UNUSED xid, char const *proc, int UNUSED sig) 116 { 117 pid_t pid; 118 119 signal(SIGCHLD, SIG_DFL); 120 pid = Efork(); 121 122 if (pid>0) { 123 int status; 124 int res; 125 while ((res=wait4(pid, &status, 0,0))==-1 && 126 (errno==EAGAIN || errno==EINTR)) {} 127 128 return (res==0 && WIFEXITED(status) && WEXITSTATUS(status)) ? 0 : 1; 129 } 130 131 execl(LEGACYDIR "/vkill", "legacy/vkill", proc, (void *)(0)); 132 perror("vkill: execl()"); 133 exit(1); 134 } 135 #endif 136 137 inline static int 138 kill_wrapper(xid_t xid, char const *pid_s, int sig) 139 { 140 pid_t pid; 141 long tmp; 142 143 if (!isNumber(pid_s, &tmp, true)) { 144 WRITE_MSG(2, "vkill: '"); 145 WRITE_STR(2, pid_s); 146 WRITE_MSG(2, "' is not a number\n"); 147 } 148 pid = (pid_t) tmp; 149 150 if (xid==VC_NOCTX) 151 xid = vc_get_task_xid(pid); 152 if (vc_ctx_kill(xid,pid,sig)==-1) { 153 #if defined(VC_ENABLE_API_LEGACY) 154 int err = errno; 155 if (vc_get_version(VC_CAT_COMPAT)==-1) 156 return kill_wrapper_legacy(xid, pid_s, sig); 157 else { 158 errno = err; 159 #else 160 { 161 #endif 162 perror("vkill: vc_ctx_kill()"); 163 return 1; 164 } 165 } 166 return 0; 167 } 168 169 170 int main(int argc, char *argv[]) 171 { 172 int fail = 0; 173 struct Arguments args = { 174 .xid = VC_NOCTX, 175 .sig = SIGTERM, 176 }; 177 178 while (1) { 179 int c = getopt_long(argc, argv, "c:s:", CMDLINE_OPTIONS, 0); 180 if (c==-1) break; 181 182 switch (c) { 183 case CMD_HELP : showHelp(1, argv[0], 0); 184 case CMD_VERSION : showVersion(); 185 case 'c' : args.xid = Evc_xidopt2xid(optarg,true); break; 186 case 's' : args.sig = str2sig(optarg); break; 187 default : 188 WRITE_MSG(2, "Try '"); 189 WRITE_STR(2, argv[0]); 190 WRITE_MSG(2, " --help' for more information.\n"); 191 return EXIT_FAILURE; 192 break; 193 } 194 } 195 196 if (args.sig==-1) { 197 WRITE_MSG(2, "Invalid signal specified\n"); 198 return EXIT_FAILURE; 199 } 200 201 if (args.xid==VC_NOCTX && optind==argc) { 202 WRITE_MSG(2, "No pid specified\n"); 203 return EXIT_FAILURE; 204 } 205 206 if (optind==argc) 207 fail += kill_wrapper(args.xid, "0", args.sig); 208 else for (;optind<argc;++optind) 209 fail += kill_wrapper(args.xid, argv[optind], args.sig); 210 211 return fail==0 ? EXIT_SUCCESS : EXIT_FAILURE; 212 } 213 214 #ifdef TESTSUITE 215 void 216 vkill_test() 217 { 218 assert(str2sig("0") ==0 ); 219 assert(str2sig("1") ==1 ); 220 assert(str2sig("10")==10); 221 assert(str2sig("SIGHUP")==1); 222 assert(str2sig("HUP") ==1); 223 assert(str2sig("SIGCHLD")==17); 224 assert(str2sig("CHLD") ==17); 225 assert(str2sig("x")==-1); 226 assert(str2sig("1 0")==-1); 227 228 return 0; 229 } 230 #endif