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
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) \
27 + kill$(EXEEXT) strace$(EXEEXT)
31 @@ -91,6 +91,14 @@ else
32 $(MINGW_CC) $c -o $(@D)/$(basename $@)$o $(MINGW_CFLAGS) $<
35 +kill$(EXEEXT): kill.o $(bupdir1)/libiberty/strsignal.o
37 + $(CXX) -o $@ $^ -B$(cygwin_build)/ $(ALL_LDFLAGS) $(KILL_LIB)
39 + @echo $(CXX) -o $@ $^ ${filter-out -B%, $(ALL_LDFLAGS)};\
40 + $(CXX) -o $@ $^ -B$(cygwin_build)/ $(ALL_LDFLAGS) $(KILL_LIB)
44 rm -f *.o $(CLEAN_PROGS)
46 diff --git a/source/winsup/utils/kill.cc b/source/winsup/utils/kill.cc
48 index 0000000..e21646f
50 +++ b/source/winsup/utils/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
69 +#include <sys/cygwin.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'},
86 +static char opts[] = "hl::fs:v";
88 +extern "C" const char *strsigno (int);
91 +usage (FILE *where = stderr)
94 + "Usage: %s [-f] [-signal] [-s signal] pid1 [pid2 ...]\n"
96 + "Send signals to processes\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);
110 + const char *v = strchr (version, ':');
120 + len = strchr (v, ' ') - v;
124 +Process Signaller\n\
125 +Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.\n\
127 +", prog_name, len, v, __DATE__);
131 +getsig (const char *in_sig)
137 + if (strncmp (in_sig, "SIG", 3) == 0)
141 + sprintf (buf, "SIG%-.20s", in_sig);
144 + intsig = strtosigno (sig) ?: atoi (in_sig);
146 + if (!intsig && (strcmp (buf, "SIG0") != 0 && (strtol (in_sig, &p, 10) != 0 || *p)))
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);
163 +listsig (const char *in_sig)
167 + for (sig = 1; sig < NSIG - 1; sig++)
168 + printf ("%s%c", strsigno (sig) + 3, (sig < NSIG - 1) ? ' ' : '\n');
171 + sig = getsig (in_sig);
172 + test_for_unknown_sig (sig, in_sig);
173 + if (atoi (in_sig) == sig)
174 + puts (strsigno (sig) + 3);
176 + printf ("%d\n", sig);
181 +get_debug_priv (void)
185 + TOKEN_PRIVILEGES tkp;
187 + if (!OpenProcessToken (GetCurrentProcess (),
188 + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tok))
191 + if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &luid))
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);
206 +static void __stdcall
207 +forcekill (int pid, int sig, int wait)
209 + // try to acquire SeDebugPrivilege
212 + external_pinfo *p = NULL;
213 + /* cygwin_internal misinterprets negative pids (Win9x pids) */
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);
220 + if (!wait || GetLastError () != ERROR_INVALID_PARAMETER)
221 + fprintf (stderr, "%s: couldn't open pid %u\n",
222 + prog_name, (unsigned) dwpid);
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 ());
234 +main (int argc, char **argv)
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];
255 + long long int pid = 0;
260 + char **av = argv + optind;
261 + if ((ch = getopt_long (argc, argv, opts, longopts, NULL)) == EOF)
267 + sig = getsig (gotasig);
272 + optarg = argv[optind];
295 + pid = strtoll (argv[optind], &p, 10);
301 + optind = 1 + av - argv;
303 + sig = getsig (gotasig);
312 + test_for_unknown_sig (sig, gotasig);
315 + while (*argv != NULL)
318 + pid = strtoll (*argv, &p, 10);
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);
326 + else if (pid <= LONG_MAX && kill ((pid_t) pid, sig) == 0)
329 + forcekill ((pid_t) pid, sig, 1);
332 + forcekill ((pid_t) pid, sig, 0);
336 + sprintf (buf, "%s: %lld", prog_name, pid);