diff --git a/winsup/utils/ChangeLog b/winsup/utils/ChangeLog index ca99cb47a..71738b218 100644 --- a/winsup/utils/ChangeLog +++ b/winsup/utils/ChangeLog @@ -1,3 +1,14 @@ +Sat Jul 29 00:44:46 2000 Christopher Faylor + + * kill.cc (main): Add '-f' option to force termination of a process. + (forcekill): New function. + * ps.cc (main): Add '-W' option to list Windows pids as well as Cygwin + pids. + (dummyprocessmodules): New function. + (GetModuleFileNameEx95): New function. + (init_win): New function. + (to_time_t): New function. + Thu Jul 27 22:54:28 2000 Jason Tishler * utils/mount.cc (main): Add --show-cygdrive-prefixes option. @@ -31,11 +42,11 @@ Sat Jun 24 23:16:33 2000 Christopher Faylor 2000-06-07 Kazuhiro Fujieda - mount.cc (error): New function to report an error and exit. - umount.cc (error): Ditto. - (remove_all_automounts): Check return status of cygwin_umount. - (remove_all_user_mounts): Ditto. - (remove_all_system_mounts): Ditto. + * mount.cc (error): New function to report an error and exit. + * umount.cc (error): Ditto. + (remove_all_automounts): Check return status of cygwin_umount. + (remove_all_user_mounts): Ditto. + (remove_all_system_mounts): Ditto. 2000-06-05 DJ Delorie diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc index 611887896..a7913e43c 100644 --- a/winsup/utils/kill.cc +++ b/winsup/utils/kill.cc @@ -1,6 +1,6 @@ /* kill.cc - Copyright 1996, 1997, 1998 Cygnus Solutions. + Copyright 1996, 1997, 1998, 1999, 2000 Red Hat, Inc. This file is part of Cygwin. @@ -13,50 +13,72 @@ details. */ #include #include #include +#include +#include static void usage (void); -static int getsig (char *); -int a = _timezone; +static int __stdcall getsig (char *); +static void __stdcall forcekill (int, int); int -main (int ac, char **av) +main (int argc, char **argv) { int sig = SIGTERM; + int force = 0; + int gotsig = 0; - if (ac == 1) + if (argc == 1) usage (); - if (*(++av)[0] == '-') - if (strcmp(*av + 1, "0") != 0) - sig = getsig (*av++ + 1); + while (*(++argv)[0] == '-') + if (strcmp (*argv + 1, "f") == 0) + force = 1; + else if (gotsig) + break; + else if (strcmp(*argv + 1, "0") != 0) + { + sig = getsig (*argv++ + 1); + gotsig = 1; + } else { - av++; + argv++; sig = 0; goto sig0; } if (sig <= 0 || sig > NSIG) { - fprintf (stderr, "kill: unknown signal: %s\n", av[-1]); + fprintf (stderr, "kill: unknown signal: %s\n", argv[-1]); exit (1); } sig0: - while (*av != NULL) + while (*argv != NULL) { char *p; - int pid = strtol (*av, &p, 10); + int pid = strtol (*argv, &p, 10); if (*p != '\0') - fprintf (stderr, "kill: illegal pid: %s\n", *av); + fprintf (stderr, "kill: illegal pid: %s\n", *argv); else { +#if 0 printf ("Sending %s(%d) signal to pid %d\n", strsignal (sig), sig, pid); +#endif if (kill (pid, sig)) - perror ("kill"); + { + if (errno == ESRCH && force && sig != 0) + forcekill (pid, sig); + else + { + char buf[1000]; + sprintf (buf, "kill %d", pid); + perror (buf); + } + } } - av++; + argv++; } return 0; } @@ -83,3 +105,13 @@ getsig (char *in_sig) } return (strtosigno (sig) ?: atoi (in_sig)); } + +static void __stdcall +forcekill (int pid, int sig) +{ + HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, (DWORD) pid); + if (!h) + return; + TerminateProcess (h, sig << 8); + CloseHandle (h); +} diff --git a/winsup/utils/ps.cc b/winsup/utils/ps.cc index cca56ac5f..593629c22 100644 --- a/winsup/utils/ps.cc +++ b/winsup/utils/ps.cc @@ -1,6 +1,6 @@ /* ps.cc - Copyright 1996, 1997, 1998 Cygnus Solutions. + Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions. This file is part of Cygwin. @@ -16,6 +16,114 @@ details. */ #include #include #include +#include +#include + +typedef BOOL (WINAPI *ENUMPROCESSMODULES)( + HANDLE hProcess, // handle to the process + HMODULE * lphModule, // array to receive the module handles + DWORD cb, // size of the array + LPDWORD lpcbNeeded // receives the number of bytes returned +); + +typedef DWORD (WINAPI *GETMODULEFILENAME)( + HANDLE hProcess, + HMODULE hModule, + LPTSTR lpstrFileName, + DWORD nSize +); + +typedef HANDLE (WINAPI *CREATESNAPSHOT)( + DWORD dwFlags, + DWORD th32ProcessID +); + +// Win95 functions +typedef BOOL (WINAPI *PROCESSWALK)( + HANDLE hSnapshot, + LPPROCESSENTRY32 lppe +); + +ENUMPROCESSMODULES myEnumProcessModules; +GETMODULEFILENAME myGetModuleFileNameEx; +CREATESNAPSHOT myCreateToolhelp32Snapshot; +PROCESSWALK myProcess32First; +PROCESSWALK myProcess32Next; + +static BOOL WINAPI dummyprocessmodules ( + HANDLE hProcess, // handle to the process + HMODULE * lphModule, // array to receive the module handles + DWORD cb, // size of the array + LPDWORD lpcbNeeded // receives the number of bytes returned +) +{ + lphModule[0] = (HMODULE) *lpcbNeeded; + *lpcbNeeded = 1; + return 1; +} + +static DWORD WINAPI GetModuleFileNameEx95 ( + HANDLE hProcess, + HMODULE hModule, + LPTSTR lpstrFileName, + DWORD n +) +{ + HANDLE h; + DWORD pid = (DWORD) hModule; + + h = myCreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); + if (!h) + return 0; + + PROCESSENTRY32 proc; + proc.dwSize = sizeof (proc); + if (myProcess32First(h, &proc)) + do + if (proc.th32ProcessID == pid) + { + CloseHandle (h); + strcpy (lpstrFileName, proc.szExeFile); + return 1; + } + while (myProcess32Next (h, &proc)); + CloseHandle (h); + return 0; +} + +int +init_win () +{ + OSVERSIONINFO os_version_info; + + memset (&os_version_info, 0, sizeof os_version_info); + os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + GetVersionEx (&os_version_info); + + HMODULE h; + if (os_version_info.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + h = LoadLibrary ("psapi.dll"); + if (!h) + return 0; + myEnumProcessModules = (ENUMPROCESSMODULES) GetProcAddress (h, "EnumProcessModules"); + myGetModuleFileNameEx = (GETMODULEFILENAME) GetProcAddress (h, "GetModuleFileNameExA"); + if (!myEnumProcessModules || !myGetModuleFileNameEx) + return 0; + return 1; + } + + h = GetModuleHandle("KERNEL32.DLL"); + myCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress (h, "CreateToolhelp32Snapshot"); + myProcess32First = (PROCESSWALK)GetProcAddress (h, "Process32First"); + myProcess32Next = (PROCESSWALK)GetProcAddress (h, "Process32Next"); + if (!myCreateToolhelp32Snapshot || !myProcess32First || !myProcess32Next) + return 0; + + myEnumProcessModules = dummyprocessmodules; + myGetModuleFileNameEx = GetModuleFileNameEx95; + return 1; +} static char * start_time (external_pinfo *child) @@ -36,11 +144,33 @@ start_time (external_pinfo *child) return stime; } +#define FACTOR (0x19db1ded53ea710LL) +#define NSPERSEC 10000000LL + +/* Convert a Win32 time to "UNIX" format. */ +long __stdcall +to_time_t (FILETIME *ptr) +{ + /* A file time is the number of 100ns since jan 1 1601 + stuffed into two long words. + A time_t is the number of seconds since jan 1 1970. */ + + long rem; + long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned)ptr->dwLowDateTime); + x -= FACTOR; /* number of 100ns between 1601 and 1970 */ + rem = x % ((long long)NSPERSEC); + rem += (NSPERSEC / 2); + x /= (long long) NSPERSEC; /* number of 100ns in a second */ + x += (long long) (rem / NSPERSEC); + return x; +} + int main (int argc, char *argv[]) { external_pinfo *p; - int aflag, lflag, fflag, uid; + int aflag, lflag, fflag, sflag, uid; + cygwin_getinfo_types query = CW_GETPINFO; const char *dtitle = " PID TTY STIME COMMAND\n"; const char *dfmt = "%5d%4d%10s %s\n"; const char *ftitle = " UID PID PPID TTY STIME COMMAND\n"; @@ -49,10 +179,11 @@ main (int argc, char *argv[]) const char *lfmt = "%c %5d %5d %5d %8u %4d %3d %8s %s\n"; char ch; - aflag = lflag = fflag = 0; + aflag = lflag = fflag = sflag = 0; uid = getuid (); + lflag = 1; - while ((ch = getopt (argc, argv, "aelfu:")) != -1) + while ((ch = getopt (argc, argv, "aelfsu:W")) != -1) switch (ch) { case 'a': @@ -65,6 +196,9 @@ main (int argc, char *argv[]) case 'l': lflag = 1; break; + case 's': + sflag = 1; + break; case 'u': uid = atoi (optarg); if (uid == 0) @@ -80,27 +214,36 @@ main (int argc, char *argv[]) } } break; + case 'W': + query = CW_GETPINFO_FULL; + aflag = 1; + break; + default: fprintf (stderr, "Usage %s [-aefl] [-u uid]\n", argv[0]); fprintf (stderr, "-f = show process uids, ppids\n"); fprintf (stderr, "-l = show process uids, ppids, pgids, winpids\n"); fprintf (stderr, "-u uid = list processes owned by uid\n"); fprintf (stderr, "-a, -e = show processes of all users\n"); + fprintf (stderr, "-s = show process summary\n"); + fprintf (stderr, "-W = show windows as well as cygwin processes\n"); exit (1); } - if (lflag) - printf (ltitle); + if (sflag) + printf (dtitle); else if (fflag) printf (ftitle); - else - printf (dtitle); + else if (lflag) + printf (ltitle); (void) cygwin_internal (CW_LOCK_PINFO, 1000); + if (query == CW_GETPINFO_FULL && !init_win ()) + query = CW_GETPINFO; + for (int pid = 0; - (p = (external_pinfo *) cygwin_internal (CW_GETPINFO, - pid | CW_NEXTPID)); + (p = (external_pinfo *) cygwin_internal (query, pid | CW_NEXTPID)); pid = p->pid) { if (p->process_state == PID_NOT_IN_USE) @@ -118,8 +261,30 @@ main (int argc, char *argv[]) char pname[MAX_PATH]; if (p->process_state & PID_ZOMBIE) strcpy (pname, ""); + else if (p->progname[0]) + { + char *s; + cygwin_conv_to_posix_path (p->progname, pname); + s = strchr (pname, '\0') - 4; + if (s > pname && strcasecmp (s, ".exe") == 0) + *s = '\0'; + } else - cygwin_conv_to_posix_path (p->progname, pname); + { + HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, p->dwProcessId); + if (!h) + continue; + HMODULE hm[1000]; + DWORD n = p->dwProcessId; + if (!myEnumProcessModules (h, hm, sizeof (hm), &n)) + n = 0; + if (!n || !myGetModuleFileNameEx (h, hm[0], pname, MAX_PATH)) + strcpy (pname, "*** unknown ***"); + FILETIME ct, et, kt, ut; + if (GetProcessTimes (h, &ct, &et, &kt, &ut)) + p->start_time = to_time_t (&ct); + CloseHandle (h); + } char uname[128]; @@ -133,13 +298,13 @@ main (int argc, char *argv[]) sprintf (uname, "%d", p->uid); } - if (lflag) - printf (lfmt, status, p->pid, p->ppid, p->pgid, - p->dwProcessId, p->uid, p->ctty, start_time (p), pname); + if (sflag) + printf (dfmt, p->pid, p->ctty, start_time (p), pname); else if (fflag) printf (ffmt, uname, p->pid, p->ppid, p->ctty, start_time (p), pname); - else - printf (dfmt, p->pid, p->ctty, start_time (p), pname); + else if (lflag) + printf (lfmt, status, p->pid, p->ppid, p->pgid, + p->dwProcessId, p->uid, p->ctty, start_time (p), pname); } (void) cygwin_internal (CW_UNLOCK_PINFO);