OSDN Git Service

* kill.cc (main): Add '-f' option to force termination of a process.
authorcgf <cgf>
Sat, 29 Jul 2000 16:26:37 +0000 (16:26 +0000)
committercgf <cgf>
Sat, 29 Jul 2000 16:26:37 +0000 (16:26 +0000)
(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.

winsup/utils/ChangeLog
winsup/utils/kill.cc
winsup/utils/ps.cc

index ca99cb4..71738b2 100644 (file)
@@ -1,3 +1,14 @@
+Sat Jul 29 00:44:46 2000  Christopher Faylor <cgf@cygnus.com>
+
+       * 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 <jt@dothill.com>
 
        * utils/mount.cc (main): Add --show-cygdrive-prefixes option.
@@ -31,11 +42,11 @@ Sat Jun 24 23:16:33 2000  Christopher Faylor <cgf@cygnus.com>
 
 2000-06-07  Kazuhiro Fujieda <fujieda@jaist.ac.jp>
 
-        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  <dj@cygnus.com>
 
index 6118878..a7913e4 100644 (file)
@@ -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 <signal.h>
 #include <string.h>
 #include <time.h>
+#include <errno.h>
+#include <windows.h>
 
 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);
+}
index cca56ac..593629c 100644 (file)
@@ -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 <stdlib.h>
 #include <pwd.h>
 #include <sys/cygwin.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+
+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, "<defunct>");
+      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);