master ohmu/fastfetch-openbsd / src / detection / top / top_nbsd.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2#include "common/debug.h"
 3#include "common/mallocHelper.h"
 4
 5#include <sys/types.h>
 6#include <sys/param.h>
 7#include <sys/sysctl.h>
 8#include <errno.h>
 9#include <string.h>
10
11const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
12    int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX };
13    size_t length;
14
15    if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
16        FF_DEBUG("sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed: %s", strerror(errno));
17        return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed";
18    }
19
20    // The process table may change between the two sysctl calls; retry with a larger buffer.
21    length += length / 8 + sizeof(struct kinfo_proc2);
22
23    FF_AUTO_FREE struct kinfo_proc2* processes = malloc(length);
24    if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) {
25        FF_DEBUG("sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, processes}) failed: %s", strerror(errno));
26        return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, processes}) failed";
27    }
28    uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc2));
29
30    const uint32_t pageSizeShift = instance.state.platform.sysinfo.pageSizeShift;
31
32    for (uint32_t i = 0; i < count; ++i) {
33        const struct kinfo_proc2* proc = &processes[i];
34
35        if ((proc->p_flag & P_SYSTEM) || !proc->p_uvalid) { // Kernel process or zombie
36            continue;
37        }
38
39        FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
40
41        ffStrbufInitS(&item->name, proc->p_comm);
42        item->pid = (uint32_t) proc->p_pid;
43
44        uint64_t userMs = (uint64_t) proc->p_uutime_sec * 1000 +
45            (uint64_t) proc->p_uutime_usec / 1000;
46        uint64_t sysMs = (uint64_t) proc->p_ustime_sec * 1000 +
47            (uint64_t) proc->p_ustime_usec / 1000;
48        item->cpuTime = userMs + sysMs;
49
50        item->memBytes = (uint64_t) proc->p_vm_rssize << pageSizeShift;
51
52        item->startTime = (uint64_t) proc->p_ustart_sec * 1000 +
53            (uint64_t) proc->p_ustart_usec / 1000;
54
55        item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE;
56        item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE;
57        item->threads = 0;
58        if (showTypes & FF_TOP_TYPE_THREADS) {
59            int lwpRequest[] = { CTL_KERN, KERN_LWP, proc->p_pid, sizeof(struct kinfo_lwp), 0 };
60            size_t lwpLength = 0;
61            if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) {
62                item->threads = (uint32_t) (lwpLength / sizeof(struct kinfo_lwp));
63            }
64        }
65    }
66
67    return NULL;
68}