ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; 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"); goto exit; } while (TRUE) { struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * Command line strings in procInfo.pr_psargs are truncated to PRARGZ * bytes. In this case we extract the arguments from the /proc/<pid>/as * file. Since most command line strings are expected to fit within * PRARGSZ bytes, we avoid calling * ExtractCommandLineFromAddressSpaceFile for every process. */ if (strlen(procInfo.pr_psargs) + 1 == PRARGSZ) { char *tmp; tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo); if (tmp != NULL) { processInfo.procCmd = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); free(tmp); } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } /* * Store the pid in dynbuf. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ 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) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmd); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }
ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; procList = Util_SafeCalloc(1, sizeof *procList); ProcMgrProcInfoArray_Init(procList, 0); processInfo.procOwner = NULL; processInfo.procCmdLine = NULL; processInfo.procCmdName = NULL; dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); goto exit; } while (TRUE) { char *tmp; char *cmdNameBegin = NULL; char *cmdNameEnd = NULL; struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; Bool cmdNameLookup = TRUE; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * If the command name in the ps info struct is strictly less than the * maximum allowed size, then we can save it right now. Else we shall * need to try and parse it from the entire command line, to avoid * saving a truncated command name. */ if (strlen(procInfo.pr_fname) + 1 < sizeof procInfo.pr_fname) { processInfo.procCmdName = Unicode_Alloc(procInfo.pr_fname, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } /* * The logic below is this: * 1. If we are looking for the explicit command name, we need to * extract the arguments from the /proc/<pid>/as file and save argv[0]. * 2. If we are not looking for the explicit command name, but the command * line in the ps info struct is not strictly less than the maximum * allowed size, we still need to extract the arguments from the * /proc/<pid>/as file, to avoid saving truncated comand line. * 3. Else we can save the command line directly from the ps info struct. */ if (cmdNameLookup) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, &processInfo.procCmdName); } else if (strlen(procInfo.pr_psargs) + 1 >= sizeof procInfo.pr_psargs) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, NULL); } else { tmp = NULL; } if (tmp != NULL) { processInfo.procCmdLine = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } else { /* * We had some issues reading procfs, mostly due to lack of * permissions for certain system owned precesses. So let's resort to * what the procinfo structure provides as a last resort. */ processInfo.procCmdLine = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); if (cmdNameLookup) { /* * Now let's try and get the best effort command name from the entire * command line. The method below does not take care of spaces in folder * names and executable file names. This is the best we can do at this * point, considering that spaces are not common in either file or * folder names in Solaris, specially when owned by the system. */ char *tmp2 = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); cmdNameBegin = tmp2; /* * Assuming the command name to end at the first blank space. */ cmdNameEnd = cmdNameBegin; while ('\0' != *cmdNameEnd) { if ('/' == *cmdNameEnd) { cmdNameBegin = cmdNameEnd + 1; } if (' ' == *cmdNameEnd) { break; } cmdNameEnd++; } *cmdNameEnd = '\0'; processInfo.procCmdName = Str_SafeAsprintf(NULL, "%s", cmdNameBegin); free(tmp2); } } free(tmp); tmp = NULL; /* * Store the pid. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ if (!ProcMgrProcInfoArray_Push(procList, processInfo)) { Warning("%s: failed to expand DynArray - out of memory\n", __FUNCTION__); goto exit; } processInfo.procCmdName = NULL; processInfo.procCmdLine = NULL; processInfo.procOwner = NULL; } // while (TRUE) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmdLine); free(processInfo.procCmdName); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }