]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
ListProcessesInGuest Cleanup for ALL OS-es.
authorVMware, Inc <>
Thu, 27 Oct 2011 18:17:53 +0000 (11:17 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 27 Oct 2011 18:17:53 +0000 (11:17 -0700)
Cleaning up memory leaks in error conditions.
Re-structuring Process List to be an array of *new* Process Info
structures, one per process. Affects ALL OS-es.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/procMgr.h
open-vm-tools/lib/procMgr/procMgrPosix.c
open-vm-tools/lib/procMgr/procMgrSolaris.c
open-vm-tools/services/plugins/vix/vixTools.c

index 485e24332f5a284e8cfbec7b123f8981806cce9e..e6c2d675ed31e25348a7881f1040a8b8de4010a4 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "vm_basic_types.h"
 #include "auth.h"
+#include "dynarray.h"
 #if !defined(_WIN32)
 #  include <sys/types.h>
 #endif
@@ -46,19 +47,23 @@ typedef struct ProcMgr_AsyncProc ProcMgr_AsyncProc;
    typedef pid_t ProcMgr_Pid;
 #endif
 
-typedef struct ProcMgr_ProcList {
-   size_t         procCount;
-   size_t cmdCount;
-   size_t ownerCount;
+/*
+ * Process information structure.
+ * This holds basic information we return per process
+ * when listing process information inside the guest.
+ */
 
-   ProcMgr_Pid *procIdList;
-   char        **procCmdList;    // UTF-8
-   char        **procOwnerList;  // UTF-8
+typedef struct ProcMgrProcInfo {
+   ProcMgr_Pid procId;
+   char *procCmd;      // UTF-8
+   char *procOwner;    // UTF-8
 #if defined(_WIN32)
-   Bool        *procDebugged;
+   Bool procDebugged;
 #endif
-   time_t      *startTime;
-} ProcMgr_ProcList;
+   time_t procStartTime;
+} ProcMgrProcInfo;
+
+DEFINE_DYNARRAY_TYPE(ProcMgrProcInfo);
 
 
 typedef struct ProcMgr_ProcArgs {
@@ -127,8 +132,8 @@ typedef HANDLE Selectable;
 typedef int Selectable;
 #endif
 
-ProcMgr_ProcList *ProcMgr_ListProcesses(void);
-void ProcMgr_FreeProcList(ProcMgr_ProcList *procList);
+ProcMgrProcInfoArray *ProcMgr_ListProcesses(void);
+void ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList);
 Bool ProcMgr_KillByPid(ProcMgr_Pid procId);
 
 
index cab8cf789080df4681bbd3556225ad6bd960b69a..dd95227c7f8a1914369dc2b64dbb9659912d8faf 100644 (file)
@@ -78,6 +78,7 @@
 #undef offsetof
 #include "file.h"
 #include "dynbuf.h"
+#include "dynarray.h"
 #include "su.h"
 #include "str.h"
 #include "fileIO.h"
@@ -125,7 +126,6 @@ static Bool ProcMgrKill(pid_t pid,
 
 #if defined(__APPLE__)
 static int ProcMgrGetCommandLineArgs(long pid,
-                                     size_t cmdlineLen,
                                      DynBuf *argsBuf);
 #endif
 
@@ -257,33 +257,30 @@ done:
  *
  * Results:
  *      
- *      A ProcMgr_ProcList.
+ *      A ProcMgrProcInfoArray.
  *
  * Side effects:
  *
  *----------------------------------------------------------------------
  */
 
-#if !defined(sun) && !defined(__FreeBSD__) && !defined(__APPLE__)
-ProcMgr_ProcList *
+#if defined(linux)
+ProcMgrProcInfoArray *
 ProcMgr_ListProcesses(void)
 {
-   ProcMgr_ProcList *procList = NULL;
-   Bool failed = FALSE;
-   DynBuf dbProcId;
-   DynBuf dbProcCmd;
-   DynBuf dbProcStartTime;
-   DynBuf dbProcOwner;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo procInfo;
+   Bool failed = TRUE;
    DIR *dir;
    struct dirent *ent;
    static time_t hostStartTime = 0;
    static unsigned long long hertz = 100;
    int numberFound;
 
-   DynBuf_Init(&dbProcId);
-   DynBuf_Init(&dbProcCmd);
-   DynBuf_Init(&dbProcStartTime);
-   DynBuf_Init(&dbProcOwner);
+   procList = Util_SafeCalloc(1, sizeof *procList);
+   ProcMgrProcInfoArray_Init(procList, 0);
+   procInfo.procCmd = NULL;
+   procInfo.procOwner = NULL;
 
    /*
     * Figure out when the system started.  We need this number to
@@ -339,7 +336,6 @@ ProcMgr_ListProcesses(void)
    dir = opendir("/proc");
    if (NULL == dir) {
       Warning("ProcMgr_ListProcesses unable to open /proc\n");
-      failed = TRUE;
       goto abort;
    }
 
@@ -349,18 +345,14 @@ ProcMgr_ListProcesses(void)
       int statResult;
       int numRead = 0;   /* number of bytes that read() actually read */
       int cmdFd;
-      pid_t pid;
       int replaceLoop;
       struct passwd *pwd;
       char *cmdLineTemp = NULL;
       char *cmdStatTemp = NULL;
-      char *cmdLine;
-      char *userName = NULL;
       size_t strLen = 0;
       unsigned long long dummy;
       unsigned long long relativeStartTime;
       char *stringBegin;
-      time_t processStartTime;
 
       /*
        * We only care about dirs that look like processes.
@@ -530,82 +522,59 @@ ProcMgr_ListProcesses(void)
       if (20 != numberFound) {
          goto next_entry;
       }
-      processStartTime = hostStartTime + (relativeStartTime / hertz);
 
       /*
        * Store the command line string pointer in dynbuf.
        */
       if (cmdLineTemp) {
-         cmdLine = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
+         procInfo.procCmd = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
       } else {
-         cmdLine = Unicode_Alloc("", STRING_ENCODING_UTF8);
+         procInfo.procCmd = Unicode_Alloc("", STRING_ENCODING_UTF8);
       }
-      DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine);
 
       /*
        * Store the pid in dynbuf.
        */
-      pid = (pid_t) atoi(ent->d_name);
-      DynBuf_Append(&dbProcId, &pid, sizeof pid);
+      procInfo.procId = (pid_t) atoi(ent->d_name);
 
       /*
        * Store the owner of the process.
        */
       pwd = getpwuid(fileStat.st_uid);
-      userName = (NULL == pwd)
-                 ? Str_Asprintf(&strLen, "%d", (int) fileStat.st_uid)
-                 : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
-      DynBuf_Append(&dbProcOwner, &userName, sizeof userName);
+      procInfo.procOwner = (NULL == pwd)
+                           ? Str_SafeAsprintf(&strLen, "%d", (int) fileStat.st_uid)
+                           : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
 
       /*
        * Store the time that the process started.
        */
-      DynBuf_Append(&dbProcStartTime,
-                    &processStartTime,
-                    sizeof processStartTime);
+      procInfo.procStartTime = hostStartTime + (relativeStartTime / hertz);
+
+      /*
+       * Store the process info pointer into a list buffer.
+       */
+      if (!ProcMgrProcInfoArray_Push(procList, procInfo)) {
+         Warning("%s: failed to expand DynArray - out of memory\n",
+                 __FUNCTION__);
+         goto abort;
+      }
+      procInfo.procCmd = NULL;
+      procInfo.procOwner = NULL;
 
 next_entry:
       free(cmdLineTemp);
       free(cmdStatTemp);
    } // while readdir
 
-   closedir(dir);
-
-   if (0 == DynBuf_GetSize(&dbProcId)) {
-      failed = TRUE;
-      goto abort;
+   if (0 < ProcMgrProcInfoArray_Count(procList)) {
+      failed = FALSE;
    }
 
-   /*
-    * We're done adding to DynBuf.  Trim off any unused allocated space.
-    * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy().
-    */
-   DynBuf_Trim(&dbProcId);
-   DynBuf_Trim(&dbProcCmd);
-   DynBuf_Trim(&dbProcStartTime);
-   DynBuf_Trim(&dbProcOwner);
-   /*
-    * Create a ProcMgr_ProcList and populate its fields.
-    */
-   procList = (ProcMgr_ProcList *) calloc(1, sizeof(ProcMgr_ProcList));
-   ASSERT_NOT_IMPLEMENTED(procList);
-
-   procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t);
-
-   procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId);
-   ASSERT_NOT_IMPLEMENTED(procList->procIdList);
-   procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd);
-   ASSERT_NOT_IMPLEMENTED(procList->procCmdList);
-   procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime);
-   ASSERT_NOT_IMPLEMENTED(procList->startTime);
-   procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner);
-   ASSERT_NOT_IMPLEMENTED(procList->procOwnerList);
-
 abort:
