326 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* ps.cc
 | 
						|
 | 
						|
   Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
 | 
						|
 | 
						|
This file is part of Cygwin.
 | 
						|
 | 
						|
This software is a copyrighted work licensed under the terms of the
 | 
						|
Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 | 
						|
details. */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <windows.h>
 | 
						|
#include <time.h>
 | 
						|
#include <getopt.h>
 | 
						|
#include <unistd.h>
 | 
						|
#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)
 | 
						|
{
 | 
						|
  time_t st = child->start_time;
 | 
						|
  time_t t = time (NULL);
 | 
						|
  static char stime[40] = {'\0'};
 | 
						|
  char now[40];
 | 
						|
 | 
						|
  strncpy (stime, ctime (&st) + 4, 15);
 | 
						|
  strcpy (now, ctime (&t) + 4);
 | 
						|
 | 
						|
  if ((t - st) < (24 * 3600))
 | 
						|
    return (stime + 7);
 | 
						|
 | 
						|
  stime[6] = '\0';
 | 
						|
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
static const char *
 | 
						|
ttynam (int ntty)
 | 
						|
{
 | 
						|
  static char buf[5];
 | 
						|
  if (ntty < 0)
 | 
						|
    return "   ?";
 | 
						|
  if (ntty == TTY_CONSOLE)
 | 
						|
    return " con";
 | 
						|
  sprintf (buf, "%4d", ntty);
 | 
						|
  return buf;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
main (int argc, char *argv[])
 | 
						|
{
 | 
						|
  external_pinfo *p;
 | 
						|
  int aflag, lflag, fflag, sflag, uid;
 | 
						|
  cygwin_getinfo_types query = CW_GETPINFO;
 | 
						|
  const char *dtitle = "    PID TTY     STIME COMMAND\n";
 | 
						|
  const char *dfmt   = "%7d%4s%10s %s\n";
 | 
						|
  const char *ftitle = "     UID     PID    PPID TTY     STIME COMMAND\n";
 | 
						|
  const char *ffmt   = "%8.8s%8d%8d%4s%10s %s\n";
 | 
						|
  const char *ltitle = "      PID    PPID    PGID     WINPID  TTY  UID    STIME COMMAND\n";
 | 
						|
  const char *lfmt   = "%c %7d %7d %7d %10u %4s %4d %8s %s\n";
 | 
						|
  char ch;
 | 
						|
 | 
						|
  aflag = lflag = fflag = sflag = 0;
 | 
						|
  uid = getuid ();
 | 
						|
  lflag = 1;
 | 
						|
 | 
						|
  while ((ch = getopt (argc, argv, "aelfsu:W")) != -1)
 | 
						|
    switch (ch)
 | 
						|
      {
 | 
						|
      case 'a':
 | 
						|
      case 'e':
 | 
						|
        aflag = 1;
 | 
						|
        break;
 | 
						|
      case 'f':
 | 
						|
        fflag = 1;
 | 
						|
        break;
 | 
						|
      case 'l':
 | 
						|
        lflag = 1;
 | 
						|
        break;
 | 
						|
      case 's':
 | 
						|
	sflag = 1;
 | 
						|
	break;
 | 
						|
      case 'u':
 | 
						|
        uid = atoi (optarg);
 | 
						|
        if (uid == 0)
 | 
						|
          {
 | 
						|
            struct passwd *pw;
 | 
						|
 | 
						|
            if ((pw = getpwnam (optarg)))
 | 
						|
              uid = pw->pw_uid;
 | 
						|
            else
 | 
						|
              {
 | 
						|
                fprintf (stderr, "user %s unknown\n", optarg);
 | 
						|
                exit (1);
 | 
						|
              }
 | 
						|
          }
 | 
						|
        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 (sflag)
 | 
						|
    printf (dtitle);
 | 
						|
  else if (fflag)
 | 
						|
    printf (ftitle);
 | 
						|
  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 (query, pid | CW_NEXTPID));
 | 
						|
       pid = p->pid)
 | 
						|
    {
 | 
						|
      if (!aflag && p->uid != uid)
 | 
						|
        continue;
 | 
						|
      char status = ' ';
 | 
						|
      if (p->process_state & PID_STOPPED)
 | 
						|
        status = 'S';
 | 
						|
      else if (p->process_state & PID_TTYIN)
 | 
						|
        status = 'I';
 | 
						|
      else if (p->process_state & PID_TTYOU)
 | 
						|
        status = 'O';
 | 
						|
 | 
						|
      char pname[MAX_PATH];
 | 
						|
      if (p->process_state & (PID_ZOMBIE | PID_EXITED))
 | 
						|
        strcpy (pname, "<defunct>");
 | 
						|
      else if (p->ppid)
 | 
						|
	{
 | 
						|
	  char *s;
 | 
						|
	  pname[0] = '\0';
 | 
						|
	  cygwin_conv_to_posix_path (p->progname, pname);
 | 
						|
	  s = strchr (pname, '\0') - 4;
 | 
						|
	  if (s > pname && strcasecmp (s, ".exe") == 0)
 | 
						|
	    *s = '\0';
 | 
						|
	}
 | 
						|
      else if (query == CW_GETPINFO_FULL)
 | 
						|
	{
 | 
						|
	  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];
 | 
						|
 | 
						|
      if (fflag)
 | 
						|
        {
 | 
						|
          struct passwd *pw;
 | 
						|
 | 
						|
          if ((pw = getpwuid (p->uid)))
 | 
						|
            strcpy (uname, pw->pw_name);
 | 
						|
          else
 | 
						|
            sprintf (uname, "%d", p->uid);
 | 
						|
        }
 | 
						|
 | 
						|
      if (sflag)
 | 
						|
        printf (dfmt, p->pid, ttynam (p->ctty), start_time (p), pname);
 | 
						|
      else if (fflag)
 | 
						|
        printf (ffmt, uname, p->pid, p->ppid, ttynam (p->ctty), start_time (p), pname);
 | 
						|
      else if (lflag)
 | 
						|
        printf (lfmt, status, p->pid, p->ppid, p->pgid,
 | 
						|
                p->dwProcessId, ttynam (p->ctty), p->uid, start_time (p), pname);
 | 
						|
 | 
						|
    }
 | 
						|
  (void) cygwin_internal (CW_UNLOCK_PINFO);
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 |