This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

1.3.3-2: ps.exe bug for processes with a zero ppid


Hello,

There is a follow up to the bug "1.3.3-2: Process
creation is possible with ppid = 0 and pgid = 0"
<http://cygwin.com/ml/cygwin/2001-10/msg00109.html>.

'ps.exe' does not behave correctly with such
processes. This is due to the fact that in the code,
there is a criteria to see if a process is a Cygwin
one or a Windows one. And that criteria is precisely
(p-ppid != 0) !.

I have written a patch for 'ps.exe'. It is more a hack
than a real bug correction, but it works. In fact the
real bug correction must be done somewhere in the
process creation routines inside 'cygwin1.dll'. This
patch is to be found in attachment.

For those who should like to install this correction,
here is how to do it. In attachment is the corrected
version of 'ps.cc'. Do compile it using the following
command :
        gcc -O2 -s ps.cc -o ps.exe
And then install it :
        cp -p ps.exe /bin

Best Regards,


=====
Robert Legros
south Brussels, Belgium
robert_legros@yahoo.com

__________________________________________________
Do You Yahoo!?
Listen to your Yahoo! Mail messages from any phone.
http://phone.yahoo.com
diff -upr cygwin-1.3.3-2/winsup/utils/ps.cc cygwin-1.3.3-2.new/winsup/utils/ps.cc
--- cygwin-1.3.3-2/winsup/utils/ps.cc	Tue May  8 05:55:40 2001
+++ cygwin-1.3.3-2.new/winsup/utils/ps.cc	Wed Oct  3 14:11:24 2001
@@ -271,7 +271,7 @@ main (int argc, char *argv[])
       char pname[MAX_PATH];
       if (p->process_state & (PID_ZOMBIE | PID_EXITED))
         strcpy (pname, "<defunct>");
-      else if (p->ppid)
+      else if (p->ctty != -1) /* THIS IS HACK ! REALLY ! */
 	{
 	  char *s;
 	  pname[0] = '\0';
2001-10-03  Robert Legros <robert_legros@yahoo.com>

	* ps.cc (main): Change criteria to recognize a Cygwin process
	from (p->ppid) to (p->ctty != -1). This is a hack since the
	real bug (ppid is allowed to be zero) is inside 'cygwin1.dll'.

/* 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->ctty != -1) /* THIS IS HACK ! REALLY ! */
	{
	  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;
}


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]