master ohmu/fastfetch-openbsd / src / detection / top / top_gnu.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2
 3#include <hurd.h>
 4#include <string.h>
 5#include <ps.h>
 6
 7const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
 8    struct ps_context* context = nullptr;
 9    if (ps_context_create(getproc(), &context) != 0) {
10        return "ps_context_create(getproc()) failed";
11    }
12
13    const char* error = nullptr;
14    struct proc_stat_list* list = nullptr;
15    if (proc_stat_list_create(context, &list) != 0) {
16        error = "proc_stat_list_create() failed";
17        goto done;
18    }
19
20    if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) {
21        error = "proc_stat_list_add_all() failed";
22        goto done;
23    }
24
25    // Flags that cannot be fetched for some process are simply left unset;
26    // each field must be checked before use.
27    if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC | ((showTypes & FF_TOP_TYPE_THREADS) ? PSTAT_NUM_THREADS : 0)) != 0) {
28        error = "proc_stat_list_set_flags() failed";
29        goto done;
30    }
31
32    for (unsigned i = 0; i < list->num_procs; ++i) {
33        struct proc_stat* stat = list->proc_stats[i];
34
35        if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) {
36            continue;
37        }
38        if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) {
39            continue;
40        }
41
42        uint32_t pid = (uint32_t) proc_stat_pid(stat);
43        if (pid == 2) { // Kernel Task
44            continue;
45        }
46
47        FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
48
49        // There is no kernel-side comm on the Hurd; use the first argument.
50        ffStrbufInit(&item->name);
51        if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) {
52            size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat));
53            ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat));
54        }
55        if (item->name.length == 0) {
56            ffStrbufAppendS(&item->name, "(unknown)");
57        }
58
59        item->pid = pid;
60        item->cpuTime = 0;
61        item->memBytes = 0;
62        item->startTime = 0;
63        item->threads = 0;
64
65        if (showTypes & FF_TOP_TYPE_THREADS) {
66            if (proc_stat_has(stat, PSTAT_NUM_THREADS)) {
67                item->threads = (uint32_t) proc_stat_num_threads(stat);
68            }
69        }
70
71        if (proc_stat_has(stat, PSTAT_TASK_BASIC)) {
72            const task_basic_info_t info = proc_stat_task_basic_info(stat);
73            item->cpuTime = (uint64_t) info->user_time64.seconds * 1000 +
74                (uint64_t) info->user_time64.nanoseconds / 1000000 +
75                (uint64_t) info->system_time64.seconds * 1000 +
76                (uint64_t) info->system_time64.nanoseconds / 1000000;
77            item->memBytes = (uint64_t) info->resident_size;
78            item->startTime = (uint64_t) info->creation_time64.seconds * 1000 +
79                (uint64_t) info->creation_time64.nanoseconds / 1000000;
80        }
81
82        // Storage io counters aren't exposed by kernel; leave them zeroed.
83        item->bytesRead = 0;
84        item->bytesWritten = 0;
85    }
86
87done:
88    if (list) {
89        proc_stat_list_free(list);
90    }
91    ps_context_free(context);
92    return error;
93}