3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 #include <sys/cygwin.h>
17 #include <cygwin/version.h>
21 static char *prog_name
;
23 static struct option longopts
[] =
25 {"help", no_argument
, NULL
, 'h' },
26 {"list", optional_argument
, NULL
, 'l'},
27 {"force", no_argument
, NULL
, 'f'},
28 {"signal", required_argument
, NULL
, 's'},
29 {"winpid", no_argument
, NULL
, 'W'},
30 {"version", no_argument
, NULL
, 'V'},
34 static char opts
[] = "hl::fs:WV";
37 usage (FILE *where
= stderr
)
40 "Usage: %1$s [-fW] [-signal] [-s signal] pid1 [pid2 ...]\n"
43 "Send signals to processes\n"
45 " -f, --force force, using win32 interface if necessary\n"
46 " -l, --list print a list of signal names\n"
47 " -s, --signal send signal (use %1$s --list for a list)\n"
48 " -W, --winpid specified pids are windows PIDs, not Cygwin PIDs\n"
49 " (use with extreme caution!)\n"
50 " -h, --help output usage information and exit\n"
51 " -V, --version output version information and exit\n"
53 exit (where
== stderr
? 1 : 0);
59 printf ("kill (cygwin) %d.%d.%d\n"
61 "Copyright (C) 1996 - %s Cygwin Authors\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);
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
);
81 getsig (const char *in_sig
)
87 if (strncmp (in_sig
, "SIG", 3) == 0)
91 sprintf (buf
, "SIG%-.20s", in_sig
);
94 intsig
= strtosigno (sig
) ?: atoi (in_sig
);
96 if (!intsig
&& (strcmp (sig
, "SIG0") != 0 && (strtol (in_sig
, &p
, 10) != 0 || *p
)))
102 test_for_unknown_sig (int sig
, const char *sigstr
)
104 if (sig
< 0 || sig
> NSIG
)
106 fprintf (stderr
, "%1$s: unknown signal: %2$s\n"
107 "Try `%1$s --help' for more information.\n",
114 listsig (const char *in_sig
)
118 for (sig
= 1; sig
< NSIG
- 1; sig
++)
119 printf ("%s%c", strsigno (sig
) + 3, (sig
< NSIG
- 1) ? ' ' : '\n');
122 sig
= getsig (in_sig
);
123 test_for_unknown_sig (sig
, in_sig
);
124 if (sig
&& atoi (in_sig
) == sig
)
125 puts (strsigno (sig
) + 3);
127 printf ("%d\n", sig
);
132 get_debug_priv (void)
136 TOKEN_PRIVILEGES tkp
;
138 if (!OpenProcessToken (GetCurrentProcess (),
139 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &tok
))
142 if (!LookupPrivilegeValue (NULL
, SE_DEBUG_NAME
, &luid
))
148 tkp
.PrivilegeCount
= 1;
149 tkp
.Privileges
[0].Luid
= luid
;
150 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
152 AdjustTokenPrivileges (tok
, FALSE
, &tkp
, sizeof tkp
, NULL
, NULL
);
157 static void __stdcall
158 forcekill (pid_t pid
, DWORD winpid
, int sig
, int wait
)
162 /* try to acquire SeDebugPrivilege */
167 external_pinfo
*p
= (external_pinfo
*)
168 cygwin_internal (CW_GETPINFO_FULL
, pid
);
171 fprintf (stderr
, "%s: %d: No such process\n", prog_name
, pid
);
174 dwpid
= p
->dwProcessId
;
177 /* pid is used for printing only after this point */
178 pid
= dwpid
= winpid
;
180 HANDLE h
= OpenProcess (PROCESS_TERMINATE
, FALSE
, dwpid
);
183 if (!wait
|| GetLastError () != ERROR_INVALID_PARAMETER
)
184 fprintf (stderr
, "%s: couldn't open pid %u\n",
185 prog_name
, (unsigned int) dwpid
);
188 if (!wait
|| WaitForSingleObject (h
, 200) != WAIT_OBJECT_0
)
189 if (sig
&& !TerminateProcess (h
, sig
<< 8)
190 && WaitForSingleObject (h
, 200) != WAIT_OBJECT_0
)
191 fprintf (stderr
, "%s: couldn't kill pid %u, %u\n",
192 prog_name
, (unsigned int) dwpid
, (unsigned int) GetLastError ());
197 main (int argc
, char **argv
)
203 char *gotasig
= NULL
;
205 prog_name
= program_invocation_short_name
;
217 char **av
= argv
+ optind
;
218 if ((ch
= getopt_long (argc
, argv
, opts
, longopts
, NULL
)) == EOF
)
224 sig
= getsig (gotasig
);
229 optarg
= argv
[optind
];
253 if (gotasig
) /* this is a negative pid, go ahead */
259 optind
= 1 + av
- argv
;
261 sig
= getsig (gotasig
);
270 test_for_unknown_sig (sig
, gotasig
);
275 fprintf (stderr
, "%s: not enough arguments\n", prog_name
);
278 for (long long int pid
= 0; *argv
!= NULL
; argv
++)
282 pid
= strtoll (*argv
, &p
, 10);
283 /* INT_MIN <= pid <= INT_MAX. -f only takes positive pids. */
284 if (*p
!= '\0' || pid
< (force
? 1 : INT_MIN
) || pid
> INT_MAX
)
286 fprintf (stderr
, "%s: illegal pid: %s\n", prog_name
, *argv
);
293 pid
= (pid_t
) cygwin_internal (CW_WINPID_TO_CYGWIN_PID
, dwpid
);
295 if (kill ((pid_t
) pid
, sig
) == 0)
298 forcekill ((pid_t
) pid
, dwpid
, sig
, 1);
301 forcekill ((pid_t
) pid
, dwpid
, sig
, 0);
305 sprintf (buf
, "%s: %lld", prog_name
, dwpid
?: pid
);