commit
de2818a394
11 changed files with 3481 additions and 0 deletions
@ -0,0 +1,26 @@ |
||||
|
||||
Copyright (c) 2018, Al Poole <netstar@gmail.com> |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are met: |
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
* Redistributions in binary form must reproduce the above copyright |
||||
notice, this list of conditions and the following disclaimer in the |
||||
documentation and/or other materials provided with the distribution. |
||||
* Neither the name of the <organization> nor the |
||||
names of its contributors may be used to endorse or promote products |
||||
derived from this software without specific prior written permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
@ -0,0 +1,7 @@ |
||||
# esysinfo |
||||
System Information (EFL) |
||||
|
||||
This is a process monitor. |
||||
|
||||
Currently have full engines for Linux, FreeBSD, OpenBSD and MacOS. |
||||
|
@ -0,0 +1,22 @@ |
||||
LIBS=
|
||||
|
||||
OSNAME := $(shell uname -s)
|
||||
|
||||
ifeq ($(OSNAME), OpenBSD) |
||||
LIBS += -lkvm
|
||||
LDFLAGS += -I/usr/local/include -L/usr/local/lib -L/usr/X11R6/lib
|
||||
endif |
||||
|
||||
export CFLAGS = -g -ggdb3 -O
|
||||
|
||||
export PKGS = eina elementary
|
||||
|
||||
export LIBS |
||||
|
||||
export LDFLAGS |
||||
|
||||
default: |
||||
$(MAKE) -C src
|
||||
|
||||
clean: |
||||
$(MAKE) -C src clean
|
@ -0,0 +1,59 @@ |
||||
/* Copyright 2018. Alastair Poole <netstar@gmail.com>
|
||||
See LICENSE file for details. |
||||
*/ |
||||
|
||||
#include "process.h" |
||||
#include "system.h" |
||||
#include "ui.h" |
||||
|
||||
static void |
||||
_win_del_cb(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) |
||||
{ |
||||
evas_object_del(obj); |
||||
ecore_main_loop_quit(); |
||||
} |
||||
|
||||
static Evas_Object * |
||||
_win_add(void) |
||||
{ |
||||
Evas_Object *win, *icon; |
||||
|
||||
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); |
||||
|
||||
win = elm_win_util_standard_add("esysinfo", "esysinfo"); |
||||
icon = elm_icon_add(win); |
||||
elm_icon_standard_set(icon, "system-preferences"); |
||||
elm_win_icon_object_set(win, icon); |
||||
|
||||
evas_object_resize(win, 768 * elm_config_scale_get(), 420 * elm_config_scale_get()); |
||||
evas_object_smart_callback_add(win, "delete,request", _win_del_cb, NULL); |
||||
|
||||
elm_win_title_set(win, "System Information"); |
||||
|
||||
return win; |
||||
} |
||||
|
||||
int |
||||
main(int argc, char **argv) |
||||
{ |
||||
Evas_Object *win; |
||||
|
||||
eina_init(); |
||||
ecore_init(); |
||||
elm_init(argc, argv); |
||||
|
||||
win = _win_add(); |
||||
ui_add(win); |
||||
|
||||
elm_win_center(win, EINA_TRUE, EINA_TRUE); |
||||
evas_object_show(win); |
||||
|
||||
ecore_main_loop_begin(); |
||||
|
||||
eina_shutdown(); |
||||
ecore_shutdown(); |
||||
elm_shutdown(); |
||||
|
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,24 @@ |
||||
TARGET = ../esysinfo
|
||||
|
||||
OBJECTS = system.o process.o ui.o main.o
|
||||
|
||||
default: $(TARGET) |
||||
|
||||
$(TARGET) : $(OBJECTS) |
||||
$(CC) $(OBJECTS) $(shell pkg-config --libs $(PKGS)) $(LIBS) $(LDFLAGS) -o $@
|
||||
|
||||
main.o: main.c |
||||
$(CC) -c $(CFLAGS) $(shell pkg-config --cflags $(PKGS)) main.c -o $@
|
||||
|
||||
system.o: system.c |
||||
$(CC) -c $(CFLAGS) system.c -o $@
|
||||
|
||||
process.o: process.c |
||||
$(CC) -c $(CFLAGS) $(shell pkg-config --cflags $(PKGS)) process.c -o $@
|
||||
|
||||
ui.o: ui.c |
||||
$(CC) -c $(CFLAGS) $(shell pkg-config --cflags $(PKGS)) ui.c -o $@
|
||||
|
||||
clean: |
||||
-rm $(OBJECTS)
|
||||
-rm $(TARGET)
|
@ -0,0 +1,568 @@ |
||||
#if defined(__MACH__) && defined(__APPLE__) |
||||
# define __MacOS__ |
||||
#endif |
||||
|
||||
#if defined(__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) |
||||
# include <sys/types.h> |
||||
# include <sys/sysctl.h> |
||||
# include <sys/user.h> |
||||
# include <sys/proc.h> |
||||
#endif |
||||
|
||||
#if defined(__OpenBSD__) |
||||
# include <kvm.h> |
||||
# include <limits.h> |
||||
# include <sys/proc.h> |
||||
# include <sys/param.h> |
||||
# include <sys/resource.h> |
||||
#endif |
||||
|
||||
#if defined(__MacOS__) |
||||
# include <libproc.h> |
||||
# include <sys/proc_info.h> |
||||
#endif |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
#include <unistd.h> |
||||
#include <limits.h> |
||||
|
||||
#include "process.h" |
||||
#include <Eina.h> |
||||
#include <Ecore.h> |
||||
#include <Ecore_File.h> |
||||
|
||||
static const char * |
||||
_process_state_name(char state) |
||||
{ |
||||
const char *statename = NULL; |
||||
#if defined(__linux__) |
||||
|
||||
switch (state) |
||||
{ |
||||
case 'D': |
||||
statename = "DSLEEP"; |
||||
break; |
||||
|
||||
case 'I': |
||||
statename = "IDLE"; |
||||
break; |
||||
|
||||
case 'R': |
||||
statename = "RUN"; |
||||
break; |
||||
|
||||
case 'S': |
||||
statename = "SLEEP"; |
||||
break; |
||||
|
||||
case 'T': |
||||
case 't': |
||||
statename = "STOP"; |
||||
break; |
||||
|
||||
case 'X': |
||||
statename = "DEAD"; |
||||
break; |
||||
|
||||
case 'Z': |
||||
statename = "ZOMB"; |
||||
break; |
||||
} |
||||
#else |
||||
switch (state) |
||||
{ |
||||
case SIDL: |
||||
statename = "IDLE"; |
||||
break; |
||||
|
||||
case SRUN: |
||||
statename = "RUN"; |
||||
break; |
||||
|
||||
case SSLEEP: |
||||
statename = "SLEEP"; |
||||
break; |
||||
|
||||
case SSTOP: |
||||
statename = "STOP"; |
||||
break; |
||||
|
||||
#if !defined(__MacOS__) |
||||
#if !defined(__OpenBSD__) |
||||
case SWAIT: |
||||
statename = "WAIT"; |
||||
break; |
||||
|
||||
case SLOCK: |
||||
statename = "LOCK"; |
||||
break; |
||||
|
||||
#endif |
||||
case SZOMB: |
||||
statename = "ZOMB"; |
||||
break; |
||||
|
||||
#endif |
||||
#if defined(__OpenBSD__) |
||||
case SDEAD: |
||||
statename = "DEAD"; |
||||
break; |
||||
|
||||
case SONPROC: |
||||
statename = "ONPROC"; |
||||
break; |
||||
#endif |
||||
} |
||||
#endif |
||||
return statename; |
||||
} |
||||
|
||||
#if defined(__linux__) |
||||
|
||||
static unsigned long |
||||
_parse_line(const char *line) |
||||
{ |
||||
char *p, *tok; |
||||
|
||||
p = strchr(line, ':') + 1; |
||||
while (isspace(*p)) |
||||
p++; |
||||
tok = strtok(p, " "); |
||||
|
||||
return atol(tok); |
||||
} |
||||
|
||||
static Eina_List * |
||||
_process_list_linux_get(void) |
||||
{ |
||||
char *name; |
||||
Eina_List *files, *list = NULL; |
||||
FILE *f; |
||||
char path[PATH_MAX], line[4096], program_name[1024], state; |
||||
int pid, res, utime, stime, cutime, cstime, uid, psr, pri, nice, numthreads; |
||||
unsigned int mem_size, mem_rss; |
||||
|
||||
int pagesize = getpagesize(); |
||||
|
||||
files = ecore_file_ls("/proc"); |
||||
EINA_LIST_FREE(files, name) |
||||
{ |
||||
pid = atoi(name); |
||||
free(name); |
||||
|
||||
if (!pid) continue; |
||||
|
||||
snprintf(path, sizeof(path), "/proc/%d/stat", pid); |
||||
|
||||
f = fopen(path, "r"); |
||||
if (!f) continue; |
||||
|
||||
if (fgets(line, sizeof(line), f)) |
||||
{ |
||||
int dummy; |
||||
char *end, *start = strchr(line, '(') + 1; |
||||
end = strchr(line, ')'); |
||||
strncpy(program_name, start, end - start); |
||||
program_name[end - start] = '\0'; |
||||
|
||||
res = sscanf(end + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u %d %d %d %d %d %d %d %d %d", |
||||
&state, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &utime, &stime, &cutime, &cstime, |
||||
&pri, &nice, &numthreads, &dummy, &dummy, &mem_size, &mem_rss, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, |
||||
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &psr, &dummy, &dummy, &dummy, &dummy, &dummy); |
||||
} |
||||
|
||||
fclose(f); |
||||
|
||||
if (res != 42) continue; |
||||
|
||||
snprintf(path, sizeof(path), "/proc/%d/status", pid); |
||||
|
||||
f = fopen(path, "r"); |
||||
if (!f) continue; |
||||
|
||||
while ((fgets(line, sizeof(line), f)) != NULL) |
||||
{ |
||||
if (!strncmp(line, "Uid:", 4)) |
||||
{ |
||||
uid = _parse_line(line); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
fclose(f); |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
|
||||
p->pid = pid; |
||||
p->uid = uid; |
||||
p->cpu_id = psr; |
||||
snprintf(p->command, sizeof(p->command), "%s", program_name); |
||||
p->state = _process_state_name(state); |
||||
p->cpu_time = utime + stime; |
||||
p->mem_size = mem_size; |
||||
p->mem_rss = mem_rss * pagesize; |
||||
p->nice = nice; |
||||
p->priority = pri; |
||||
p->numthreads = numthreads; |
||||
|
||||
list = eina_list_append(list, p); |
||||
} |
||||
|
||||
if (files) |
||||
eina_list_free(files); |
||||
|
||||
return list; |
||||
} |
||||
|
||||
Proc_Stats * |
||||
proc_info_by_pid(int pid) |
||||
{ |
||||
FILE *f; |
||||
char path[PATH_MAX]; |
||||
char line[4096]; |
||||
char state, program_name[1024]; |
||||
int res, dummy, utime, stime, cutime, cstime, uid, psr; |
||||
unsigned int mem_size, mem_rss, pri, nice, numthreads; |
||||
|
||||
snprintf(path, sizeof(path), "/proc/%d/stat", pid); |
||||
if (!ecore_file_exists(path)) |
||||
return NULL; |
||||
|
||||
f = fopen(path, "r"); |
||||
if (!f) return NULL; |
||||
|
||||
if (fgets(line, sizeof(line), f)) |
||||
{ |
||||
char *end, *start = strchr(line, '(') + 1; |
||||
end = strchr(line, ')'); |
||||
strncpy(program_name, start, end - start); |
||||
program_name[end - start] = '\0'; |
||||
|
||||
res = sscanf(end + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u %d %d %d %d %d %d %d %d %d", |
||||
&state, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &utime, &stime, &cutime, &cstime, |
||||
&pri, &nice, &numthreads, &dummy, &dummy, &mem_size, &mem_rss, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, |
||||
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &psr, &dummy, &dummy, &dummy, &dummy, &dummy); |
||||
} |
||||
fclose(f); |
||||
|
||||
if (res != 42) return NULL; |
||||
|
||||
snprintf(path, sizeof(path), "/proc/%d/status", pid); |
||||
|
||||
f = fopen(path, "r"); |
||||
if (!f) return NULL; |
||||
|
||||
while ((fgets(line, sizeof(line), f)) != NULL) |
||||
{ |
||||
if (!strncmp(line, "Uid:", 4)) |
||||
{ |
||||
uid = _parse_line(line); |
||||
break; |
||||
} |
||||
} |
||||
fclose(f); |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
p->pid = pid; |
||||
p->uid = uid; |
||||
p->cpu_id = psr; |
||||
snprintf(p->command, sizeof(p->command), "%s", program_name); |
||||
p->state = _process_state_name(state); |
||||
p->cpu_time = utime + stime; |
||||
p->mem_size = mem_size; |
||||
p->mem_rss = mem_rss * getpagesize(); |
||||
p->priority = pri; |
||||
p->nice = nice; |
||||
p->numthreads = numthreads; |
||||
|
||||
return p; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#if defined(__OpenBSD__) |
||||
|
||||
Proc_Stats * |
||||
proc_info_by_pid(int pid) |
||||
{ |
||||
struct kinfo_proc *kp; |
||||
kvm_t *kern; |
||||
char errbuf[4096]; |
||||
int count, pagesize, pid_count; |
||||
|
||||
kern = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); |
||||
if (!kern) return NULL; |
||||
|
||||
kp = kvm_getprocs(kern, KERN_PROC_PID, pid, sizeof(*kp), &count); |
||||
if (!kp) return NULL; |
||||
|
||||
if (count == 0) return NULL; |
||||
pagesize = getpagesize(); |
||||
|
||||
Proc_Stats *p = malloc(sizeof(Proc_Stats)); |
||||
p->pid = kp->p_pid; |
||||
p->uid = kp->p_uid; |
||||
p->cpu_id = kp->p_cpuid; |
||||
snprintf(p->command, sizeof(p->command), "%s", kp->p_comm); |
||||
p->state = _process_state_name(kp->p_stat); |
||||
p->cpu_time = kp->p_uticks + kp->p_sticks + kp->p_iticks; |
||||
p->mem_size = (kp->p_vm_tsize * pagesize) + (kp->p_vm_dsize * pagesize) + (kp->p_vm_ssize * pagesize); |
||||
p->mem_rss = kp->p_vm_rssize * pagesize; |
||||
p->priority = kp->p_priority - PZERO; |
||||
p->nice = kp->p_nice - NZERO; |
||||
p->numthreads = -1; |
||||
|
||||
kp = kvm_getprocs(kern, KERN_PROC_SHOW_THREADS, 0, sizeof(*kp), &pid_count); |
||||
|
||||
for (int i = 0; i < pid_count; i++) |
||||
{ |
||||
if (kp[i].p_pid == p->pid) |
||||
p->numthreads++; |
||||
} |
||||
|
||||
kvm_close(kern); |
||||
|
||||
return p; |
||||
} |
||||
|
||||
static Eina_List * |
||||
_process_list_openbsd_get(void) |
||||
{ |
||||
struct kinfo_proc *kp; |
||||
Proc_Stats *p; |
||||
char errbuf[4096]; |
||||
kvm_t *kern; |
||||
int pid_count, pagesize; |
||||
Eina_List *l, *list = NULL; |
||||
|
||||
kern = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); |
||||
if (!kern) return NULL; |
||||
|
||||
kp = kvm_getprocs(kern, KERN_PROC_ALL, 0, sizeof(*kp), &pid_count); |
||||
if (!kp) return NULL; |
||||
|
||||
pagesize = getpagesize(); |
||||
|
||||
for (int i = 0; i < pid_count; i++) |
||||
{ |
||||
p = malloc(sizeof(Proc_Stats)); |
||||
p->pid = kp[i].p_pid; |
||||
p->uid = kp[i].p_uid; |
||||
p->cpu_id = kp[i].p_cpuid; |
||||
snprintf(p->command, sizeof(p->command), "%s", kp[i].p_comm); |
||||
p->state = _process_state_name(kp[i].p_stat); |
||||
p->cpu_time = kp[i].p_uticks + kp[i].p_sticks + kp[i].p_iticks; |
||||
p->mem_size = (kp[i].p_vm_tsize * pagesize) + (kp[i].p_vm_dsize * pagesize) + (kp[i].p_vm_ssize * pagesize); |
||||
p->mem_rss = kp[i].p_vm_rssize * pagesize; |
||||
p->priority = kp[i].p_priority - PZERO; |
||||
p->nice = kp[i].p_nice - NZERO; |
||||
p->numthreads = -1; |
||||
list = eina_list_append(list, p); |
||||
} |
||||
|
||||
kp = kvm_getprocs(kern, KERN_PROC_SHOW_THREADS, 0, sizeof(*kp), &pid_count); |
||||
|
||||
EINA_LIST_FOREACH (list, l, p) |
||||
{ |
||||
for (int i = 0; i < pid_count; i++) |
||||
{ |
||||
if (kp[i].p_pid == p->pid) |
||||
p->numthreads++; |
||||
} |
||||
} |
||||
|
||||
kvm_close(kern); |
||||
|
||||
return list; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#if defined(__MacOS__) |
||||
static Eina_List * |
||||
_process_list_macos_get(void) |
||||
{ |
||||
Eina_List *list = NULL; |
||||
|
||||
for (int i = 1; i <= PID_MAX; i++) |
||||
{ |
||||
struct proc_taskallinfo taskinfo; |
||||
int size = proc_pidinfo(i, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo)); |
||||
if (size != sizeof(taskinfo)) continue; |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
p->pid = i; |
||||
p->uid = taskinfo.pbsd.pbi_uid; |
||||
p->cpu_id = -1; |
||||
snprintf(p->command, sizeof(p->command), "%s", taskinfo.pbsd.pbi_comm); |
||||
p->cpu_time = taskinfo.ptinfo.pti_total_user + taskinfo.ptinfo.pti_total_system; |
||||
p->cpu_time /= 10000000; |
||||
p->state = _process_state_name(taskinfo.pbsd.pbi_status); |
||||
p->mem_size = taskinfo.ptinfo.pti_virtual_size; |
||||
p->mem_rss = taskinfo.ptinfo.pti_resident_size; |
||||
p->priority = taskinfo.ptinfo.pti_priority; |
||||
p->nice = taskinfo.pbsd.pbi_nice; |
||||
p->numthreads = taskinfo.ptinfo.pti_threadnum; |
||||
|
||||
list = eina_list_append(list, p); |
||||
} |
||||
|
||||
return list; |
||||
} |
||||
|
||||
Proc_Stats * |
||||
proc_info_by_pid(int pid) |
||||
{ |
||||
struct kinfo_proc kp; |
||||
struct proc_taskallinfo taskinfo; |
||||
struct proc_workqueueinfo workqueue; |
||||
size_t size; |
||||
|
||||
size = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo)); |
||||
if (size != sizeof(taskinfo)) |
||||
return NULL; |
||||
|
||||
size = proc_pidinfo(pid, PROC_PIDWORKQUEUEINFO, 0, &workqueue, sizeof(workqueue)); |
||||
if (size != sizeof(workqueue)) |
||||
return NULL; |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
p->pid = pid; |
||||
p->uid = taskinfo.pbsd.pbi_uid; |
||||
p->cpu_id = workqueue.pwq_nthreads; |
||||
snprintf(p->command, sizeof(p->command), "%s", taskinfo.pbsd.pbi_comm); |
||||
p->cpu_time = taskinfo.ptinfo.pti_total_user + taskinfo.ptinfo.pti_total_system; |
||||
p->cpu_time /= 10000000; |
||||
p->state = _process_state_name(taskinfo.pbsd.pbi_status); |
||||
p->mem_size = taskinfo.ptinfo.pti_virtual_size; |
||||
p->mem_rss = taskinfo.ptinfo.pti_resident_size; |
||||
p->priority = taskinfo.ptinfo.pti_priority; |
||||
p->nice = taskinfo.pbsd.pbi_nice; |
||||
p->numthreads = taskinfo.ptinfo.pti_threadnum; |
||||
|
||||
return p; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) |
||||
static Eina_List * |
||||
_process_list_freebsd_get(void) |
||||
{ |
||||
Eina_List *list; |
||||
struct rusage *usage; |
||||
struct kinfo_proc kp; |
||||
int mib[4]; |
||||
size_t len; |
||||
int pagesize = getpagesize(); |
||||
|
||||
list = NULL; |
||||
|
||||
len = sizeof(int); |
||||
if (sysctlnametomib("kern.proc.pid", mib, &len) == -1) |
||||
return NULL; |
||||
|
||||
for (int i = 1; i <= PID_MAX; i++) |
||||
{ |
||||
mib[3] = i; |
||||
len = sizeof(kp); |
||||
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) |
||||
{ |
||||
continue; |
||||
} |
||||
|
||||
if (kp.ki_flag & P_SYSTEM) |
||||
continue; |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
|
||||
p->pid = kp.ki_pid; |
||||
p->uid = kp.ki_uid; |
||||
snprintf(p->command, sizeof(p->command), "%s", kp.ki_comm); |
||||
p->cpu_id = kp.ki_oncpu; |
||||
if (p->cpu_id == -1) |
||||
p->cpu_id = kp.ki_lastcpu; |
||||
|
||||
usage = &kp.ki_rusage; |
||||
|
||||
p->cpu_time = (usage->ru_utime.tv_sec * 1000000) + usage->ru_utime.tv_usec + (usage->ru_stime.tv_sec * 1000000) + usage->ru_stime.tv_usec; |
||||
p->cpu_time /= 10000; |
||||
p->state = _process_state_name(kp.ki_stat); |
||||
p->mem_size = kp.ki_size; |
||||
p->mem_rss = kp.ki_rssize * pagesize; |
||||
p->nice = kp.ki_nice - NZERO; |
||||
p->priority = kp.ki_pri.pri_level - PZERO; |
||||
p->numthreads = kp.ki_numthreads; |
||||
|
||||
list = eina_list_append(list, p); |
||||
} |
||||
|
||||
return list; |
||||
} |
||||
|
||||
Proc_Stats * |
||||
proc_info_by_pid(int pid) |
||||
{ |
||||
struct rusage *usage; |
||||
struct kinfo_proc kp; |
||||
int mib[4]; |
||||
size_t len; |
||||
int pagesize = getpagesize(); |
||||
|
||||
len = sizeof(int); |
||||
if (sysctlnametomib("kern.proc.pid", mib, &len) == -1) |
||||
return NULL; |
||||
|
||||
mib[3] = pid; |
||||
|
||||
len = sizeof(kp); |
||||
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) |
||||
return NULL; |
||||
|
||||
Proc_Stats *p = calloc(1, sizeof(Proc_Stats)); |
||||
p->pid = kp.ki_pid; |
||||
p->uid = kp.ki_uid; |
||||
snprintf(p->command, sizeof(p->command), "%s", kp.ki_comm); |
||||
p->cpu_id = kp.ki_oncpu; |
||||
if (p->cpu_id == -1) |
||||
p->cpu_id = kp.ki_lastcpu; |
||||
|
||||
usage = &kp.ki_rusage; |
||||
|
||||
p->cpu_time = (usage->ru_utime.tv_sec * 1000000) + usage->ru_utime.tv_usec + (usage->ru_stime.tv_sec * 1000000) + usage->ru_stime.tv_usec; |
||||
p->cpu_time /= 10000; |
||||
p->state = _process_state_name(kp.ki_stat); |
||||
p->mem_size = kp.ki_size; |
||||
p->mem_rss = kp.ki_rssize * pagesize; |
||||
p->nice = kp.ki_nice = NZERO; |
||||
p->priority = kp.ki_pri.pri_level - PZERO; |
||||
p->numthreads = kp.ki_numthreads; |
||||
|
||||
return p; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
Eina_List * |
||||
proc_info_all_get(void) |
||||
{ |
||||
Eina_List *processes; |
||||
|
||||
#if defined(__linux__) |
||||
processes = _process_list_linux_get(); |
||||
#elif defined(__FreeBSD__) || defined(__DragonFly__) |
||||
processes = _process_list_freebsd_get(); |
||||
#elif defined(__MacOS__) |
||||
processes = _process_list_macos_get(); |
||||
#elif defined(__OpenBSD__) |
||||
processes = _process_list_openbsd_get(); |
||||
#else |
||||
processes = NULL; |
||||
#endif |
||||
|
||||
return processes; |
||||
} |
||||
|
@ -0,0 +1,69 @@ |
||||
#ifndef __PROC_H__ |
||||
#define __PROC_H__ |
||||
|
||||
/**
|
||||
* @file |
||||
* @brief Routines for querying processes. |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief Querying Processes |
||||
* @defgroup Proc |
||||
* |
||||
* @{ |
||||
* |
||||
* Query processes. |
||||
* |
||||
*/ |
||||
|
||||
#include <Eina.h> |
||||
#include <stdint.h> |
||||
#include <unistd.h> |
||||
|
||||
#if !defined(PID_MAX) |
||||
# define PID_MAX 99999 |
||||
#endif |
||||
|
||||
#define CMD_NAME_MAX 256 |
||||
|
||||
typedef struct _Proc_Stats |
||||
{ |
||||
pid_t pid; |
||||
uid_t uid; |
||||
int8_t nice; |
||||
int8_t priority; |
||||
int cpu_id; |
||||
int32_t numthreads; |
||||
int64_t mem_size; |
||||
int64_t mem_rss; |
||||
double cpu_usage; |
||||
char command[CMD_NAME_MAX]; |
||||
const char *state; |
||||
|
||||
// Not used yet in UI.
|
||||
long cpu_time; |
||||
} Proc_Stats; |
||||
|
||||
/**
|
||||
* Query a full list of running processes and return a list. |
||||
* |
||||
* @return A list of proc_t members for all processes. |
||||
*/ |
||||
Eina_List * |
||||
proc_info_all_get(void); |
||||
|
||||
/**
|
||||
* Query a process for its current state. |
||||
* |
||||
* @param pid The process ID to query. |
||||
* |
||||
* @return A proc_t pointer containing the process information. |
||||
*/ |
||||
Proc_Stats * |
||||
proc_info_by_pid(int pid); |
||||
|
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
#endif |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@ |
||||
#ifndef __SYSTEM_H__ |
||||
#define __SYSTEM_H__ |
||||
|
||||
int |
||||
system_cpu_memory_get(double *percent_cpu, long *memory_total, long *memory_used); |
||||
|
||||
#endif |
@ -0,0 +1,114 @@ |
||||
#ifndef __UI_H__ |
||||
#define __UI_H__ |
||||
|
||||
#include <Elementary.h> |
||||
|
||||
typedef enum |
||||
{ |
||||
PROCESS_INFO_FIELD_PID, |
||||
PROCESS_INFO_FIELD_UID, |
||||
PROCESS_INFO_FIELD_SIZE, |
||||
PROCESS_INFO_FIELD_RSS, |
||||
PROCESS_INFO_FIELD_COMMAND, |
||||
PROCESS_INFO_FIELD_STATE, |
||||
PROCESS_INFO_FIELD_CPU_USAGE, |
||||
|
||||
// Not displayed in the main UI.
|
||||
PROCESS_INFO_FIELD_NICE, |
||||
PROCESS_INFO_FIELD_PRI, |
||||
PROCESS_INFO_FIELD_CPU, |
||||
PROCESS_INFO_FIELD_THREADS, |
||||
// Not used yet in UI.
|
||||
PROCESS_INFO_FIELD_CPU_TIME, |
||||
} Proc_Stats_Field; |
||||
|
||||
#define PROCESS_INFO_FIELDS 7 |
||||
|
||||
typedef enum |
||||
{ |
||||
SORT_BY_NONE, |
||||
SORT_BY_PID, |
||||
SORT_BY_UID, |
||||
SORT_BY_NICE, |
||||
SORT_BY_PRI, |
||||
SORT_BY_CPU, |
||||
SORT_BY_THREADS, |
||||
SORT_BY_SIZE, |
||||
SORT_BY_RSS, |
||||
SORT_BY_CMD, |
||||
SORT_BY_STATE, |
||||
SORT_BY_CPU_USAGE, |
||||
} Sort_Type; |
||||
|
||||
typedef struct Ui |
||||
{ |
||||
Evas_Object *win; |
||||
Evas_Object *panel; |
||||
Evas_Object *scroller; |
||||
|
||||
Evas_Object *progress_cpu; |
||||
Evas_Object *progress_mem; |
||||
|
||||
Evas_Object *entry_pid; |
||||
Evas_Object *entry_uid; |
||||
Evas_Object *entry_size; |
||||
Evas_Object *entry_rss; |
||||
Evas_Object *entry_cmd; |
||||
Evas_Object *entry_state; |
||||
Evas_Object *entry_cpu_usage; |
||||
|
||||
Evas_Object *btn_pid; |
||||
Evas_Object *btn_uid; |
||||
Evas_Object *btn_size; |
||||
Evas_Object *btn_rss; |
||||
Evas_Object *btn_cmd; |
||||
Evas_Object *btn_state; |
||||
Evas_Object *btn_cpu_usage; |
||||
|
||||
Evas_Object *entry_pid_cmd; |
||||
Evas_Object *entry_pid_user; |
||||
Evas_Object *entry_pid_pid; |
||||
Evas_Object *entry_pid_uid; |
||||
Evas_Object *entry_pid_cpu; |
||||
Evas_Object *entry_pid_threads; |
||||
Evas_Object *entry_pid_size; |
||||
Evas_Object *entry_pid_rss; |
||||
Evas_Object *entry_pid_nice; |
||||
Evas_Object *entry_pid_pri; |
||||
Evas_Object *entry_pid_state; |
||||
Evas_Object *entry_pid_cpu_usage; |
||||
|
||||
Ecore_Timer *timer_pid; |
||||
pid_t selected_pid; |
||||
pid_t program_pid; |
||||
|
||||
#define TEXT_FIELD_MAX 65535 |
||||
char *fields[PROCESS_INFO_FIELDS]; |
||||
|
||||
Evas_Object *list_pid; |
||||
|
||||
Eina_Bool first_run; |
||||
|
||||
int64_t cpu_times[PID_MAX]; |
||||
int64_t pid_cpu_time; |
||||
|
||||
int poll_delay; |
||||
|
||||
Sort_Type sort_type; |
||||
Eina_Bool sort_reverse; |
||||
Eina_Bool panel_visible; |
||||
|
||||
} Ui; |
||||
|
||||
typedef struct Sys_Stats |
||||
{ |
||||
int cpu_count; |
||||
double cpu_usage; |
||||
long mem_total; |
||||
long mem_used; |
||||
} Sys_Stats; |
||||
|
||||
void |
||||
ui_add(Evas_Object *win); |
||||
|
||||
#endif |
Loading…
Reference in new issue