02f386a5cc56518d7835bf9f42660a4656367fa2
[util-vserver.git] / src / vkill.c
1 // $Id: vkill.c,v 1.8 2004/08/19 14:30:50 ensc Exp $    --*- 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 "linuxvirtual.h"
25 #include "util.h"
26
27 #include <getopt.h>
28 #include <signal.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/resource.h>
36 #include <sys/wait.h>
37
38 #define ENSC_WRAPPERS_VSERVER   1
39 #define ENSC_WRAPPERS_UNISTD    1
40 #include <wrappers.h>
41
42 #define CMD_HELP        0x8000
43 #define CMD_VERSION     0x8001
44
45 int             wrapper_exit_code = 1;
46
47 static struct option const
48 CMDLINE_OPTIONS[] = {
49   { "help",     no_argument,        0, CMD_HELP },
50   { "version",  no_argument,        0, CMD_VERSION },
51   { "xid",      required_argument,  0, 'c' },
52   { 0,0,0,0 }
53 };
54
55 struct Arguments
56 {
57     xid_t               xid;
58     int                 sig;
59 };
60
61 static char const * const SIGNALS[] = {
62   // 0      1      2          3       4       5       6       7
63   "UNUSED", "HUP", "INT",     "QUIT", "ILL",  "TRAP", "ABRT", "UNUSED",
64   "FPE",    "KILL", "USR1",   "SEGV", "USR2", "PIPE", "ALRM", "TERM",
65   "STKFLT", "CHLD", "CONT",   "STOP", "TSTP", "TTIN", "TTOU", "IO",
66   "XCPU",   "XFSZ", "VTALRM", "PROF", "WINCH",
67   0,
68 };
69
70 static void
71 showHelp(int fd, char const *cmd, int res)
72 {
73   WRITE_MSG(fd, "Usage:  ");
74   WRITE_STR(fd, cmd);
75   WRITE_MSG(fd,
76             " [--xid|-c <xid>] [-s <signal>] [--] <pid>*\n"
77             "Please report bugs to " PACKAGE_BUGREPORT "\n");
78   exit(res);
79 }
80
81 static void
82 showVersion()
83 {
84   WRITE_MSG(1,
85             "vkill " VERSION " -- sends signals to processes within other contexts\n"
86             "This program is part of " PACKAGE_STRING "\n\n"
87             "Copyright (C) 2003 Enrico Scholz\n"
88             VERSION_COPYRIGHT_DISCLAIMER);
89   exit(0);
90 }
91
92 static int
93 str2sig(char const *str)
94 {
95   char  *errptr;
96   int   res = strtol(str, &errptr, 10);
97   
98   if (*errptr!='\0') res=-1;
99   if (res==-1 && strncmp(str,"SIG",3)==0) str+=3;
100   if (res==-1) {
101     char const * const  *ptr = SIGNALS;
102     for (;*ptr!=0; ++ptr) {
103       if (strcmp(*ptr,str)!=0) continue;
104       res = ptr-SIGNALS;
105       break;
106     }
107   }
108
109   return res;
110 }
111
112 #if defined(VC_ENABLE_API_LEGACY)
113 inline static ALWAYSINLINE int
114 kill_wrapper_legacy(xid_t UNUSED xid, char const *proc, int UNUSED sig)
115 {
116   pid_t         pid;
117
118   signal(SIGCHLD, SIG_DFL);
119   pid = Efork();
120
121   if (pid==0) {
122     int         status;
123     int         res;
124     while ((res=wait4(pid, &status, 0,0))==-1 &&
125            (errno==EAGAIN || errno==EINTR)) {}
126
127     return (res==0 && WIFEXITED(status) && WEXITSTATUS(status)) ? 0 : 1;
128   }
129
130   execl(LEGACYDIR "/vkill", "legacy/vkill", proc, (void *)(0));
131   perror("vkill: execl()");
132   exit(1);
133 }
134
135 static int
136 kill_wrapper(xid_t xid, char const *pid, int sig)
137 {
138   //printf("kill_wrapper(%u, %s, %i)\n", xid, pid, sig);
139   if (vc_ctx_kill(xid,atoi(pid),sig)==-1) {
140     int         err = errno;
141     if (vc_get_version(VC_CAT_COMPAT)==-1)
142       return kill_wrapper_legacy(xid, pid, sig);
143     else {
144       errno = err;
145       perror("vkill: vc_ctx_kill()");
146       return 1;
147     }
148   }
149   
150   return 0;
151 }
152 #else // VC_ENABLE_API_LEGACY
153 inline static int
154 kill_wrapper(xid_t xid, char const *pid, int sig)
155 {
156   if (vc_ctx_kill(xid,atoi(pid),sig)==-1) {
157     perror("vkill: vc_ctx_kill()");
158     return 1;
159   }
160   return 0;
161 }
162 #endif
163
164
165 int main(int argc, char *argv[])
166 {
167   int                   fail = 0;
168   struct Arguments      args = {
169     .xid = VC_NOCTX,
170     .sig = SIGTERM,
171   };
172   
173   while (1) {
174     int         c = getopt_long(argc, argv, "c:s:", CMDLINE_OPTIONS, 0);
175     if (c==-1) break;
176
177     switch (c) {
178       case CMD_HELP     :  showHelp(1, argv[0], 0);
179       case CMD_VERSION  :  showVersion();
180       case 'c'          :  args.xid = Evc_xidopt2xid(optarg,true); break;
181       case 's'          :  args.sig = str2sig(optarg);             break;
182       default           :
183         WRITE_MSG(2, "Try '");
184         WRITE_STR(2, argv[0]);
185         WRITE_MSG(2, " --help\" for more information.\n");
186         return EXIT_FAILURE;
187         break;
188     }
189   }
190
191   if (args.sig==-1) {
192     WRITE_MSG(2, "Invalid signal specified\n");
193     return EXIT_FAILURE;
194   }
195
196   if (args.xid==VC_NOCTX && optind==argc) {
197     WRITE_MSG(2, "No pid specified\n");
198     return EXIT_FAILURE;
199   }
200
201   if (optind==argc)
202     fail += kill_wrapper(args.xid, "0", args.sig);
203   else for (;optind<argc;++optind)
204     fail += kill_wrapper(args.xid, argv[optind], args.sig);
205
206   return fail==0 ? EXIT_SUCCESS : EXIT_FAILURE;
207 }
208
209 #ifdef TESTSUITE
210 void
211 vkill_test()
212 {
213   assert(str2sig("0") ==0 );
214   assert(str2sig("1") ==1 );
215   assert(str2sig("10")==10);
216   assert(str2sig("SIGHUP")==1);
217   assert(str2sig("HUP")   ==1);
218   assert(str2sig("SIGCHLD")==17);
219   assert(str2sig("CHLD")   ==17);
220   assert(str2sig("x")==-1);
221   assert(str2sig("1 0")==-1);
222
223   return 0;
224 }
225 #endif