]> sourceware.org Git - newlib-cygwin.git/blame - winsup/utils/kill.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / utils / kill.cc
CommitLineData
1fd5e000
CF
1/* kill.cc
2
df0f949c
CF
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
4 2009, 2011 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <signal.h>
15#include <string.h>
16#include <time.h>
cc631726
CF
17#include <errno.h>
18#include <windows.h>
6b70b463 19#include <sys/cygwin.h>
92b499ac 20#include <cygwin/version.h>
c49fa762 21#include <getopt.h>
87b83839 22#include <limits.h>
c49fa762 23
ef48a2ca
CF
24static char *prog_name;
25
c49fa762
CF
26static 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'},
92b499ac 32 {"version", no_argument, NULL, 'V'},
c49fa762
CF
33 {NULL, 0, NULL, 0}
34};
35
92b499ac 36static char opts[] = "hl::fs:V";
c49fa762 37
af53a09c 38static void
30feaa22 39usage (FILE *where = stderr)
af53a09c 40{
ef48a2ca 41 fprintf (where , ""
92b499ac
CV
42 "Usage: %1$s [-f] [-signal] [-s signal] pid1 [pid2 ...]\n"
43 " %1$s -l [signal]\n"
44 "\n"
aa275fe0
JDF
45 "Send signals to processes\n"
46 "\n"
ef48a2ca
CF
47 " -f, --force force, using win32 interface if necessary\n"
48 " -l, --list print a list of signal names\n"
92b499ac 49 " -s, --signal send signal (use %1$s --list for a list)\n"
ef48a2ca 50 " -h, --help output usage information and exit\n"
92b499ac
CV
51 " -V, --version output version information and exit\n"
52 "\n", prog_name);
30feaa22 53 exit (where == stderr ? 1 : 0);
af53a09c
CF
54}
55
ef48a2ca
CF
56static void
57print_version ()
58{
92b499ac 59 printf ("kill (cygwin) %d.%d.%d\n"
1b23b30b
CF
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"
92b499ac 63 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
1b23b30b
CF
64 CYGWIN_VERSION_DLL_MAJOR / 1000,
65 CYGWIN_VERSION_DLL_MAJOR % 1000,
66 CYGWIN_VERSION_DLL_MINOR,
67 strrchr (__DATE__, ' ') + 1);
ef48a2ca
CF
68}
69
5c8891e9
CF
70static const char *
71strsigno (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
af53a09c 80static int
c49fa762 81getsig (const char *in_sig)
af53a09c 82{
c49fa762 83 const char *sig;
af53a09c 84 char buf[80];
c49fa762 85 int intsig;
af53a09c
CF
86
87 if (strncmp (in_sig, "SIG", 3) == 0)
88 sig = in_sig;
89 else
90 {
45345618 91 sprintf (buf, "SIG%-.20s", in_sig);
af53a09c
CF
92 sig = buf;
93 }
c49fa762
CF
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
101static void
102test_for_unknown_sig (int sig, const char *sigstr)
103{
104 if (sig < 0 || sig > NSIG)
105 {
92b499ac
CV
106 fprintf (stderr, "%1$s: unknown signal: %2$s\n"
107 "Try `%1$s --help' for more information.\n",
108 prog_name, sigstr);
c49fa762
CF
109 exit (1);
110 }
111}
112
113static void
114listsig (const char *in_sig)
115{
116 int sig;
117 if (!in_sig)
0512945e 118 for (sig = 1; sig < NSIG - 1; sig++)
c49fa762
CF
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);
6eabab55
CF
124 if (atoi (in_sig) == sig)
125 puts (strsigno (sig) + 3);
126 else
127 printf ("%d\n", sig);
c49fa762 128 }
af53a09c
CF
129}
130
5817840a
CV
131static void
132get_debug_priv (void)
133{
134 HANDLE tok;
135 LUID luid;
136 TOKEN_PRIVILEGES tkp;
137
138 if (!OpenProcessToken (GetCurrentProcess (),
1b23b30b 139 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tok))
5817840a
CV
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
af53a09c
CF
157static void __stdcall
158forcekill (int pid, int sig, int wait)
159{
5817840a
CV
160 // try to acquire SeDebugPrivilege
161 get_debug_priv();
162
87b83839
PH
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);
40d885eb
CF
167 DWORD dwpid = p ? p->dwProcessId : (DWORD) pid;
168 HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, (DWORD) dwpid);
af53a09c 169 if (!h)
40d885eb 170 {
1b23b30b
CF
171 if (!wait || GetLastError () != ERROR_INVALID_PARAMETER)
172 fprintf (stderr, "%s: couldn't open pid %u\n",
173 prog_name, (unsigned) dwpid);
a98a0011 174 return;
40d885eb 175 }
af53a09c 176 if (!wait || WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
87b83839 177 if (sig && !TerminateProcess (h, sig << 8)
a98a0011 178 && WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
61522196
CV
179 fprintf (stderr, "%s: couldn't kill pid %u, %u\n",
180 prog_name, (unsigned) dwpid, (unsigned int) GetLastError ());
af53a09c
CF
181 CloseHandle (h);
182}
1fd5e000
CF
183
184int
cc631726 185main (int argc, char **argv)
1fd5e000
CF
186{
187 int sig = SIGTERM;
cc631726 188 int force = 0;
69f9407f 189 int ret = 0;
b1e00863 190 char *gotasig = NULL;
1fd5e000 191
92b499ac 192 prog_name = program_invocation_short_name;
ef48a2ca 193
cc631726 194 if (argc == 1)
1fd5e000
CF
195 usage ();
196
c49fa762 197 opterr = 0;
7ed1b504
CF
198
199 char *p;
87b83839 200 long long int pid = 0;
7ed1b504 201
c49fa762 202 for (;;)
1fd5e000 203 {
c49fa762
CF
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':
b1e00863
CF
211 gotasig = optarg;
212 sig = getsig (gotasig);
c49fa762
CF
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;
30feaa22
CF
231 case 'h':
232 usage (stdout);
233 break;
92b499ac 234 case 'V':
ef48a2ca
CF
235 print_version ();
236 break;
c49fa762 237 case '?':
b1e00863 238 if (gotasig)
7ed1b504 239 {
9e278ffd
CV
240 --optind;
241 goto out;
7ed1b504 242 }
c49fa762
CF
243 optreset = 1;
244 optind = 1 + av - argv;
b1e00863
CF
245 gotasig = *av + 1;
246 sig = getsig (gotasig);
c49fa762
CF
247 break;
248 default:
249 usage ();
250 break;
251 }
1fd5e000
CF
252 }
253
7ed1b504 254out:
b1e00863 255 test_for_unknown_sig (sig, gotasig);
c49fa762
CF
256
257 argv += optind;
cc631726 258 while (*argv != NULL)
1fd5e000 259 {
7ed1b504 260 if (!pid)
87b83839
PH
261 pid = strtoll (*argv, &p, 10);
262 if (*p != '\0'
61522196
CV
263 || (!force && (pid < INT_MIN || pid > INT_MAX))
264 || (force && (pid <= 0 || pid > UINT_MAX)))
12f6d7bc 265 {
ef48a2ca 266 fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv);
12f6d7bc
CF
267 ret = 1;
268 }
61522196 269 else if (pid <= INT_MAX && kill ((pid_t) pid, sig) == 0)
12f6d7bc
CF
270 {
271 if (force)
87b83839 272 forcekill ((pid_t) pid, sig, 1);
12f6d7bc 273 }
87b83839
PH
274 else if (force)
275 forcekill ((pid_t) pid, sig, 0);
1fd5e000
CF
276 else
277 {
12f6d7bc 278 char buf[1000];
87b83839 279 sprintf (buf, "%s: %lld", prog_name, pid);
12f6d7bc
CF
280 perror (buf);
281 ret = 1;
1fd5e000 282 }
cc631726 283 argv++;
7ed1b504 284 pid = 0;
1fd5e000 285 }
69f9407f 286 return ret;
1fd5e000 287}
5817840a 288
This page took 0.308451 seconds and 5 git commands to generate.