Updated to Git v1.8.1
[msysgit.git] / src / rt / patches / 0004-Added-Cygwin-implementation-of-kill.patch
blobbd01518d4d21f53034d7940ce2efe11d7a701d2a
1 From 7703f21b767e2cd2fb9089a3e17f18a541a3f491 Mon Sep 17 00:00:00 2001
2 From: Alexander Gavrilov <angavrilov@gmail.com>
3 Date: Mon, 14 Jul 2008 22:44:47 +0400
4 Subject: [PATCH] Added Cygwin implementation of kill.
6 Cygwin uses a special implementation of kill, that supports
7 terminating native Windows processes via the '-f' switch.
9 It is necessary for killing msysgit back-ends from Tcl/Tk.
11 kill.cc: Revision 1.27 from Cygwin CVS
12 ---
13 source/winsup/utils/Makefile.in | 10 ++-
14 source/winsup/utils/kill.cc | 294 +++++++++++++++++++++++++++++++++++++++
15 2 files changed, 303 insertions(+), 1 deletions(-)
16 create mode 100644 source/winsup/utils/kill.cc
18 diff --git a/source/winsup/utils/Makefile.in b/source/winsup/utils/Makefile.in
19 index a59f3bb..af96c3d 100644
20 --- a/source/winsup/utils/Makefile.in
21 +++ b/source/winsup/utils/Makefile.in
22 @@ -64,7 +64,7 @@ MINGW_LDFLAGS:=-B/usr/lib/mingw $(MINGW_LIB)
24 PROGS:=mount$(EXEEXT) ps$(EXEEXT) \
25 cygpath$(EXEEXT) cygcheck$(EXEEXT) \
26 - strace$(EXEEXT)
27 + kill$(EXEEXT) strace$(EXEEXT)
29 CLEAN_PROGS:=$(PROGS)
31 @@ -91,6 +91,14 @@ else
32 $(MINGW_CC) $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) $<
33 endif
35 +kill$(EXEEXT): kill.o $(bupdir1)/libiberty/strsignal.o
36 +ifdef VERBOSE
37 + $(CXX) -o $@ $^ -B$(cygwin_build)/ $(ALL_LDFLAGS) $(KILL_LIB)
38 +else
39 + @echo $(CXX) -o $@ $^ ${filter-out -B%, $(ALL_LDFLAGS)};\
40 + $(CXX) -o $@ $^ -B$(cygwin_build)/ $(ALL_LDFLAGS) $(KILL_LIB)
41 +endif
43 clean:
44 rm -f *.o $(CLEAN_PROGS)
46 diff --git a/source/winsup/utils/kill.cc b/source/winsup/utils/kill.cc
47 new file mode 100644
48 index 0000000..e21646f
49 --- /dev/null
50 +++ b/source/winsup/utils/kill.cc
51 @@ -0,0 +1,294 @@
52 +/* kill.cc
54 + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
56 +This file is part of Cygwin.
58 +This software is a copyrighted work licensed under the terms of the
59 +Cygwin license. Please consult the file "CYGWIN_LICENSE" for
60 +details. */
62 +#include <stdio.h>
63 +#include <stdlib.h>
64 +#include <signal.h>
65 +#include <string.h>
66 +#include <time.h>
67 +#include <errno.h>
68 +#include <windows.h>
69 +#include <sys/cygwin.h>
70 +#include <getopt.h>
71 +#include <limits.h>
73 +static const char version[] = "$Revision: 1.14 $";
74 +static char *prog_name;
76 +static struct option longopts[] =
78 + {"help", no_argument, NULL, 'h' },
79 + {"list", optional_argument, NULL, 'l'},
80 + {"force", no_argument, NULL, 'f'},
81 + {"signal", required_argument, NULL, 's'},
82 + {"version", no_argument, NULL, 'v'},
83 + {NULL, 0, NULL, 0}
84 +};
86 +static char opts[] = "hl::fs:v";
88 +extern "C" const char *strsigno (int);
90 +static void
91 +usage (FILE *where = stderr)
93 + fprintf (where , ""
94 + "Usage: %s [-f] [-signal] [-s signal] pid1 [pid2 ...]\n"
95 + " %s -l [signal]\n"
96 + "Send signals to processes\n"
97 + "\n"
98 + " -f, --force force, using win32 interface if necessary\n"
99 + " -l, --list print a list of signal names\n"
100 + " -s, --signal send signal (use %s --list for a list)\n"
101 + " -h, --help output usage information and exit\n"
102 + " -v, --version output version information and exit\n"
103 + "", prog_name, prog_name, prog_name);
104 + exit (where == stderr ? 1 : 0);
107 +static void
108 +print_version ()
110 + const char *v = strchr (version, ':');
111 + int len;
112 + if (!v)
114 + v = "?";
115 + len = 1;
117 + else
119 + v += 2;
120 + len = strchr (v, ' ') - v;
122 + printf ("\
123 +%s (cygwin) %.*s\n\
124 +Process Signaller\n\
125 +Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
126 +Compiled on %s\n\
127 +", prog_name, len, v, __DATE__);
130 +static int
131 +getsig (const char *in_sig)
133 + const char *sig;
134 + char buf[80];
135 + int intsig;
137 + if (strncmp (in_sig, "SIG", 3) == 0)
138 + sig = in_sig;
139 + else
141 + sprintf (buf, "SIG%-.20s", in_sig);
142 + sig = buf;
144 + intsig = strtosigno (sig) ?: atoi (in_sig);
145 + char *p;
146 + if (!intsig && (strcmp (buf, "SIG0") != 0 && (strtol (in_sig, &p, 10) != 0 || *p)))
147 + intsig = -1;
148 + return intsig;
151 +static void
152 +test_for_unknown_sig (int sig, const char *sigstr)
154 + if (sig < 0 || sig > NSIG)
156 + fprintf (stderr, "%s: unknown signal: %s\n", prog_name, sigstr);
157 + usage ();
158 + exit (1);
162 +static void
163 +listsig (const char *in_sig)
165 + int sig;
166 + if (!in_sig)
167 + for (sig = 1; sig < NSIG - 1; sig++)
168 + printf ("%s%c", strsigno (sig) + 3, (sig < NSIG - 1) ? ' ' : '\n');
169 + else
171 + sig = getsig (in_sig);
172 + test_for_unknown_sig (sig, in_sig);
173 + if (atoi (in_sig) == sig)
174 + puts (strsigno (sig) + 3);
175 + else
176 + printf ("%d\n", sig);
180 +static void
181 +get_debug_priv (void)
183 + HANDLE tok;
184 + LUID luid;
185 + TOKEN_PRIVILEGES tkp;
187 + if (!OpenProcessToken (GetCurrentProcess (),
188 + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tok))
189 + return;
191 + if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid))
193 + CloseHandle (tok);
194 + return;
197 + tkp.PrivilegeCount = 1;
198 + tkp.Privileges[0].Luid = luid;
199 + tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
201 + AdjustTokenPrivileges (tok, FALSE, &tkp, sizeof tkp, NULL, NULL);
203 + CloseHandle (tok);
206 +static void __stdcall
207 +forcekill (int pid, int sig, int wait)
209 + // try to acquire SeDebugPrivilege
210 + get_debug_priv();
212 + external_pinfo *p = NULL;
213 + /* cygwin_internal misinterprets negative pids (Win9x pids) */
214 + if (pid > 0)
215 + p = (external_pinfo *) cygwin_internal (CW_GETPINFO_FULL, pid);
216 + DWORD dwpid = p ? p->dwProcessId : (DWORD) pid;
217 + HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, (DWORD) dwpid);
218 + if (!h)
220 + if (!wait || GetLastError () != ERROR_INVALID_PARAMETER)
221 + fprintf (stderr, "%s: couldn't open pid %u\n",
222 + prog_name, (unsigned) dwpid);
223 + return;
225 + if (!wait || WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
226 + if (sig && !TerminateProcess (h, sig << 8)
227 + && WaitForSingleObject (h, 200) != WAIT_OBJECT_0)
228 + fprintf (stderr, "%s: couldn't kill pid %u, %lu\n",
229 + prog_name, (unsigned) dwpid, GetLastError ());
230 + CloseHandle (h);
233 +int
234 +main (int argc, char **argv)
236 + int sig = SIGTERM;
237 + int force = 0;
238 + int ret = 0;
239 + char *gotasig = NULL;
241 + prog_name = strrchr (argv[0], '/');
242 + if (prog_name == NULL)
243 + prog_name = strrchr (argv[0], '\\');
244 + if (prog_name == NULL)
245 + prog_name = argv[0];
246 + else
247 + prog_name++;
249 + if (argc == 1)
250 + usage ();
252 + opterr = 0;
254 + char *p;
255 + long long int pid = 0;
257 + for (;;)
259 + int ch;
260 + char **av = argv + optind;
261 + if ((ch = getopt_long (argc, argv, opts, longopts, NULL)) == EOF)
262 + break;
263 + switch (ch)
265 + case 's':
266 + gotasig = optarg;
267 + sig = getsig (gotasig);
268 + break;
269 + case 'l':
270 + if (!optarg)
272 + optarg = argv[optind];
273 + if (optarg)
275 + optind++;
276 + optreset = 1;
279 + if (argv[optind])
280 + usage ();
281 + listsig (optarg);
282 + break;
283 + case 'f':
284 + force = 1;
285 + break;
286 + case 'h':
287 + usage (stdout);
288 + break;
289 + case 'v':
290 + print_version ();
291 + break;
292 + case '?':
293 + if (gotasig)
295 + pid = strtoll (argv[optind], &p, 10);
296 + if (pid < 0)
297 + goto out;
298 + usage ();
300 + optreset = 1;
301 + optind = 1 + av - argv;
302 + gotasig = *av + 1;
303 + sig = getsig (gotasig);
304 + break;
305 + default:
306 + usage ();
307 + break;
311 +out:
312 + test_for_unknown_sig (sig, gotasig);
314 + argv += optind;
315 + while (*argv != NULL)
317 + if (!pid)
318 + pid = strtoll (*argv, &p, 10);
319 + if (*p != '\0'
320 + || (!force && (pid < LONG_MIN || pid > LONG_MAX))
321 + || (force && (pid <= 0 || pid > ULONG_MAX)))
323 + fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv);
324 + ret = 1;
326 + else if (pid <= LONG_MAX && kill ((pid_t) pid, sig) == 0)
328 + if (force)
329 + forcekill ((pid_t) pid, sig, 1);
331 + else if (force)
332 + forcekill ((pid_t) pid, sig, 0);
333 + else
335 + char buf[1000];
336 + sprintf (buf, "%s: %lld", prog_name, pid);
337 + perror (buf);
338 + ret = 1;
340 + argv++;
341 + pid = 0;
343 + return ret;
347 1.5.6.2.1111.g806df