summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndrew Christian <andrew.christian@nokia.com>2012-02-09 09:02:25 -0500
committerChris Craig <ext-chris.craig@nokia.com>2012-02-10 04:06:15 +0100
commitacd5d8d6ff45c002d97af70d1b9ee6aaf6edb898 (patch)
tree81b79783e480ec368f67d15869ff2c25b3bd3717 /src
parentd33cd2c25f6062d51eba713126bbe881021f693b (diff)
Added ExecutingProcessInfo object for data display of executing processes
Change-Id: I127d41d7e5015073f96ef8d780efa50369e05e56 Reviewed-by: Chris Craig <ext-chris.craig@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/core/procutils.cpp196
-rw-r--r--src/core/procutils.h48
2 files changed, 244 insertions, 0 deletions
diff --git a/src/core/procutils.cpp b/src/core/procutils.cpp
index 0d3f0ea..405828d 100644
--- a/src/core/procutils.cpp
+++ b/src/core/procutils.cpp
@@ -50,12 +50,207 @@
#include <QDebug>
+#if defined(Q_OS_MAC)
+#include <sys/sysctl.h>
+#include <errno.h>
+#endif
+
QT_BEGIN_NAMESPACE_PROCESSMANAGER
+struct ProcessPrivateData {
+ pid_t pid, ppid, pgrp, sid;
+ uid_t uid, euid, suid;
+ gid_t gid, egid, sgid;
+ int priority, nice;
+};
+
+/*!
+ Construct a ExecutingProcessInfo object from \a pid.
+ */
+
+ExecutingProcessInfo::ExecutingProcessInfo(pid_t pid)
+ : m_data(0)
+{
+#if defined(Q_OS_LINUX)
+ QFile file(QString::fromLatin1("/proc/%1/stat").arg(pid));
+ if (!file.open(QIODevice::ReadOnly))
+ return;
+
+ m_data = new ProcessPrivateData;
+ memset(m_data, 0, sizeof(ProcessPrivateData));
+ QList<QByteArray> contents = file.readAll().split(' ');
+ file.close();
+ /*
+ Index, name, format, description (from man 5 page for proc)
+ 0 pid %d The process ID.
+ 3 ppid %d The PID of the parent.
+ 4 pgrp %d The process group ID of the process.
+ 5 session %d The session ID of the process.
+ 17 priority %ld For processes running under a non-real-time scheduling policy, this is
+ the raw nice value (setpriority(2)) as represented in the kernel.
+ The kernel stores nice values as numbers in the range 0 (high) to 39 (low),
+ corresponding to the user- visible nice range of -20 to 19.
+ 18 nice %ld The nice value (see setpriority(2)), a value in the range
+ 19 (low priority) to -20 (high priority).
+ */
+ m_data->pid = contents.at(0).toInt();
+ m_data->ppid = contents.at(3).toInt();
+ m_data->pgrp = contents.at(4).toInt();
+ m_data->sid = contents.at(5).toInt();
+ m_data->priority = contents.at(17).toLong();
+ m_data->nice = contents.at(18).toLong();
+
+ /* Some of the contents (from kernel documentation proc.txt)
+ Field Content
+ Name filename of the executable
+ Pid process id
+ PPid process id of the parent process
+ Uid Real, effective, saved set, and file system UIDs
+ Gid Real, effective, saved set, and file system GIDs
+ Groups supplementary group list
+ ...
+ */
+ QFile status(QString::fromLatin1("/proc/%1/status").arg(pid));
+ if (!status.open(QIODevice::ReadOnly)) {
+ qWarning("Unable to open status file for pid=%d", pid);
+ return;
+ }
+
+ char buf[256];
+ qint64 len;
+ while ((len = status.readLine(buf, 256)) != -1) {
+ if (!strncmp("Name:", buf, 5))
+ m_name = QString::fromLocal8Bit(buf + 6, len-6);
+ else if (!strncmp("Uid:", buf, 4)) {
+ QList<QByteArray> uids = QByteArray(buf + 5, len-5).split('\t');
+ m_data->uid = uids.at(0).toInt();
+ m_data->euid = uids.at(1).toInt();
+ m_data->suid = uids.at(2).toInt();
+ }
+ else if (!strncmp("Gid:", buf, 4)) {
+ QList<QByteArray> gids = QByteArray(buf + 5, len-5).split('\t');
+ m_data->gid = gids.at(0).toInt();
+ m_data->egid = gids.at(1).toInt();
+ m_data->sgid = gids.at(2).toInt();
+ }
+ else if (!strncmp("Groups:", buf, 7)) {
+ QList<QByteArray> groups = QByteArray(buf+8, len-8).split(' ');
+ while (groups.size()) {
+ bool ok;
+ gid_t group = groups.takeFirst().toInt(&ok);
+ if (ok)
+ m_groups.append(group);
+ }
+ }
+ }
+ status.close();
+#elif defined(Q_OS_MAC)
+ int name[4];
+ size_t bufferSize;
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_PID;
+ name[3] = pid;
+
+ if (::sysctl(name, 4, NULL, &bufferSize, NULL, 0) < 0) {
+ qDebug() << "error code" << errno;
+ return;
+ }
+ struct kinfo_proc *kinfo = (struct kinfo_proc *) malloc(bufferSize);
+ if (!kinfo)
+ return;
+ if (::sysctl(name, 4, kinfo, &bufferSize, NULL, 0) < 0) {
+ free(kinfo);
+ return;
+ }
+ int n = bufferSize / sizeof(struct kinfo_proc);
+ if (n != 1) {
+ free(kinfo);
+ return;
+ }
+
+ qDebug() << "Creating data";
+ m_data = new ProcessPrivateData;
+ memset(m_data, 0, sizeof(ProcessPrivateData));
+
+ // Proc data
+ m_data->pid = kinfo->kp_proc.p_pid;
+ m_data->priority = kinfo->kp_proc.p_priority; // Process priority (u_char)
+ m_data->nice = kinfo->kp_proc.p_nice; // Process 'nice' value (char)
+
+ // Effective proc data
+ m_data->ppid = kinfo->kp_eproc.e_ppid; // Parent process id
+ m_data->pgrp = kinfo->kp_eproc.e_pgid; // Process group id
+ m_data->uid = kinfo->kp_eproc.e_pcred.p_ruid; // Real user ID
+ m_data->suid = kinfo->kp_eproc.e_pcred.p_svuid; // Saved user ID
+ m_data->gid = kinfo->kp_eproc.e_pcred.p_rgid; // Real group ID
+ m_data->sgid = kinfo->kp_eproc.e_pcred.p_svgid; // Saved group ID
+
+ // Credentials
+ m_data->euid = kinfo->kp_eproc.e_ucred.cr_uid; // Effective user ID
+ for (int i = 0 ; i < kinfo->kp_eproc.e_ucred.cr_ngroups ; i++)
+ m_groups.append(kinfo->kp_eproc.e_ucred.cr_groups[i]);
+ m_data->egid = m_groups.at(0); // I believe this is correct
+ free(kinfo);
+
+ // Session
+ m_data->sid = ::getsid(m_data->pid);
+
+ // Name requires two additional sysctl calls
+ name[0] = CTL_KERN;
+ name[1] = KERN_ARGMAX;
+ int maxArgs;
+ bufferSize = sizeof(maxArgs);
+ if (::sysctl(name, 2, &maxArgs, &bufferSize, NULL, 0) == -1)
+ return;
+ char *args = (char *) malloc(maxArgs);
+ if (!args)
+ return;
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROCARGS2;
+ name[2] = pid;
+ bufferSize = (size_t) maxArgs;
+ if (::sysctl(name, 3, args, &bufferSize, NULL, 0) == -1) {
+ free(args);
+ return;
+ }
+ char *p = args + sizeof(int); // First few bytes are the number of arguments
+ char *p2 = strrchr(p, '/');
+ if (p2)
+ m_name = QString::fromLocal8Bit(p2+1);
+ else
+ m_name = QString::fromLocal8Bit(p);
+ free(args);
+#endif
+}
+
+bool ExecutingProcessInfo::exists() const { return (m_data != 0); }
+pid_t ExecutingProcessInfo::pid() const { return (m_data ? m_data->pid : 0); }
+pid_t ExecutingProcessInfo::ppid() const { return (m_data ? m_data->ppid : 0); }
+pid_t ExecutingProcessInfo::pgrp() const { return (m_data ? m_data->pgrp : 0); }
+pid_t ExecutingProcessInfo::sid() const { return (m_data ? m_data->sid : 0); }
+uid_t ExecutingProcessInfo::uid() const { return (m_data ? m_data->uid : 0); }
+uid_t ExecutingProcessInfo::euid() const { return (m_data ? m_data->euid : 0); }
+uid_t ExecutingProcessInfo::suid() const { return (m_data ? m_data->suid : 0); }
+gid_t ExecutingProcessInfo::gid() const { return (m_data ? m_data->gid : 0); }
+gid_t ExecutingProcessInfo::egid() const { return (m_data ? m_data->egid : 0); }
+gid_t ExecutingProcessInfo::sgid() const { return (m_data ? m_data->sgid : 0); }
+int ExecutingProcessInfo::priority() const { return (m_data ? m_data->priority : 0); }
+int ExecutingProcessInfo::nice() const { return (m_data ? m_data->nice : 0); }
+
+
ProcUtils::ProcUtils()
{
}
+
+/*!
+ Note: Under MacOSX, we need to use sysctl with CTL_KERN, KERN_PROC, KERN_PROCARGS2, pid
+ which returns a buffer containing the process name, all arguments, all environment variables
+ and sometimes other stuff.
+ */
+
QString ProcUtils::execNameForPid(qint64 pid)
{
#if defined(Q_OS_LINUX)
@@ -189,5 +384,6 @@ bool ProcUtils::setOomAdjustment(pid_t pid, qint32 oomAdjustment)
return false;
}
+#include "moc_procutils.cpp"
QT_END_NAMESPACE_PROCESSMANAGER
diff --git a/src/core/procutils.h b/src/core/procutils.h
index a56297a..c1e14c4 100644
--- a/src/core/procutils.h
+++ b/src/core/procutils.h
@@ -41,6 +41,8 @@
#define PROCUTILS_H
#include <QString>
+#include <QList>
+#include <QObject>
QT_FORWARD_DECLARE_CLASS(QLocalSocket)
@@ -48,6 +50,52 @@ QT_FORWARD_DECLARE_CLASS(QLocalSocket)
QT_BEGIN_NAMESPACE_PROCESSMANAGER
+struct ProcessPrivateData;
+
+class Q_ADDON_PROCESSMANAGER_EXPORT ExecutingProcessInfo : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(pid_t pid READ pid CONSTANT)
+ Q_PROPERTY(pid_t ppid READ ppid CONSTANT)
+ Q_PROPERTY(pid_t pgrp READ pgrp CONSTANT)
+ Q_PROPERTY(pid_t sid READ sid CONSTANT)
+ Q_PROPERTY(uid_t uid READ uid CONSTANT)
+ Q_PROPERTY(uid_t euid READ euid CONSTANT)
+ Q_PROPERTY(uid_t suid READ suid CONSTANT)
+ Q_PROPERTY(gid_t gid READ gid CONSTANT)
+ Q_PROPERTY(gid_t egid READ egid CONSTANT)
+ Q_PROPERTY(gid_t sgid READ sgid CONSTANT)
+ Q_PROPERTY(QList<gid_t> groups READ groups CONSTANT)
+ Q_PROPERTY(int priority READ priority CONSTANT)
+ Q_PROPERTY(int nice READ nice CONSTANT)
+ Q_PROPERTY(QString name READ name CONSTANT)
+
+public:
+ ExecutingProcessInfo(pid_t pid);
+
+ bool exists() const;
+ pid_t pid() const;
+ pid_t ppid() const;
+ pid_t pgrp() const;
+ pid_t sid() const;
+ uid_t uid() const;
+ uid_t euid() const;
+ uid_t suid() const;
+ gid_t gid() const;
+ gid_t egid() const;
+ gid_t sgid() const;
+ int priority() const;
+ int nice() const;
+
+ QList<gid_t> groups() const { return m_groups; }
+ QString name() const { return m_name; }
+
+private:
+ struct ProcessPrivateData *m_data;
+ QList<gid_t> m_groups;
+ QString m_name;
+};
+
class Q_ADDON_PROCESSMANAGER_EXPORT ProcUtils
{
ProcUtils();