示例#1
0
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;
}
示例#3
0
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;
}