File indexing completed on 2024-05-19 03:56:25
0001 /* 0002 0003 This file is part of the KDE Frameworks 0004 0005 SPDX-FileCopyrightText: 2019 Tobias C. Berner <tcberner@FreeBSD.org> 0006 0007 SPDX-License-Identifier: LGPL-2.1-only 0008 */ 0009 0010 #pragma once 0011 0012 #include <sys/param.h> 0013 #include <sys/sysctl.h> 0014 #include <sys/types.h> 0015 #include <sys/user.h> 0016 0017 #include <sys/queue.h> // Must be included before libprocstat.h, otherwise this fails to build on FreeBSD 0018 0019 #include <libprocstat.h> 0020 0021 namespace KProcessList 0022 { 0023 struct ProcStat { 0024 public: 0025 struct procstat *pstat; 0026 ProcStat() 0027 { 0028 pstat = procstat_open_sysctl(); 0029 } 0030 0031 ~ProcStat() 0032 { 0033 procstat_close(pstat); 0034 } 0035 0036 operator bool() const 0037 { 0038 return pstat; 0039 } 0040 }; 0041 0042 struct ProcStatProcesses { 0043 private: 0044 ProcStat &parent; 0045 unsigned int proc_count; 0046 struct kinfo_proc *procs; 0047 0048 public: 0049 ProcStatProcesses(ProcStat &pstat) 0050 : parent(pstat) 0051 { 0052 procs = procstat_getprocs(parent.pstat, KERN_PROC_PROC, 0, &proc_count); 0053 } 0054 0055 ~ProcStatProcesses() 0056 { 0057 if (procs) { 0058 procstat_freeprocs(parent.pstat, procs); 0059 } 0060 } 0061 0062 operator bool() const 0063 { 0064 return procs && proc_count > 0; 0065 } 0066 0067 unsigned int count() const 0068 { 0069 return proc_count; 0070 } 0071 0072 class ProcessIterator 0073 { 0074 private: 0075 const ProcStatProcesses &processes; 0076 unsigned int pos; 0077 0078 public: 0079 ProcessIterator(const ProcStatProcesses &processes, unsigned int pos) 0080 : processes(processes) 0081 , pos(pos){}; 0082 0083 bool operator!=(const ProcessIterator &other) const 0084 { 0085 return pos != other.pos; 0086 } 0087 0088 ProcessIterator &operator++() 0089 { 0090 if (pos < processes.count()) { 0091 ++pos; 0092 } 0093 return *this; 0094 } 0095 0096 const KProcessInfo operator*() 0097 { 0098 QStringList command_line; 0099 QString command; 0100 struct kinfo_proc *proc = &processes.procs[pos]; 0101 0102 // Don't use procstat_getpathname() because: 0103 // - it can fail, and then it spams a warning to stderr 0104 // - it produces a full path, e.g. /tmp/kde/build/kcoreaddons/bin/kprocesslisttest 0105 // rather than the command-name, so it fails in tests that check for 0106 // a process name only. 0107 command = QString::fromLocal8Bit(proc->ki_comm); 0108 0109 char **args; 0110 args = procstat_getargv(processes.parent.pstat, proc, 0); 0111 if (args) { 0112 for (int i = 0; args[i] != nullptr; i++) { 0113 command_line << QString::fromLocal8Bit(args[i]); 0114 } 0115 } 0116 0117 pid_t pid = proc->ki_pid; 0118 QString user = QString::fromLocal8Bit(proc->ki_login); 0119 return KProcessInfo(pid, command_line.join(QString::fromLocal8Bit(" ")), command, user); 0120 } 0121 }; 0122 0123 ProcessIterator begin() const 0124 { 0125 return ProcessIterator(*this, 0); 0126 } 0127 ProcessIterator end() const 0128 { 0129 return ProcessIterator(*this, this->count()); 0130 } 0131 }; 0132 }