]> sourceware.org Git - newlib-cygwin.git/blob - winsup/utils/kill.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / utils / kill.cc
1 /* kill.cc
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
4 2009, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <signal.h>
15 #include <string.h>
16 #include <time.h>
17 #include <errno.h>
18 #include <windows.h>
19 #include <sys/cygwin.h>
20 #include <cygwin/version.h>
21 #include <getopt.h>
22 #include <limits.h>
23
24 static char *prog_name;
25
26 static struct option longopts[] =
27 {
28 {"help", no_argument, NULL, 'h' },
29 {"list", optional_argument, NULL, 'l'},
30 {"force", no_argument, NULL, 'f'},
31 {"signal", required_argument, NULL, 's'},
32 {"version", no_argument, NULL, 'V'},
33 {NULL, 0, NULL, 0}
34 };
35
36 static char opts[] = "hl::fs:V";
37
38 static void
39 usage (FILE *where = stderr)
40 {
41 fprintf (where , ""
42 "Usage: %1$s [-f] [-signal] [-s signal] pid1 [pid2 ...]\n"
43 " %1$s -l [signal]\n"
44 "\n"
45 "Send signals to processes\n"
46 "\n"
47 " -f, --force force, using win32 interface if necessary\n"
48 " -l, --list print a list of signal names\n"
49 " -s, --signal send signal (use %1$s --list for a list)\n"
50 " -h, --help output usage information and exit\n"
51 " -V, --version output version information and exit\n"
52 "\n", prog_name);
53 exit (where == stderr ? 1 : 0);
54 }
55
56 static void
57 print_version ()
58 {
59 printf ("kill (cygwin) %d.%d.%d\n"
60 "Process Signaller\n"
61 "Copyright (C) 1996 - %s Red Hat, Inc.\n"
62 "This is free software; see the source for copying conditions. There is NO\n"
63 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
64 CYGWIN_VERSION_DLL_MAJOR / 1000,
65 CYGWIN_VERSION_DLL_MAJOR % 1000,
66 CYGWIN_VERSION_DLL_MINOR,
67 strrchr (__DATE__, ' ') + 1);
68 }
69
70 static const char *
71 strsigno (int signo)
72 {
73 if (signo >= 0 && signo < NSIG)
74 return sys_sigabbrev[signo];
75 static char buf[sizeof ("Unknown signal") + 32];
76 sprintf (buf, "Unknown signal %d", signo);
77 return buf;
78 }
79
80 static int
81 getsig (const char *in_sig)
82 {
83 const char *sig;
84 char buf[80];
85 int intsig;
86
87 if (strncmp (in_sig, "SIG", 3) == 0)
88 sig = in_sig;
89 else
90 {
91 sprintf (buf, "SIG%-.20s", in_sig);
92 sig = buf;
93 }
94 intsig = strtosigno (sig) ?: atoi (in_sig);
95 char *p;
96 if (!intsig && (strcmp (buf, "SIG0") != 0 && (strtol (in_sig, &p, 10) != 0 || *p)))
97 intsig = -1;
98 return intsig;
99 }
100
101 static void
102 test_for_unknown_sig (int sig, const char *sigstr)
103 {
104 if (sig < 0 || sig > NSIG)
105 {
106 fprintf (stderr, "%1$s: unknown signal: %2$s\n"
107 "Try `%1$s --help' for more information.\n",
108 prog_name, sigstr);
109 exit (1);
110 }
111 }
112
113 static void
114 listsig (const char *in_sig)
115 {
116 int sig;
117 if (!in_sig)
118 for (sig = 1; sig < NSIG - 1; sig++)
119 printf ("%s%c", strsigno (sig) + 3, (sig < NSIG - 1) ? ' ' : '\n');
120 else
121 {
122 sig = getsig (in_sig);
123 test_for_unknown_sig (sig, in_sig);
124 if (atoi (in_sig) == sig)
125 puts (strsigno (sig) + 3);
126 else
127 printf ("%d\n", sig);
128 }
129 }
130
131 static void
132 get_debug_priv (void)
133 {
134 HANDLE tok;
135 LUID luid;
136 TOKEN_PRIVILEGES tkp;
137
138 if (!OpenProcessToken (GetCurrentProcess (),
139 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tok))
140 return;
141
142 if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid))
143 {
144 CloseHandle (tok);
145 return;
146 }
147
148 tkp.PrivilegeCount = 1;
149 tkp.Privileges[0].Luid = luid;
150 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
151
152 AdjustTokenPrivileges (tok, FALSE, &tkp, sizeof tkp, NULL, NULL);
153
154 CloseHandle (tok);
155 }
156
157 static void __stdcall
158 forcekill (int pid, int sig, int wait)
159 {
160 // try to acquire SeDebugPrivilege
161 get_debug_priv();
162
163 external_pinfo *p = NULL;
164 /* cygwin_internal misinterprets negative pids (Win9x pids) */
165 if (pid > 0)
166 p = (external_pinfo *) cygwin_internal (CW_GETPINFO_FULL, pid);
167 DWORD dwpid = p ? p->dwProcessId : (DWORD) pid;
168 HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, (DWORD) dwpid);
169 if (!h)
170 {
171 if (!wait || GetLastError () != ERROR_INVALID_PARAMETER)
172 fprintf (stderr, "%s: couldn't open pid %u\n",
173 prog_name, (unsigned) dwpid);
174 return;
175 }
176 if (!wait || WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
177 if (sig && !TerminateProcess (h, sig << 8)
178 && WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
179 fprintf (stderr, "%s: couldn't kill pid %u, %u\n",
180 prog_name, (unsigned) dwpid, (unsigned int) GetLastError ());
181 CloseHandle (h);
182 }
183
184 int
185 main (int argc, char **argv)
186 {
187 int sig = SIGTERM;
188 int force = 0;
189 int ret = 0;
190 char *gotasig = NULL;
191
192 prog_name = program_invocation_short_name;
193
194 if (argc == 1)
195 usage ();
196
197 opterr = 0;
198
199 char *p;
200 long long int pid = 0;
201
202 for (;;)
203 {
204 int ch;
205 char **av = argv + optind;
206 if ((ch = getopt_long (argc, argv, opts, longopts, NULL)) == EOF)
207 break;
208 switch (ch)
209 {
210 case 's':
211 gotasig = optarg;
212 sig = getsig (gotasig);
213 break;
214 case 'l':
215 if (!optarg)
216 {
217 optarg = argv[optind];
218 if (optarg)
219 {
220 optind++;
221 optreset = 1;
222 }
223 }
224 if (argv[optind])
225 usage ();
226 listsig (optarg);
227 break;
228 case 'f':
229 force = 1;
230 break;
231 case 'h':
232 usage (stdout);
233 break;
234 case 'V':
235 print_version ();
236 break;
237 case '?':
238 if (gotasig)
239 {
240 --optind;
241 goto out;
242 }
243 optreset = 1;
244 optind = 1 + av - argv;
245 gotasig = *av + 1;
246 sig = getsig (gotasig);
247 break;
248 default:
249 usage ();
250 break;
251 }
252 }
253
254 out:
255 test_for_unknown_sig (sig, gotasig);
256
257 argv += optind;
258 while (*argv != NULL)
259 {
260 if (!pid)
261 pid = strtoll (*argv, &p, 10);
262 if (*p != '\0'
263 || (!force && (pid < INT_MIN || pid > INT_MAX))
264 || (force && (pid <= 0 || pid > UINT_MAX)))
265 {
266 fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv);
267 ret = 1;
268 }
269 else if (pid <= INT_MAX && kill ((pid_t) pid, sig) == 0)
270 {
271 if (force)
272 forcekill ((pid_t) pid, sig, 1);
273 }
274 else if (force)
275 forcekill ((pid_t) pid, sig, 0);
276 else
277 {
278 char buf[1000];
279 sprintf (buf, "%s: %lld", prog_name, pid);
280 perror (buf);
281 ret = 1;
282 }
283 argv++;
284 pid = 0;
285 }
286 return ret;
287 }
288
This page took 0.049277 seconds and 6 git commands to generate.