static Bool ResolutionCanSet(void) { ResolutionInfoX11Type *resInfoX = &resolutionInfoX11; FileIODescriptor fd; FileIOResult res; int64 filePos = 0; Bool keepSearching = TRUE; Bool found = FALSE; char buf[sizeof VERSION_STRING + 10]; // size of VERSION_STRING plus some extra for the version number const char versionString[] = VERSION_STRING; size_t bytesRead; int32 major, minor, level; unsigned int tokPos; /* See if the randr X module is loaded */ if (!XRRQueryVersion(resInfoX->display, &major, &minor) ) { return FALSE; } #ifndef NO_MULTIMON /* * See if RandR >= 1.2 can be used: The extension version is high enough and * all output names match the expected format. */ if (major > 1 || (major == 1 && minor >= 2)) { XRRScreenResources* xrrRes; XRROutputInfo* xrrOutput; unsigned int num; int i; xrrRes = XRRGetScreenResources(resInfoX->display, resInfoX->rootWindow); if (xrrRes) { for (i = 0; i < xrrRes->noutput; i++) { xrrOutput = XRRGetOutputInfo(resInfoX->display, xrrRes, xrrRes->outputs[i]); if (!xrrOutput) { break; } if (sscanf(xrrOutput->name, RR12_OUTPUT_FORMAT, &num) != 1 || num < 1) { XRRFreeOutputInfo(xrrOutput); break; } XRRFreeOutputInfo(xrrOutput); } if (i == xrrRes->noutput) { resInfoX->canUseRandR12 = TRUE; } else { g_debug("RandR >= 1.2 not usable\n"); } XRRFreeScreenResources(xrrRes); } if (resInfoX->canUseRandR12) { return TRUE; } } #endif // ifndef NO_MULTIMON /* * See if the VMWARE_CTRL extension is supported. */ if (resInfoX->canUseVMwareCtrl) { return TRUE; } /* * XXX: This check does not work with XOrg 6.9/7.0 for two reasons: Both * versions now use .so for the driver extension and 7.0 moves the drivers * to a completely different directory. As long as we ship a driver for * 6.9/7.0, we can instead just use the VMWARE_CTRL check. */ buf[sizeof buf - 1] = '\0'; FileIO_Invalidate(&fd); res = FileIO_Open(&fd, VMWAREDRV_PATH_64, FILEIO_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { res = FileIO_Open(&fd, VMWAREDRV_PATH, FILEIO_ACCESS_READ, FILEIO_OPEN); } if (res == FILEIO_SUCCESS) { /* * One of the opens succeeded, so start searching thru the file. */ while (keepSearching) { res = FileIO_Read(&fd, buf, sizeof buf - 1, &bytesRead); if (res != FILEIO_SUCCESS || bytesRead < sizeof buf -1 ) { keepSearching = FALSE; } else { if (Str_Strncmp(versionString, buf, sizeof versionString - 1) == 0) { keepSearching = FALSE; found = TRUE; } } filePos = FileIO_Seek(&fd, filePos+1, FILEIO_SEEK_BEGIN); if (filePos == -1) { keepSearching = FALSE; } } FileIO_Close(&fd); if (found) { /* * We NUL-terminated buf earlier, but Coverity really wants it to * be NUL-terminated after the call to FileIO_Read (because * FileIO_Read doesn't NUL-terminate). So we'll do it again. */ buf[sizeof buf - 1] = '\0'; /* * Try and parse the major, minor and level versions */ tokPos = sizeof versionString - 1; if (!StrUtil_GetNextIntToken(&major, &tokPos, buf, ".- ")) { return FALSE; } if (!StrUtil_GetNextIntToken(&minor, &tokPos, buf, ".- ")) { return FALSE; } if (!StrUtil_GetNextIntToken(&level, &tokPos, buf, ".- ")) { return FALSE; } return ((major > 10) || (major == 10 && minor >= 11)); } } return FALSE; }
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; }