-   DynBuf_Destroy(&dbProcId);
-   DynBuf_Destroy(&dbProcCmd);
-   DynBuf_Destroy(&dbProcStartTime);
-   DynBuf_Destroy(&dbProcOwner);
+   closedir(dir);
+
+   free(procInfo.procCmd);
+   free(procInfo.procOwner);
 
    if (failed) {
       ProcMgr_FreeProcList(procList);
@@ -614,7 +583,7 @@ abort:
 
    return procList;
 }
-#endif // !defined(sun) & !defined(__FreeBSD__) && !defined(__APPLE__)
+#endif // defined(linux)
 
 
 /*
@@ -628,7 +597,7 @@ abort:
  *
  * Results:
  *
- *      A ProcMgr_ProcList.
+ *      A ProcMgrProcInfoArray.
  *
  * Side effects:
  *
@@ -636,24 +605,22 @@ abort:
  */
 
 #if defined(__FreeBSD__)
-ProcMgr_ProcList *
+ProcMgrProcInfoArray *
 ProcMgr_ListProcesses(void)
 {
-   ProcMgr_ProcList *procList = NULL;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo procInfo;
    Bool failed = TRUE;
    static kvm_t *kd;
    struct kinfo_proc *kp;
    char errbuf[_POSIX2_LINE_MAX];
-   int i, nentries=-1, flag=0;
-   DynBuf dbProcId;
-   DynBuf dbProcCmd;
-   DynBuf dbProcStartTime;
-   DynBuf dbProcOwner;
+   int i;
+   int nentries=-1;
+   int flag=0;
 
-   DynBuf_Init(&dbProcId);
-   DynBuf_Init(&dbProcCmd);
-   DynBuf_Init(&dbProcStartTime);
-   DynBuf_Init(&dbProcOwner);
+   procList = Util_SafeCalloc(1, sizeof *procList);
+   procInfo.procCmd = NULL;
+   procInfo.procOwner = NULL;
 
    /*
     * Get the handle to the Kernel Virtual Memory
@@ -668,43 +635,40 @@ ProcMgr_ListProcesses(void)
     * Get the list of process info structs
     */
    kp = kvm_getprocs(kd, KERN_PROC_PROC, flag, &nentries);
-   if ((kp == NULL && nentries > 0) || (kp != NULL && nentries < 0)) {
+   if (kp == NULL || nentries <= 0) {
       Warning("%s: failed to get proc infos with error: %s\n",
               __FUNCTION__, kvm_geterr(kd));
       goto abort;
    }
 
+   /*
+    * Pre-allocate the dynamic array of required size.
+    */
+   if (!ProcMgrProcInfoArray_Init(procList, nentries)) {
+      Warning("%s: failed to create DynArray - out of memory\n",
+              __FUNCTION__);
+      goto abort;
+   }
+
    /*
     * Iterate through the list of process entries
     */
    for (i = 0; i < nentries; ++i, ++kp) {
       struct passwd *pwd;
-      char *userName = NULL;
-      char *cmdLine = NULL;
       char **cmdLineTemp = NULL;
-      time_t processStartTime;
 
       /*
        * Store the pid of the process
        */
-      if (!DynBuf_Append(&dbProcId, &(kp->ki_pid), sizeof(kp->ki_pid))) {
-         Warning("%s: failed to append pid in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
+      procInfo.procId = kp->ki_pid;
 
       /*
        * Store the owner of the process.
        */
       pwd = getpwuid(kp->ki_uid);
-      userName = (NULL == pwd)
-                 ? Str_SafeAsprintf(NULL, "%d", (int) kp->ki_uid)
-                 : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
-      if (!DynBuf_Append(&dbProcOwner, &userName, sizeof userName)) {
-         Warning("%s: failed to append username in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
+      procInfo.procOwner = (NULL == pwd)
+                           ? Str_SafeAsprintf(NULL, "%d", (int) kp->ki_uid)
+                           : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
 
       /*
        * Store the command line string of the process
@@ -738,75 +702,36 @@ ProcMgr_ListProcesses(void)
             goto abort;
          }
          DynBuf_Trim(&dbuf);
-         cmdLine = DynBuf_Detach(&dbuf);
+         procInfo.procCmd = DynBuf_Detach(&dbuf);
          DynBuf_Destroy(&dbuf);
       } else {
-         cmdLine = Unicode_Alloc(kp->ki_comm, STRING_ENCODING_DEFAULT);
-      }
-      if (!DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine)) {
-         Warning("%s: failed to append cmdline in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
+         procInfo.procCmd = Unicode_Alloc(kp->ki_comm, STRING_ENCODING_DEFAULT);
       }
 
       /*
        * Store the start time of the process
        */
-      processStartTime = kp->ki_start.tv_sec;
-      if (!DynBuf_Append(&dbProcStartTime,
-                    &processStartTime,
-                    sizeof processStartTime)) {
-         Warning("%s: failed to append start time in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
-
-   } // for nentries
-
-   if (0 == DynBuf_GetSize(&dbProcId)) {
-      goto abort;
-   }
-
-   /*
-    * We're done adding to DynBuf.  Trim off any unused allocated space.
-    * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy().
-    */
-   DynBuf_Trim(&dbProcId);
-   DynBuf_Trim(&dbProcCmd);
-   DynBuf_Trim(&dbProcStartTime);
-   DynBuf_Trim(&dbProcOwner);
+      procInfo.procStartTime = kp->ki_start.tv_sec;
 
-   /*
-    * Create a ProcMgr_ProcList and populate its fields.
-    */
-   procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof(ProcMgr_ProcList));
-   ASSERT_NOT_IMPLEMENTED(procList);
-
-   procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t);
+      /*
+       * Store the process info pointer into a list buffer.
+       */
+      *ProcMgrProcInfoArray_AddressOf(procList, i) = procInfo;
+      procInfo.procCmd = NULL;
+      procInfo.procOwner = NULL;
 
-   procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId);
-   ASSERT_NOT_IMPLEMENTED(procList->procIdList);
-   procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd);
-   ASSERT_NOT_IMPLEMENTED(procList->procCmdList);
-   procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime);
-   ASSERT_NOT_IMPLEMENTED(procList->startTime);
-   procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner);
-   ASSERT_NOT_IMPLEMENTED(procList->procOwnerList);
+   } // for nentries
 
    failed = FALSE;
-abort:
-   DynBuf_Destroy(&dbProcId);
-   DynBuf_Destroy(&dbProcCmd);
-   DynBuf_Destroy(&dbProcStartTime);
-   DynBuf_Destroy(&dbProcOwner);
 
+abort:
    if (kd != NULL) {
-      /*
-       * Wrap up: also deallocates memory (if) allocated by kvm_getargv()
-       */
       kvm_close(kd);
    }
 
+   free(procInfo.procCmd);
+   free(procInfo.procOwner);
+
    if (failed) {
       ProcMgr_FreeProcList(procList);
       procList = NULL;
@@ -837,7 +762,6 @@ abort:
 
 static int
 ProcMgrGetCommandLineArgs(long pid,               // IN:  process id
-                          size_t cmdlineLen,      // IN:  max command line length
                           DynBuf *argsBuf)        // OUT: Buffer with arguments
 {
    int argCount = 0;
@@ -846,17 +770,31 @@ ProcMgrGetCommandLineArgs(long pid,               // IN:  process id
    char *cmdLineRaw = NULL;
    char *cmdLineTemp;
    char *cmdLineEnd;
+   size_t maxargs = 0;
+   size_t maxargsSize;
+   int maxargsName[] = {CTL_KERN, KERN_ARGMAX};
    int argName[] = {CTL_KERN, KERN_PROCARGS2, pid};
 
+   /*
+    * Get the sysctl kern argmax.
+    */
+   maxargsSize = sizeof maxargs;
+   if (sysctl(maxargsName, ARRAYSIZE(maxargsName),
+              &maxargs, &maxargsSize, NULL, 0) < 0) {
+      Warning("%s: failed to get the kernel max args with errno = %d\n",
+               __FUNCTION__, errno);
+      goto abort;
+   }
+
    /*
     * Fetch the raw command line
     */
-   cmdLineRaw = (char *) Util_SafeCalloc(cmdlineLen, sizeof *cmdLineRaw);
-   if (sysctl(argName, ARRAYSIZE(argName), cmdLineRaw, &cmdlineLen, NULL, 0) < 0) {
+   cmdLineRaw = Util_SafeCalloc(maxargs, sizeof *cmdLineRaw);
+   if (sysctl(argName, ARRAYSIZE(argName), cmdLineRaw, &maxargs, NULL, 0) < 0) {
       Debug("%s: No command line args for pid = %ld\n", __FUNCTION__, pid);
       goto abort;
    }
-   cmdLineEnd = &cmdLineRaw[cmdlineLen];
+   cmdLineEnd = &cmdLineRaw[maxargs];
 
    /*
     * Format of the raw command line (without line breaks):
@@ -973,57 +911,30 @@ abort:
  *      UTF-8 encoded, although we do not enforce it right now.
  *
  * Results:
- *      A ProcMgr_ProcList.
+ *      A ProcMgrProcInfoArray.
  *
  * Side effects:
  *
  *----------------------------------------------------------------------
  */
 
-ProcMgr_ProcList *
+ProcMgrProcInfoArray *
 ProcMgr_ListProcesses(void)
 {
-   ProcMgr_ProcList *procList = NULL;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo procInfo;
    Bool failed = TRUE;
-   char *userName = NULL;
-   char *cmdLine = NULL;
    struct kinfo_proc *kptmp;
    struct kinfo_proc *kp = NULL;
-   size_t maxargs;
-   size_t maxargsSize;
    size_t procsize;
-   size_t procCount = 0;
-   size_t ownerCount = 0;
-   size_t cmdCount = 0;
    int i;
    int nentries;
-   DynBuf dbProcId;
-   DynBuf dbProcCmd;
-   DynBuf dbProcStartTime;
-   DynBuf dbProcOwner;
-
-   /*
-    * Different multi-level names used for sysctl calls.
-    */
-   int maxargsName[] = {CTL_KERN, KERN_ARGMAX};
    int procName[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
 
-   DynBuf_Init(&dbProcId);
-   DynBuf_Init(&dbProcCmd);
-   DynBuf_Init(&dbProcStartTime);
-   DynBuf_Init(&dbProcOwner);
+   procList = Util_SafeCalloc(1, sizeof *procList);
+   procInfo.procCmd = NULL;
+   procInfo.procOwner = NULL;
 
-   procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof *procList);
-   /*
-    * Get the sysctl kern argmax.
-    */
-   maxargsSize = sizeof maxargs;
-   if (sysctl(maxargsName, ARRAYSIZE(maxargsName),
-              &maxargs, &maxargsSize, NULL, 0) < 0) {
-      Warning("%s: failed to get the kernel max args with errno = %d\n",
-               __FUNCTION__, errno);
-      goto abort;
-   }
    /*
     * Get the number of process info structs in the entire list.
     */
@@ -1036,7 +947,7 @@ ProcMgr_ListProcesses(void)
    /*
     * Get the list of process info structs.
     */
-   kp = (struct kinfo_proc *) Util_SafeCalloc(nentries, sizeof *kp);
+   kp = Util_SafeCalloc(nentries, sizeof *kp);
    if (sysctl(procName, ARRAYSIZE(procName), kp, &procsize, NULL, 0) < 0) {
       Warning("%s: failed to get the process struct list (errno = %d)\n",
                __FUNCTION__, errno);
@@ -1045,13 +956,22 @@ ProcMgr_ListProcesses(void)
    /*
     * Recalculate the number of entries as they may have changed.
     */
-   nentries = (int)(procsize / sizeof *kp);
+   if (0 >= (nentries = (int)(procsize / sizeof *kp))) {
+      goto abort;
+   }
+   /*
+    * Pre-allocate the dynamic array of required size.
+    */
+   if (!ProcMgrProcInfoArray_Init(procList, nentries)) {
+      Warning("%s: failed to create DynArray - out of memory\n",
+              __FUNCTION__);
+      goto abort;
+   }
    /*
     * Iterate through the list of process entries
     */
    for (i = 0, kptmp = kp; i < nentries; ++i, ++kptmp) {
       DynBuf argsBuf;
-      time_t processStartTime;
       char buffer[BUFSIZ];
       struct passwd pw;
       struct passwd *ppw = &pw;
@@ -1060,95 +980,46 @@ ProcMgr_ListProcesses(void)
       /*
        * Store the pid of the process
        */
-      if (!DynBuf_Append(&dbProcId, &(kptmp->kp_proc.p_pid),
-                         sizeof kptmp->kp_proc.p_pid)) {
-         Warning("%s: failed to append pid in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
-      procCount++;
+      procInfo.procId = kptmp->kp_proc.p_pid;
       /*
        * Store the owner of the process.
        */
       error = Posix_Getpwuid_r(kptmp->kp_eproc.e_pcred.p_ruid,
                                &pw, buffer, sizeof buffer, &ppw);
-      userName = (0 != error || NULL == ppw)
-                 ? Str_SafeAsprintf(NULL, "%d",
-                                    (int) kptmp->kp_eproc.e_pcred.p_ruid)
-                 : Unicode_Alloc(ppw->pw_name, STRING_ENCODING_DEFAULT);
-      if (!DynBuf_Append(&dbProcOwner, &userName, sizeof userName)) {
-         Warning("%s: failed to append username in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
-      userName = NULL;
-      ownerCount++;
+      procInfo.procOwner = (0 != error || NULL == ppw)
+                           ? Str_SafeAsprintf(NULL, "%d", (int) kptmp->kp_eproc.e_pcred.p_ruid)
+                           : Unicode_Alloc(ppw->pw_name, STRING_ENCODING_DEFAULT);
+
       /*
-       * Get the command line arguments of the process.
+       * Store the command line arguments of the process.
        * If no arguments are found, use the full command name.
        */
       DynBuf_Init(&argsBuf);
-      if (ProcMgrGetCommandLineArgs(kptmp->kp_proc.p_pid, maxargs, &argsBuf) > 0) {
-         cmdLine = DynBuf_Detach(&argsBuf);
+      if (ProcMgrGetCommandLineArgs(kptmp->kp_proc.p_pid, &argsBuf) > 0) {
+         procInfo.procCmd = DynBuf_Detach(&argsBuf);
       } else {
-         cmdLine = Unicode_Alloc(kptmp->kp_proc.p_comm, STRING_ENCODING_DEFAULT);
+         procInfo.procCmd = Unicode_Alloc(kptmp->kp_proc.p_comm, STRING_ENCODING_DEFAULT);
       }
       DynBuf_Destroy(&argsBuf);
       /*
-       * Store the command line string of the process.
+       * Store the start time of the process
        */
-      if (!DynBuf_Append(&dbProcCmd, &cmdLine, sizeof cmdLine)) {
-         Warning("%s: failed to append cmdline in DynBuf - out of memory\n",
-                 __FUNCTION__);
-         goto abort;
-      }
-      cmdLine = NULL;
-      cmdCount++;
+      procInfo.procStartTime = kptmp->kp_proc.p_starttime.tv_sec;
       /*
-       * Store the start time of the process
+       * Store the process info pointer into a list buffer.
        */
-      processStartTime = kptmp->kp_proc.p_starttime.tv_sec;
-      if (!DynBuf_Append(&dbProcStartTime, &processStartTime,
-                         sizeof processStartTime)) {
-         Warning("%s: failed to append start time in DynBuf - out of memory\n",
-                  __FUNCTION__);
-         goto abort;
-      }
-   }
-
-   if (0 < procCount) {
-      failed = FALSE;
-   }
+      *ProcMgrProcInfoArray_AddressOf(procList, i) = procInfo;
+      procInfo.procCmd = NULL;
+      procInfo.procOwner = NULL;
 
-abort:
-   /*
-    * We're done adding to DynBuf.  Trim off any unused allocated space.
-    * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy().
-    */
-   DynBuf_Trim(&dbProcId);
-   DynBuf_Trim(&dbProcCmd);
-   DynBuf_Trim(&dbProcStartTime);
-   DynBuf_Trim(&dbProcOwner);
+   } // nentries
 
-   /*
-    * Populate fields of ProcMgr_ProcList
-    */
-   procList->procCount = procCount;
-   procList->ownerCount = ownerCount;
-   procList->cmdCount = cmdCount;
-   procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId);
-   procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd);
-   procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime);
-   procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner);
-
-   DynBuf_Destroy(&dbProcId);
-   DynBuf_Destroy(&dbProcCmd);
-   DynBuf_Destroy(&dbProcStartTime);
-   DynBuf_Destroy(&dbProcOwner);
+   failed = FALSE;
 
+abort:
    free(kp);
-   free(userName);
-   free(cmdLine);
+   free(procInfo.procCmd);
+   free(procInfo.procOwner);
 
    if (failed) {
       ProcMgr_FreeProcList(procList);
@@ -1164,7 +1035,7 @@ abort:
  *
  * ProcMgr_FreeProcList --
  *
- *      Free the memory occupied by ProcMgr_ProcList.
+ *      Free the memory occupied by ProcMgrProcInfoArray.
  *
  * Results:
  *      
@@ -1176,37 +1047,25 @@ abort:
  */
 
 void
-ProcMgr_FreeProcList(ProcMgr_ProcList *procList)
+ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList)
 {
    int i;
+   size_t procCount;
 
    if (NULL == procList) {
       return;
    }
 
-#if defined(__APPLE__)
-   /*
-    * We need to do the following for other OSes as well.
-    * Each list shall have its own counter to address
-    * error conditions while building the list.
-    */
-   for (i = 0; i < procList->cmdCount; i++) {
-      free(procList->procCmdList[i]);
-   }
-   for (i = 0; i < procList->ownerCount; i++) {
-      free(procList->procOwnerList[i]);
-   }
-#else
-   for (i = 0; i < procList->procCount; i++) {
-      free(procList->procCmdList[i]);
-      free(procList->procOwnerList[i]);
+   procCount = ProcMgrProcInfoArray_Count(procList);
+   for (i = 0; i < procCount; i++) {
+      ProcMgrProcInfo *procInfo;
+
+      procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
+      free(procInfo->procCmd);
+      free(procInfo->procOwner);
    }
-#endif
 
-   free(procList->procIdList);
-   free(procList->procCmdList);
-   free(procList->startTime);
-   free(procList->procOwnerList);
+   ProcMgrProcInfoArray_Destroy(procList);
    free(procList);
 }
 
index 478b704e8cd69bc75e7f7d34f2bf215d957cd58f..a5c4142d9f698f7f8be95e5b1c4df6fff32d17e5 100644 (file)
@@ -85,38 +85,29 @@ ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo);
  *----------------------------------------------------------------------------
  */
 
-ProcMgr_ProcList *
+ProcMgrProcInfoArray *
 ProcMgr_ListProcesses(void)
 {
-   ProcMgr_ProcList *procList = NULL;
-
-   Bool failed = FALSE;
-   DynBuf dbProcId;
-   DynBuf dbProcCmd;
-   DynBuf dbProcStartTime;
-   DynBuf dbProcOwner;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo processInfo;
+   Bool failed = TRUE;
    DIR *dir;
    struct dirent *ent;
 
-   DynBuf_Init(&dbProcId);
-   DynBuf_Init(&dbProcCmd);
-   DynBuf_Init(&dbProcStartTime);
-   DynBuf_Init(&dbProcOwner);
+   procList = Util_SafeCalloc(1, sizeof *procList);
+   ProcMgrProcInfoArray_Init(procList, 0);
+   processInfo.procOwner = NULL;
+   processInfo.procCmd = NULL;
 
    dir = opendir("/proc");
    if (NULL == dir) {
       Warning("ProcMgr_ListProcesses unable to open /proc\n");
-      failed = TRUE;
       goto exit;
    }
 
    while (TRUE) {
-      pid_t pid;
       struct passwd *pwd;
-      char *cmdLineTemp;
-      char *userName = NULL;
       char tempPath[MAXPATHLEN];
-      time_t processStartTime;
       psinfo_t procInfo;
       size_t strLen = 0;
       size_t numRead = 0;
@@ -131,7 +122,6 @@ ProcMgr_ListProcesses(void)
          if (errno == 0) {
             break;
          } else {
-            failed = TRUE;
             goto exit;
          }
       }
@@ -152,7 +142,6 @@ ProcMgr_ListProcesses(void)
              (res == FILEIO_NO_PERMISSION)) {
             continue;
          } else {
-            failed = TRUE;
             goto exit;
          }
       }
@@ -160,11 +149,10 @@ ProcMgr_ListProcesses(void)
       res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead);
       FileIO_Close(&psInfoFd);
       if (res != FILEIO_SUCCESS) {
-         failed = TRUE;
          goto exit;
       }
 
-      processStartTime = procInfo.pr_start.tv_sec;
+      processInfo.procStartTime = procInfo.pr_start.tv_sec;
 
       /*
        * Command line strings in procInfo.pr_psargs are truncated to PRARGZ
@@ -178,83 +166,51 @@ ProcMgr_ListProcesses(void)
 
          tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo);
          if (tmp != NULL) {
-            cmdLineTemp = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT);
+            processInfo.procCmd = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT);
             free(tmp);
          } else {
-            cmdLineTemp = Unicode_Alloc(procInfo.pr_psargs,
-                                        STRING_ENCODING_DEFAULT);
+            processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs,
+                                                STRING_ENCODING_DEFAULT);
          }
       } else {
-         cmdLineTemp = Unicode_Alloc(procInfo.pr_psargs,
-                                     STRING_ENCODING_DEFAULT);
+         processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs,
+                                             STRING_ENCODING_DEFAULT);
       }
 
-      /*
-       * Store the command line string pointer in dynbuf.
-       */
-      DynBuf_Append(&dbProcCmd, &cmdLineTemp, sizeof cmdLineTemp);
-
       /*
        * Store the pid in dynbuf.
        */
-      pid = procInfo.pr_pid;
-      DynBuf_Append(&dbProcId, &pid, sizeof pid);
+      processInfo.procId = procInfo.pr_pid;
 
       /*
        * Store the owner of the process.
        */
       pwd = getpwuid(procInfo.pr_uid);
-      userName = (NULL == pwd)
-                 ? Str_Asprintf(&strLen, "%d", (int) procInfo.pr_uid)
-                 : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
-      DynBuf_Append(&dbProcOwner, &userName, sizeof userName);
+      processInfo.procOwner = (NULL == pwd)
+                              ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid)
+                              : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT);
 
       /*
-       * Store the time that the process started.
+       * Store the process info into a list buffer.
        */
-      DynBuf_Append(&dbProcStartTime,
-                    &processStartTime,
-                    sizeof processStartTime);
+      if (!ProcMgrProcInfoArray_Push(procList, processInfo)) {
+         Warning("%s: failed to expand DynArray - out of memory\n",
+                 __FUNCTION__);
+         goto exit;
+      }
+      processInfo.procCmd = NULL;
+      processInfo.procOwner = NULL;
    } // while (TRUE)
 
-   closedir(dir);
-
-   if (0 == DynBuf_GetSize(&dbProcId)) {
-      failed = TRUE;
-      goto exit;
+   if (0 < ProcMgrProcInfoArray_Count(procList)) {
+      failed = FALSE;
    }
 
-   /*
-    * We're done adding to DynBuf.  Trim off any unused allocated space.
-    * DynBuf_Trim() followed by DynBuf_Detach() avoids a memcpy().
-    */
-   DynBuf_Trim(&dbProcId);
-   DynBuf_Trim(&dbProcCmd);
-   DynBuf_Trim(&dbProcStartTime);
-   DynBuf_Trim(&dbProcOwner);
-
-   /*
-    * Create a ProcMgr_ProcList and populate its fields.
-    */
-   procList = (ProcMgr_ProcList *) Util_SafeCalloc(1, sizeof(ProcMgr_ProcList));
-   ASSERT_MEM_ALLOC(procList);
-
-   procList->procCount = DynBuf_GetSize(&dbProcId) / sizeof(pid_t);
-
-   procList->procIdList = (pid_t *) DynBuf_Detach(&dbProcId);
-   ASSERT_MEM_ALLOC(procList->procIdList);
-   procList->procCmdList = (char **) DynBuf_Detach(&dbProcCmd);
-   ASSERT_MEM_ALLOC(procList->procCmdList);
-   procList->startTime = (time_t *) DynBuf_Detach(&dbProcStartTime);
-   ASSERT_MEM_ALLOC(procList->startTime);
-   procList->procOwnerList = (char **) DynBuf_Detach(&dbProcOwner);
-   ASSERT_MEM_ALLOC(procList->procOwnerList);
-
 exit:
-   DynBuf_Destroy(&dbProcId);
-   DynBuf_Destroy(&dbProcCmd);
-   DynBuf_Destroy(&dbProcStartTime);
-   DynBuf_Destroy(&dbProcOwner);
+   closedir(dir);
+
+   free(processInfo.procOwner);
+   free(processInfo.procCmd);
 
    if (failed) {
       ProcMgr_FreeProcList(procList);
index be7e2ff0334c1888fd8b2fbf08292e4bde7208f1..c39aba7576efdc26f619d2af307942eeb2e64193 100644 (file)
@@ -69,6 +69,7 @@
 #include "timeutil.h"
 #include "vm_version.h"
 #include "message.h"
+#include "dynarray.h"
 
 #define G_LOG_DOMAIN  "vix"
 #define Debug         g_debug
@@ -4319,7 +4320,8 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN
    VixError err = VIX_OK;
    int i;
    static char resultBuffer[GUESTMSG_MAX_IN_SIZE];
-   ProcMgr_ProcList *procList = NULL;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo *procInfo;
    char *destPtr;
    char *endDestPtr;
    char *procBufPtr = NULL;
@@ -4329,6 +4331,7 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN
    Bool escapeStrs;
    char *escapedName = NULL;
    char *escapedUser = NULL;
+   size_t procCount;
 
    ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE);
 
@@ -4357,32 +4360,34 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN
                              VIX_XML_ESCAPED_TAG);
    }
 
-   for (i = 0; i < procList->procCount; i++) {
+   procCount = ProcMgrProcInfoArray_Count(procList);
+   for (i = 0; i < procCount; i++) {
       const char *name;
       const char *user;
 
+      procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
+
       if (escapeStrs) {
          name = escapedName =
-            VixToolsEscapeXMLString(procList->procCmdList[i]);
+            VixToolsEscapeXMLString(procInfo->procCmd);
          if (NULL == escapedName) {
             err = VIX_E_OUT_OF_MEMORY;
             goto abort;
          }
       } else {
-         name = procList->procCmdList[i];
+         name = procInfo->procCmd;
       }
 
-      if ((NULL != procList->procOwnerList) &&
-          (NULL != procList->procOwnerList[i])) {
+      if (NULL != procInfo->procOwner) {
          if (escapeStrs) {
             user = escapedUser =
-               VixToolsEscapeXMLString(procList->procOwnerList[i]);
+               VixToolsEscapeXMLString(procInfo->procOwner);
             if (NULL == escapedUser) {
                err = VIX_E_OUT_OF_MEMORY;
                goto abort;
             }
          } else {
-            user = procList->procOwnerList[i];
+            user = procInfo->procOwner;
          }
       } else {
          user = "";
@@ -4395,14 +4400,12 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN
 #endif
                              "<user>%s</user><start>%d</start></proc>",
                              name,
-                             (int) procList->procIdList[i],
+                             (int) procInfo->procId,
 #if defined(_WIN32)
-                             (int) procList->procDebugged[i],
+                             (int) procInfo->procDebugged,
 #endif
                              user,
-                             (NULL == procList->startTime)
-                                 ? 0
-                                 : (int) procList->startTime[i]);
+                             (int) procInfo->procStartTime);
       if (NULL == procBufPtr) {
          err = VIX_E_OUT_OF_MEMORY;
          goto abort;
@@ -4521,12 +4524,14 @@ VixToolsListProcessesExGenerateData(uint32 numPids,          // IN
                                     char **resultBuffer)     // OUT
 {
    VixError err = VIX_OK;
-   ProcMgr_ProcList *procList = NULL;
+   ProcMgrProcInfoArray *procList = NULL;
+   ProcMgrProcInfo *procInfo;
    DynBuf dynBuffer;
    VixToolsExitedProgramState *epList;
    int i;
    int j;
    Bool bRet;
+   size_t procCount;
 
    DynBuf_Init(&dynBuffer);
 
@@ -4591,22 +4596,22 @@ VixToolsListProcessesExGenerateData(uint32 numPids,          // IN
     * the Vix side with GetNthProperty, and can have a mix of live and
     * dead processes.
     */
+   procCount = ProcMgrProcInfoArray_Count(procList);
    if (numPids > 0) {
       for (i = 0; i < numPids; i++) {
          // ignore it if its on the exited list -- we added it above
          if (VixToolsFindExitedProgramState(pids[i])) {
             continue;
          }
-         for (j = 0; j < procList->procCount; j++) {
-            if (pids[i] == procList->procIdList[j]) {
+         for (j = 0; j < procCount; j++) {
+            procInfo = ProcMgrProcInfoArray_AddressOf(procList, j);
+            if (pids[i] == procInfo->procId) {
                err = VixToolsPrintProcInfoEx(&dynBuffer,
-                                             procList->procCmdList[j],
-                                             procList->procIdList[j],
-                                             (NULL == procList->procOwnerList
-                                              || NULL == procList->procOwnerList[j])
-                                             ? "" : procList->procOwnerList[j],
-                                             (NULL == procList->startTime)
-                                             ? 0 : (int) procList->startTime[j],
+                                             procInfo->procCmd,
+                                             procInfo->procId,
+                                             (NULL == procInfo->procOwner)
+                                             ? "" : procInfo->procOwner,
+                                             (int) procInfo->procStartTime,
                                              0, 0);
                if (VIX_OK != err) {
                   goto abort;
@@ -4615,19 +4620,18 @@ VixToolsListProcessesExGenerateData(uint32 numPids,          // IN
          }
       }
    } else {
-      for (i = 0; i < procList->procCount; i++) {
+      for (i = 0; i < procCount; i++) {
+         procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
          // ignore it if its on the exited list -- we added it above
-         if (VixToolsFindExitedProgramState(procList->procIdList[i])) {
+         if (VixToolsFindExitedProgramState(procInfo->procId)) {
             continue;
          }
          err = VixToolsPrintProcInfoEx(&dynBuffer,
-                                       procList->procCmdList[i],
-                                       procList->procIdList[i],
-                                       (NULL == procList->procOwnerList
-                                        || NULL == procList->procOwnerList[i])
-                                       ? "" : procList->procOwnerList[i],
-                                       (NULL == procList->startTime)
-                                       ? 0 : (int) procList->startTime[i],
+                                       procInfo->procCmd,
+                                       procInfo->procId,
+                                       (NULL == procInfo->procOwner)
+                                       ? "" : procInfo->procOwner,
+                                       (int) procInfo->procStartTime,
                                        0, 0);
          if (VIX_OK != err) {
             goto abort;