Pi66

Home | Repos | About | Blog | Gaza

sta
minimal & simple status monitoring app.
git clone https://git.pi66.xyz/sta

About | Files | Commits | Refs | License


add slstatus patch

Author: pi66
Date: 2025-10-10 23:51
commit: 0ec8219d

Stat

A patcher.py 32 +32 -0
A patches/slstatus/components/battery.c 257 +257 -0
A patches/slstatus/components/cpu.c 162 +162 -0
A patches/slstatus/components/datetime.c 20 +20 -0
A patches/slstatus/components/disk.c 62 +62 -0
A patches/slstatus/components/ram.c 220 +220 -0
A patches/slstatus/components/run_command.c 29 +29 -0
A patches/slstatus/components/temperature.c 75 +75 -0
A patches/slstatus/components/util.c 146 +146 -0
A patches/slstatus/components/wifi.c 275 +275 -0
A patches/slstatus/slstatus.patch 415 +415 -0

Diff

diff --git a/patcher.py b/patcher.py
new file mode 100644
index 0000000..3b204d7
--- /dev/null
+++ b/patcher.py
@@ -0,0 +1,32 @@
+from os import listdir,system
+
+patches = listdir("./patches")
+
+
+for index,patch in enumerate(patches):
+    print(f"[{index+1}]- {patch}")
+
+try:
+    patch_id = int(input("\nchooce patche id: "))
+except ValueError:
+    print("Not a valid number")
+    exit(1)
+

...
Show all
diff --git a/patcher.py b/patcher.py
new file mode 100644
index 0000000..3b204d7
--- /dev/null
+++ b/patcher.py
@@ -0,0 +1,32 @@
+from os import listdir,system
+
+patches = listdir("./patches")
+
+
+for index,patch in enumerate(patches):
+    print(f"[{index+1}]- {patch}")
+
+try:
+    patch_id = int(input("\nchooce patche id: "))
+except ValueError:
+    print("Not a valid number")
+    exit(1)
+
+
+if patch_id <1 or patch_id > len(patches):
+    print("Out of range!!")
+    exit(1)
+
+
+
+if patches[patch_id-1] == "slstatus":
+    print("")
+    system("cp -r patches/slstatus/components .")
+    system("patch < patches/slstatus/slstatus.patch")
+    print("")
+    print("don't forget to run:\n\t sudo make install")
+else:
+    print("Out of range!!")
+    exit(1)
+
+
diff --git a/patches/slstatus/components/battery.c b/patches/slstatus/components/battery.c
new file mode 100644
index 0000000..734bc1d
--- /dev/null
+++ b/patches/slstatus/components/battery.c
@@ -0,0 +1,257 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <string.h>
+
+#include "../util.h"
+
+#if defined(__linux__)
+/*
+ * https://www.kernel.org/doc/html/latest/power/power_supply_class.html
+ */
+	#include <limits.h>
+	#include <stdint.h>
+	#include <unistd.h>
+
+	#define POWER_SUPPLY_CAPACITY "/sys/class/power_supply/%s/capacity"
+	#define POWER_SUPPLY_STATUS   "/sys/class/power_supply/%s/status"
+	#define POWER_SUPPLY_CHARGE   "/sys/class/power_supply/%s/charge_now"
+	#define POWER_SUPPLY_ENERGY   "/sys/class/power_supply/%s/energy_now"
+	#define POWER_SUPPLY_CURRENT  "/sys/class/power_supply/%s/current_now"
+	#define POWER_SUPPLY_POWER    "/sys/class/power_supply/%s/power_now"
+
+	static const char *
+	pick(const char *bat, const char *f1, const char *f2, char *path,
+	     size_t length)
+	{
+	static _Thread_local char buf[1024];
+		if (esnprintf(buf, path, length, f1, bat) > 0 &&
+		    access(path, R_OK) == 0)
+			return f1;
+
+		if (esnprintf(buf, path, length, f2, bat) > 0 &&
+		    access(path, R_OK) == 0)
+			return f2;
+
+		return NULL;
+	}
+
+	const char *
+	battery_perc(const char *bat)
+	{
+	static _Thread_local char buf[1024];
+		int cap_perc;
+		char path[PATH_MAX];
+
+		if (esnprintf(buf, path, sizeof(path), POWER_SUPPLY_CAPACITY, bat) < 0)
+			return NULL;
+		if (pscanf(buf, path, "%d", &cap_perc) != 1)
+			return NULL;
+
+		return bprintf(buf, "%d", cap_perc);
+	}
+
+	const char *
+	battery_state(const char *bat)
+	{
+	static _Thread_local char buf[1024];
+		static struct {
+			char *state;
+			char *symbol;
+		} map[] = {
+			{ "Charging",    "󰚥" },
+			{ "Discharging", "󰚦" },
+			{ "Full",        "󰚥" },
+			{ "Not charging", "󰚥"},
+		};
+		size_t i;
+		char path[PATH_MAX], state[12];
+
+		if (esnprintf(buf, path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)
+			return NULL;
+		if (pscanf(buf, path, "%12[a-zA-Z ]", state) != 1)
+			return NULL;
+
+		for (i = 0; i < LEN(map); i++)
+			if (!strcmp(map[i].state, state))
+				break;
+
+		return (i == LEN(map)) ? "?" : map[i].symbol;
+	}
+
+	const char *
+	battery_remaining(const char *bat)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t charge_now, current_now, m, h;
+		double timeleft;
+		char path[PATH_MAX], state[12];
+
+		if (esnprintf(buf, path, sizeof(path), POWER_SUPPLY_STATUS, bat) < 0)
+			return NULL;
+		if (pscanf(buf, path, "%12[a-zA-Z ]", state) != 1)
+			return NULL;
+
+		if (!pick(bat, POWER_SUPPLY_CHARGE, POWER_SUPPLY_ENERGY, path,
+		          sizeof(path)) ||
+		    pscanf(buf, path, "%ju", &charge_now) < 0)
+			return NULL;
+
+		if (!strcmp(state, "Discharging")) {
+			if (!pick(bat, POWER_SUPPLY_CURRENT, POWER_SUPPLY_POWER, path,
+			          sizeof(path)) ||
+			    pscanf(buf, path, "%ju", &current_now) < 0)
+				return NULL;
+
+			if (current_now == 0)
+				return NULL;
+
+			timeleft = (double)charge_now / (double)current_now;
+			h = timeleft;
+			m = (timeleft - (double)h) * 60;
+
+			return bprintf(buf, "%juh %jum", h, m);
+		}
+
+		return "";
+	}
+#elif defined(__OpenBSD__)
+	#include <fcntl.h>
+	#include <machine/apmvar.h>
+	#include <sys/ioctl.h>
+	#include <unistd.h>
+
+	static int
+	load_apm_power_info(struct apm_power_info *apm_info)
+	{
+	static _Thread_local char buf[1024];
+		int fd;
+
+		fd = open("/dev/apm", O_RDONLY);
+		if (fd < 0) {
+			warn("open '/dev/apm':");
+			return 0;
+		}
+
+		memset(apm_info, 0, sizeof(struct apm_power_info));
+		if (ioctl(fd, APM_IOC_GETPOWER, apm_info) < 0) {
+			warn("ioctl 'APM_IOC_GETPOWER':");
+			close(fd);
+			return 0;
+		}
+		return close(fd), 1;
+	}
+
+	const char *
+	battery_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct apm_power_info apm_info;
+
+		if (load_apm_power_info(&apm_info))
+			return bprintf(buf, "%d", apm_info.battery_life);
+
+		return NULL;
+	}
+
+	const char *
+	battery_state(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct {
+			unsigned int state;
+			char *symbol;
+		} map[] = {
+			{ APM_AC_ON,      "+" },
+			{ APM_AC_OFF,     "-" },
+		};
+		struct apm_power_info apm_info;
+		size_t i;
+
+		if (load_apm_power_info(&apm_info)) {
+			for (i = 0; i < LEN(map); i++)
+				if (map[i].state == apm_info.ac_state)
+					break;
+
+			return (i == LEN(map)) ? "?" : map[i].symbol;
+		}
+
+		return NULL;
+	}
+
+	const char *
+	battery_remaining(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct apm_power_info apm_info;
+		unsigned int h, m;
+
+		if (load_apm_power_info(&apm_info)) {
+			if (apm_info.ac_state != APM_AC_ON) {
+				h = apm_info.minutes_left / 60;
+				m = apm_info.minutes_left % 60;
+				return bprintf(buf, "%uh %02um", h, m);
+			} else {
+				return "";
+			}
+		}
+
+		return NULL;
+	}
+#elif defined(__FreeBSD__)
+	#include <sys/sysctl.h>
+
+	#define BATTERY_LIFE  "hw.acpi.battery.life"
+	#define BATTERY_STATE "hw.acpi.battery.state"
+	#define BATTERY_TIME  "hw.acpi.battery.time"
+
+	const char *
+	battery_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int cap_perc;
+		size_t len;
+
+		len = sizeof(cap_perc);
+		if (sysctlbyname(BATTERY_LIFE, &cap_perc, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		return bprintf(buf, "%d", cap_perc);
+	}
+
+	const char *
+	battery_state(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int state;
+		size_t len;
+
+		len = sizeof(state);
+		if (sysctlbyname(BATTERY_STATE, &state, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		switch (state) {
+		case 0: /* FALLTHROUGH */
+		case 2:
+			return "+";
+		case 1:
+			return "-";
+		default:
+			return "?";
+		}
+	}
+
+	const char *
+	battery_remaining(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int rem;
+		size_t len;
+
+		len = sizeof(rem);
+		if (sysctlbyname(BATTERY_TIME, &rem, &len, NULL, 0) < 0 || !len
+		    || rem < 0)
+			return NULL;
+
+		return bprintf(buf, "%uh %02um", rem / 60, rem % 60);
+	}
+#endif
diff --git a/patches/slstatus/components/cpu.c b/patches/slstatus/components/cpu.c
new file mode 100644
index 0000000..f95759a
--- /dev/null
+++ b/patches/slstatus/components/cpu.c
@@ -0,0 +1,162 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "../util.h"
+
+#if defined(__linux__)
+	#define CPU_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
+
+	const char *
+	cpu_freq(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t freq;
+
+		/* in kHz */
+		if (pscanf(buf, CPU_FREQ, "%ju", &freq) != 1)
+			return NULL;
+
+		return fmt_human(buf, freq * 1000, 1000);
+	}
+
+	const char *
+	cpu_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		static long double a[7];
+		long double b[7], sum;
+
+		memcpy(b, a, sizeof(b));
+		/* cpu user nice system idle iowait irq softirq */
+		if (pscanf(buf, "/proc/stat", "%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf",
+		           &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6])
+		    != 7)
+			return NULL;
+
+		if (b[0] == 0)
+			return NULL;
+
+		sum = (b[0] + b[1] + b[2] + b[3] + b[4] + b[5] + b[6]) -
+		      (a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6]);
+
+		if (sum == 0)
+			return NULL;
+
+		return bprintf(buf, "%d", (int)(100 *
+		               ((b[0] + b[1] + b[2] + b[5] + b[6]) -
+		                (a[0] + a[1] + a[2] + a[5] + a[6])) / sum));
+	}
+#elif defined(__OpenBSD__)
+	#include <sys/param.h>
+	#include <sys/sched.h>
+	#include <sys/sysctl.h>
+
+	const char *
+	cpu_freq(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int freq, mib[2];
+		size_t size;
+
+		mib[0] = CTL_HW;
+		mib[1] = HW_CPUSPEED;
+
+		size = sizeof(freq);
+
+		/* in MHz */
+		if (sysctl(mib, 2, &freq, &size, NULL, 0) < 0) {
+			warn("sysctl 'HW_CPUSPEED':");
+			return NULL;
+		}
+
+		return fmt_human(buf, freq * 1E6, 1000);
+	}
+
+	const char *
+	cpu_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int mib[2];
+		static uintmax_t a[CPUSTATES];
+		uintmax_t b[CPUSTATES], sum;
+		size_t size;
+
+		mib[0] = CTL_KERN;
+		mib[1] = KERN_CPTIME;
+
+		size = sizeof(a);
+
+		memcpy(b, a, sizeof(b));
+		if (sysctl(mib, 2, &a, &size, NULL, 0) < 0) {
+			warn("sysctl 'KERN_CPTIME':");
+			return NULL;
+		}
+		if (b[0] == 0)
+			return NULL;
+
+		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -
+		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);
+
+		if (sum == 0)
+			return NULL;
+
+		return bprintf(buf, "%d", 100 *
+		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +
+		                 a[CP_INTR]) -
+		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +
+		                 b[CP_INTR])) / sum);
+	}
+#elif defined(__FreeBSD__)
+	#include <devstat.h>
+	#include <sys/param.h>
+	#include <sys/sysctl.h>
+
+	const char *
+	cpu_freq(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int freq;
+		size_t size;
+
+		size = sizeof(freq);
+		/* in MHz */
+		if (sysctlbyname("hw.clockrate", &freq, &size, NULL, 0) < 0 || !size) {
+			warn("sysctlbyname 'hw.clockrate':");
+			return NULL;
+		}
+
+		return fmt_human(buf, freq * 1E6, 1000);
+	}
+
+	const char *
+	cpu_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		size_t size;
+		static long a[CPUSTATES];
+		long b[CPUSTATES], sum;
+
+		size = sizeof(a);
+		memcpy(b, a, sizeof(b));
+		if (sysctlbyname("kern.cp_time", &a, &size, NULL, 0) < 0 || !size) {
+			warn("sysctlbyname 'kern.cp_time':");
+			return NULL;
+		}
+		if (b[0] == 0)
+			return NULL;
+
+		sum = (a[CP_USER] + a[CP_NICE] + a[CP_SYS] + a[CP_INTR] + a[CP_IDLE]) -
+		      (b[CP_USER] + b[CP_NICE] + b[CP_SYS] + b[CP_INTR] + b[CP_IDLE]);
+
+		if (sum == 0)
+			return NULL;
+
+		return bprintf(buf, "%d", 100 *
+		               ((a[CP_USER] + a[CP_NICE] + a[CP_SYS] +
+		                 a[CP_INTR]) -
+		                (b[CP_USER] + b[CP_NICE] + b[CP_SYS] +
+		                 b[CP_INTR])) / sum);
+	}
+#endif
diff --git a/patches/slstatus/components/datetime.c b/patches/slstatus/components/datetime.c
new file mode 100644
index 0000000..b06ece2
--- /dev/null
+++ b/patches/slstatus/components/datetime.c
@@ -0,0 +1,20 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <time.h>
+
+#include "../util.h"
+
+const char *
+datetime(const char *fmt)
+{
+	static _Thread_local char buf[1024];
+	time_t t;
+
+	t = time(NULL);
+	if (!strftime(buf, sizeof(buf), fmt, localtime(&t))) {
+		warn("strftime: Result string exceeds buffer size");
+		return NULL;
+	}
+
+	return buf;
+}
diff --git a/patches/slstatus/components/disk.c b/patches/slstatus/components/disk.c
new file mode 100644
index 0000000..3d2028a
--- /dev/null
+++ b/patches/slstatus/components/disk.c
@@ -0,0 +1,62 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <sys/statvfs.h>
+
+#include "../util.h"
+
+const char *
+disk_free(const char *path)
+{
+	static _Thread_local char buf[1024];
+	struct statvfs fs;
+
+	if (statvfs(path, &fs) < 0) {
+		warn("statvfs '%s':", path);
+		return NULL;
+	}
+
+	return fmt_human(buf, fs.f_frsize * fs.f_bavail, 1024);
+}
+
+const char *
+disk_perc(const char *path)
+{
+	static _Thread_local char buf[1024];
+	struct statvfs fs;
+
+	if (statvfs(path, &fs) < 0) {
+		warn("statvfs '%s':", path);
+		return NULL;
+	}
+
+	return bprintf(buf, "%d", (int)(100 *
+	               (1 - ((double)fs.f_bavail / (double)fs.f_blocks))));
+}
+
+const char *
+disk_total(const char *path)
+{
+	static _Thread_local char buf[1024];
+	struct statvfs fs;
+
+	if (statvfs(path, &fs) < 0) {
+		warn("statvfs '%s':", path);
+		return NULL;
+	}
+
+	return fmt_human(buf, fs.f_frsize * fs.f_blocks, 1024);
+}
+
+const char *
+disk_used(const char *path)
+{
+	static _Thread_local char buf[1024];
+	struct statvfs fs;
+
+	if (statvfs(path, &fs) < 0) {
+		warn("statvfs '%s':", path);
+		return NULL;
+	}
+
+	return fmt_human(buf, fs.f_frsize * (fs.f_blocks - fs.f_bfree), 1024);
+}
diff --git a/patches/slstatus/components/ram.c b/patches/slstatus/components/ram.c
new file mode 100644
index 0000000..4fe2752
--- /dev/null
+++ b/patches/slstatus/components/ram.c
@@ -0,0 +1,220 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+
+#include "../util.h"
+
+#if defined(__linux__)
+	#include <stdint.h>
+
+	const char *
+	ram_free(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t free;
+
+		if (pscanf(buf, "/proc/meminfo",
+		           "MemTotal: %ju kB\n"
+		           "MemFree: %ju kB\n"
+		           "MemAvailable: %ju kB\n",
+		           &free, &free, &free) != 3)
+			return NULL;
+
+		return fmt_human(buf, free * 1024, 1024);
+	}
+
+	const char *
+	ram_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t total, free, buffers, cached;
+		int percent;
+
+		if (pscanf(buf, "/proc/meminfo",
+		           "MemTotal: %ju kB\n"
+		           "MemFree: %ju kB\n"
+		           "MemAvailable: %ju kB\n"
+		           "Buffers: %ju kB\n"
+		           "Cached: %ju kB\n",
+		           &total, &free, &buffers, &buffers, &cached) != 5)
+			return NULL;
+
+		if (total == 0)
+			return NULL;
+
+		percent = 100 * ((total - free) - (buffers + cached)) / total;
+		return bprintf(buf, "%d", percent);
+	}
+
+	const char *
+	ram_total(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t total;
+
+		if (pscanf(buf, "/proc/meminfo", "MemTotal: %ju kB\n", &total)
+		    != 1)
+			return NULL;
+
+		return fmt_human(buf, total * 1024, 1024);
+	}
+
+	const char *
+	ram_used(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t total, free, buffers, cached, used;
+
+		if (pscanf(buf, "/proc/meminfo",
+		           "MemTotal: %ju kB\n"
+		           "MemFree: %ju kB\n"
+		           "MemAvailable: %ju kB\n"
+		           "Buffers: %ju kB\n"
+		           "Cached: %ju kB\n",
+		           &total, &free, &buffers, &buffers, &cached) != 5)
+			return NULL;
+
+		used = (total - free - buffers - cached);
+		return fmt_human(buf, used * 1024, 1024);
+	}
+#elif defined(__OpenBSD__)
+	#include <stdlib.h>
+	#include <sys/sysctl.h>
+	#include <sys/types.h>
+	#include <unistd.h>
+
+	#define LOG1024 10
+	#define pagetok(size, pageshift) (size_t)(size << (pageshift - LOG1024))
+
+	inline int
+	load_uvmexp(struct uvmexp *uvmexp)
+	{
+	static _Thread_local char buf[1024];
+		int uvmexp_mib[] = {CTL_VM, VM_UVMEXP};
+		size_t size;
+
+		size = sizeof(*uvmexp);
+
+		if (sysctl(uvmexp_mib, 2, uvmexp, &size, NULL, 0) >= 0)
+			return 1;
+
+		return 0;
+	}
+
+	const char *
+	ram_free(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct uvmexp uvmexp;
+		int free_pages;
+
+		if (!load_uvmexp(&uvmexp))
+			return NULL;
+
+		free_pages = uvmexp.npages - uvmexp.active;
+		return fmt_human(buf, pagetok(free_pages, uvmexp.pageshift) *
+				 1024, 1024);
+	}
+
+	const char *
+	ram_perc(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct uvmexp uvmexp;
+		int percent;
+
+		if (!load_uvmexp(&uvmexp))
+			return NULL;
+
+		percent = uvmexp.active * 100 / uvmexp.npages;
+		return bprintf(buf, "%d", percent);
+	}
+
+	const char *
+	ram_total(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct uvmexp uvmexp;
+
+		if (!load_uvmexp(&uvmexp))
+			return NULL;
+
+		return fmt_human(buf, pagetok(uvmexp.npages,
+					 uvmexp.pageshift) * 1024, 1024);
+	}
+
+	const char *
+	ram_used(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		struct uvmexp uvmexp;
+
+		if (!load_uvmexp(&uvmexp))
+			return NULL;
+
+		return fmt_human(buf, pagetok(uvmexp.active,
+					 uvmexp.pageshift) * 1024, 1024);
+	}
+#elif defined(__FreeBSD__)
+	#include <sys/sysctl.h>
+	#include <sys/vmmeter.h>
+	#include <unistd.h>
+	#include <vm/vm_param.h>
+
+	const char *
+	ram_free(const char *unused) {
+		struct vmtotal vm_stats;
+		int mib[] = {CTL_VM, VM_TOTAL};
+		size_t len;
+
+		len = sizeof(struct vmtotal);
+		if (sysctl(mib, 2, &vm_stats, &len, NULL, 0) < 0
+		    || !len)
+			return NULL;
+
+		return fmt_human(buf, vm_stats.t_free * getpagesize(), 1024);
+	}
+
+	const char *
+	ram_total(const char *unused) {
+		unsigned int npages;
+		size_t len;
+
+		len = sizeof(npages);
+		if (sysctlbyname("vm.stats.vm.v_page_count",
+		                 &npages, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		return fmt_human(buf, npages * getpagesize(), 1024);
+	}
+
+	const char *
+	ram_perc(const char *unused) {
+		unsigned int npages;
+		unsigned int active;
+		size_t len;
+
+		len = sizeof(npages);
+		if (sysctlbyname("vm.stats.vm.v_page_count",
+		                 &npages, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		if (sysctlbyname("vm.stats.vm.v_active_count",
+		                 &active, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		return bprintf(buf, "%d", active * 100 / npages);
+	}
+
+	const char *
+	ram_used(const char *unused) {
+		unsigned int active;
+		size_t len;
+
+		len = sizeof(active);
+		if (sysctlbyname("vm.stats.vm.v_active_count",
+		                 &active, &len, NULL, 0) < 0 || !len)
+			return NULL;
+
+		return fmt_human(buf, active * getpagesize(), 1024);
+	}
+#endif
diff --git a/patches/slstatus/components/run_command.c b/patches/slstatus/components/run_command.c
new file mode 100644
index 0000000..b9fc3a2
--- /dev/null
+++ b/patches/slstatus/components/run_command.c
@@ -0,0 +1,29 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <string.h>
+
+const char *
+run_command(const char *cmd)
+{
+	static _Thread_local char buf[1024];
+	char *p;
+	FILE *fp;
+
+	if (!(fp = popen(cmd, "r"))) {
+		fprintf(stderr,"error '%s':", cmd);
+		return "";
+	}
+
+	p = fgets(buf, sizeof(buf) - 1, fp);
+	if (pclose(fp) < 0) {
+		fprintf(stderr,"pclose '%s':", cmd);
+		return "";
+	}
+	if (!p)
+		return "";
+
+	if ((p = strrchr(buf, '\n')))
+		p[0] = '\0';
+
+	return buf[0] ? buf : "";
+}
diff --git a/patches/slstatus/components/temperature.c b/patches/slstatus/components/temperature.c
new file mode 100644
index 0000000..9d9e45d
--- /dev/null
+++ b/patches/slstatus/components/temperature.c
@@ -0,0 +1,75 @@
+/* See LICENSE file for copyright and license details. */
+#include <stddef.h>
+
+#include "../util.h"
+
+
+#if defined(__linux__)
+	#include <stdint.h>
+
+	const char *
+	temp(const char *file)
+	{
+	static _Thread_local char buf[1024];
+		uintmax_t temp;
+
+		if (pscanf(buf, file, "%ju", &temp) != 1)
+			return NULL;
+
+		return bprintf(buf, "%ju", temp / 1000);
+	}
+#elif defined(__OpenBSD__)
+	#include <stdio.h>
+	#include <sys/time.h> /* before <sys/sensors.h> for struct timeval */
+	#include <sys/sensors.h>
+	#include <sys/sysctl.h>
+
+	const char *
+	temp(const char *unused)
+	{
+	static _Thread_local char buf[1024];
+		int mib[5];
+		size_t size;
+		struct sensor temp;
+
+		mib[0] = CTL_HW;
+		mib[1] = HW_SENSORS;
+		mib[2] = 0; /* cpu0 */
+		mib[3] = SENSOR_TEMP;
+		mib[4] = 0; /* temp0 */
+
+		size = sizeof(temp);
+
+		if (sysctl(mib, 5, &temp, &size, NULL, 0) < 0) {
+			warn("sysctl 'SENSOR_TEMP':");
+			return NULL;
+		}
+
+		/* kelvin to celsius */
+		return bprintf(buf, "%d", (int)((float)(temp.value-273150000) / 1E6));
+	}
+#elif defined(__FreeBSD__)
+	#include <stdio.h>
+	#include <stdlib.h>
+	#include <sys/sysctl.h>
+
+	#define ACPI_TEMP "hw.acpi.thermal.%s.temperature"
+
+	const char *
+	temp(const char *zone)
+	{
+	static _Thread_local char buf[1024];
+		char buf[256];
+		int temp;
+		size_t len;
+
+		len = sizeof(temp);
+		snprintf(buf, sizeof(buf), ACPI_TEMP, zone);
+		if (sysctlbyname(buf, &temp, &len, NULL, 0) < 0
+				|| !len)
+			return NULL;
+
+		/* kelvin to decimal celcius */
+		return bprintf(buf, "%d.%d", (temp - 2731) / 10, abs((temp - 2731) % 10));
+	}
+#endif
diff --git a/patches/slstatus/components/util.c b/patches/slstatus/components/util.c
new file mode 100644
index 0000000..9524d85
--- /dev/null
+++ b/patches/slstatus/components/util.c
@@ -0,0 +1,146 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../util.h"
+
+char *argv0;
+
+static void
+verr(const char *fmt, va_list ap)
+{
+	vfprintf(stderr, fmt, ap);
+
+	if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
+		fputc(' ', stderr);
+		perror(NULL);
+	} else {
+		fputc('\n', stderr);
+	}
+}
+
+void
+warn(const char *fmt, ...)
+{
+	
+	va_list ap;
+
+	va_start(ap, fmt);
+	verr(fmt, ap);
+	va_end(ap);
+}
+
+void
+die(const char *fmt, ...)
+{
+	
+	va_list ap;
+
+	va_start(ap, fmt);
+	verr(fmt, ap);
+	va_end(ap);
+
+	exit(1);
+}
+
+static int
+evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
+{
+	
+	int ret;
+
+	ret = vsnprintf(str, size, fmt, ap);
+
+	if (ret < 0) {
+		warn("vsnprintf:");
+		return -1;
+	} else if ((size_t)ret >= size) {
+		warn("vsnprintf: Output truncated");
+		return -1;
+	}
+
+	return ret;
+}
+
+int 
+esnprintf(const char *buf, char *str, size_t size, const char *fmt, ...)
+{
+	
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	ret = evsnprintf(str, size, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+char *
+bprintf(const char *buf, const char *fmt, ...)
+{
+    va_list ap;
+    int ret;
+
+    va_start(ap, fmt);
+    ret = evsnprintf(buf, sizeof(buf), fmt, ap);
+    va_end(ap);
+
+    return (ret < 0) ? NULL : buf;
+}
+
+const char *
+fmt_human(const char *buf, uintmax_t num, int base)
+{
+	
+	double scaled;
+	size_t i, prefixlen;
+	const char **prefix;
+	const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z",
+	                              "Y" };
+	const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei",
+	                              "Zi", "Yi" };
+
+	switch (base) {
+	case 1000:
+		prefix = prefix_1000;
+		prefixlen = LEN(prefix_1000);
+		break;
+	case 1024:
+		prefix = prefix_1024;
+		prefixlen = LEN(prefix_1024);
+		break;
+	default:
+		warn("fmt_human: Invalid base");
+		return NULL;
+	}
+
+	scaled = num;
+	for (i = 0; i < prefixlen && scaled >= base; i++)
+		scaled /= base;
+
+	return bprintf(buf, "%.1f %s", scaled, prefix[i]);
+}
+
+int
+pscanf(const char *buf, const char *path, const char *fmt, ...)
+{
+	
+	FILE *fp;
+	va_list ap;
+	int n;
+
+	if (!(fp = fopen(path, "r"))) {
+		warn("fopen '%s':", path);
+		return -1;
+	}
+	va_start(ap, fmt);
+	n = vfscanf(fp, fmt, ap);
+	va_end(ap);
+	fclose(fp);
+
+	return (n == EOF) ? -1 : n;
+}
+
diff --git a/patches/slstatus/components/wifi.c b/patches/slstatus/components/wifi.c
new file mode 100644
index 0000000..5808175
--- /dev/null
+++ b/patches/slstatus/components/wifi.c
@@ -0,0 +1,275 @@
+/* See LICENSE file for copyright and license details. */
+#include <ifaddrs.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "../util.h"
+
+#define RSSI_TO_PERC(rssi) \
+			rssi >= -50 ? 100 : \
+			(rssi <= -100 ? 0 : \
+			(2 * (rssi + 100)))
+
+#if defined(__linux__)
+	#include <limits.h>
+	#include <linux/wireless.h>
+
+	#define NET_OPERSTATE "/sys/class/net/%s/operstate"
+
+	const char *
+	wifi_perc(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		int cur;
+		size_t i;
+		char *p, *datastart;
+		char path[PATH_MAX];
+		char status[5];
+		FILE *fp;
+
+		if (esnprintf(buf, path, sizeof(path), NET_OPERSTATE, interface) < 0)
+			return NULL;
+		if (!(fp = fopen(path, "r"))) {
+			warn("fopen '%s':", path);
+			return NULL;
+		}
+		p = fgets(status, 5, fp);
+		fclose(fp);
+		if (!p || strcmp(status, "up\n") != 0)
+			return NULL;
+
+		if (!(fp = fopen("/proc/net/wireless", "r"))) {
+			warn("fopen '/proc/net/wireless':");
+			return NULL;
+		}
+
+		for (i = 0; i < 3; i++)
+			if (!(p = fgets(buf, sizeof(buf) - 1, fp)))
+				break;
+
+		fclose(fp);
+		if (i < 2 || !p)
+			return NULL;
+
+		if (!(datastart = strstr(buf, interface)))
+			return NULL;
+
+		datastart = (datastart+(strlen(interface)+1));
+		sscanf(datastart + 1, " %*d   %d  %*d  %*d\t\t  %*d\t   "
+		       "%*d\t\t%*d\t\t %*d\t  %*d\t\t %*d", &cur);
+
+		/* 70 is the max of /proc/net/wireless */
+		return bprintf(buf, "%d", (int)((float)cur / 70 * 100));
+	}
+
+	const char *
+	wifi_essid(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		static char id[IW_ESSID_MAX_SIZE+1];
+		int sockfd;
+		struct iwreq wreq;
+
+		memset(&wreq, 0, sizeof(struct iwreq));
+		wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
+		if (esnprintf(buf, wreq.ifr_name, sizeof(wreq.ifr_name), "%s",
+		              interface) < 0)
+			return NULL;
+
+		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+			warn("socket 'AF_INET':");
+			return NULL;
+		}
+		wreq.u.essid.pointer = id;
+		if (ioctl(sockfd,SIOCGIWESSID, &wreq) < 0) {
+			warn("ioctl 'SIOCGIWESSID':");
+			close(sockfd);
+			return NULL;
+		}
+
+		close(sockfd);
+
+		if (!strcmp(id, ""))
+			return NULL;
+
+		return id;
+	}
+#elif defined(__OpenBSD__)
+	#include <net/if.h>
+	#include <net/if_media.h>
+	#include <net80211/ieee80211.h>
+	#include <sys/select.h> /* before <sys/ieee80211_ioctl.h> for NBBY */
+	#include <net80211/ieee80211_ioctl.h>
+	#include <stdlib.h>
+	#include <sys/types.h>
+
+	static int
+	load_ieee80211_nodereq(const char *interface, struct ieee80211_nodereq *nr)
+	{
+	static _Thread_local char buf[1024];
+		struct ieee80211_bssid bssid;
+		int sockfd;
+		uint8_t zero_bssid[IEEE80211_ADDR_LEN];
+
+		memset(&bssid, 0, sizeof(bssid));
+		memset(nr, 0, sizeof(struct ieee80211_nodereq));
+		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+			warn("socket 'AF_INET':");
+			return 0;
+		}
+		strlcpy(bssid.i_name, interface, sizeof(bssid.i_name));
+		if ((ioctl(sockfd, SIOCG80211BSSID, &bssid)) < 0) {
+			warn("ioctl 'SIOCG80211BSSID':");
+			close(sockfd);
+			return 0;
+		}
+		memset(&zero_bssid, 0, sizeof(zero_bssid));
+		if (memcmp(bssid.i_bssid, zero_bssid,
+		    IEEE80211_ADDR_LEN) == 0) {
+			close(sockfd);
+			return 0;
+		}
+		strlcpy(nr->nr_ifname, interface, sizeof(nr->nr_ifname));
+		memcpy(&nr->nr_macaddr, bssid.i_bssid, sizeof(nr->nr_macaddr));
+		if ((ioctl(sockfd, SIOCG80211NODE, nr)) < 0 && nr->nr_rssi) {
+			warn("ioctl 'SIOCG80211NODE':");
+			close(sockfd);
+			return 0;
+		}
+
+		return close(sockfd), 1;
+	}
+
+	const char *
+	wifi_perc(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		struct ieee80211_nodereq nr;
+		int q;
+
+		if (load_ieee80211_nodereq(interface, &nr)) {
+			if (nr.nr_max_rssi)
+				q = IEEE80211_NODEREQ_RSSI(&nr);
+			else
+				q = RSSI_TO_PERC(nr.nr_rssi);
+
+			return bprintf(buf, "%d", q);
+		}
+
+		return NULL;
+	}
+
+	const char *
+	wifi_essid(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		struct ieee80211_nodereq nr;
+
+		if (load_ieee80211_nodereq(interface, &nr))
+			return bprintf(buf, "%s", nr.nr_nwid);
+
+		return NULL;
+	}
+#elif defined(__FreeBSD__)
+	#include <net/if.h>
+	#include <net80211/ieee80211_ioctl.h>
+
+	int
+	load_ieee80211req(int sock, const char *interface, void *data, int type, size_t *len)
+	{
+	static _Thread_local char buf[1024];
+		char warn_buf[256];
+		struct ieee80211req ireq;
+		memset(&ireq, 0, sizeof(ireq));
+		ireq.i_type = type;
+		ireq.i_data = (caddr_t) data;
+		ireq.i_len = *len;
+
+		strlcpy(ireq.i_name, interface, sizeof(ireq.i_name));
+		if (ioctl(sock, SIOCG80211, &ireq) < 0) {
+			snprintf(warn_buf,  sizeof(warn_buf),
+					"ioctl: 'SIOCG80211': %d", type);
+			warn(warn_buf);
+			return 0;
+		}
+
+		*len = ireq.i_len;
+		return 1;
+	}
+
+	const char *
+	wifi_perc(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		union {
+			struct ieee80211req_sta_req sta;
+			uint8_t buf[24 * 1024];
+		} info;
+		uint8_t bssid[IEEE80211_ADDR_LEN];
+		int rssi_dbm;
+		int sockfd;
+		size_t len;
+		const char *fmt;
+
+		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+			warn("socket 'AF_INET':");
+			return NULL;
+		}
+
+		/* Retreive MAC address of interface */
+		len = IEEE80211_ADDR_LEN;
+		fmt = NULL;
+		if (load_ieee80211req(sockfd, interface, &bssid, IEEE80211_IOC_BSSID, &len))
+		{
+	static _Thread_local char buf[1024];
+			/* Retrieve info on station with above BSSID */
+			memset(&info, 0, sizeof(info));
+			memcpy(info.sta.is_u.macaddr, bssid, sizeof(bssid));
+
+			len = sizeof(info);
+			if (load_ieee80211req(sockfd, interface, &info, IEEE80211_IOC_STA_INFO, &len)) {
+				rssi_dbm = info.sta.info[0].isi_noise +
+ 					         info.sta.info[0].isi_rssi / 2;
+
+				fmt = bprintf(buf, "%d", RSSI_TO_PERC(rssi_dbm));
+			}
+		}
+
+		close(sockfd);
+		return fmt;
+	}
+
+	const char *
+	wifi_essid(const char *interface)
+	{
+	static _Thread_local char buf[1024];
+		char ssid[IEEE80211_NWID_LEN + 1];
+		size_t len;
+		int sockfd;
+		const char *fmt;
+
+		if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+			warn("socket 'AF_INET':");
+			return NULL;
+		}
+
+		fmt = NULL;
+		len = sizeof(ssid);
+		memset(&ssid, 0, len);
+		if (load_ieee80211req(sockfd, interface, &ssid, IEEE80211_IOC_SSID, &len)) {
+			if (len < sizeof(ssid))
+				len += 1;
+			else
+				len = sizeof(ssid);
+
+			ssid[len - 1] = '\0';
+			fmt = bprintf(buf, "%s", ssid);
+		}
+
+		close(sockfd);
+		return fmt;
+	}
+#endif
diff --git a/patches/slstatus/slstatus.patch b/patches/slstatus/slstatus.patch
new file mode 100644
index 0000000..4c34c1c
--- /dev/null
+++ b/patches/slstatus/slstatus.patch
@@ -0,0 +1,415 @@
+diff --git a/Makefile b/Makefile
+index 33a1ec7..31660a3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,8 +1,10 @@
+-compile:
+-	cc -o sta main.c
++config.h:
++	cp config.def.h config.h
++compile: config.h
++	cc -o sta main.c ./components/* -pthread
+ 
+ install: compile
+ 	cp sta /usr/local/bin
+ 
+ uninstall:
+-	rm /usr/local/bin/sta
++	rm -f /usr/local/bin/sta
+diff --git a/config.def.h b/config.def.h
+new file mode 100644
+index 0000000..d8165c3
+--- /dev/null
++++ b/config.def.h
+@@ -0,0 +1,60 @@
++/*
++ * function            description                     argument (example)
++ *
++ * battery_perc        battery percentage              battery name (BAT0)
++ *                                                     NULL on OpenBSD/FreeBSD
++ * battery_remaining   battery remaining HH:MM         battery name (BAT0)
++ *                                                     NULL on OpenBSD/FreeBSD
++ * battery_state       battery charging state          battery name (BAT0)
++ *                                                     NULL on OpenBSD/FreeBSD
++ * cat                 read arbitrary file             path
++ * cpu_freq            cpu frequency in MHz            NULL
++ * cpu_perc            cpu usage in percent            NULL
++ * datetime            date and time                   format string (%F %T)
++ * disk_free           free disk space in GB           mountpoint path (/)
++ * disk_perc           disk usage in percent           mountpoint path (/)
++ * disk_total          total disk space in GB          mountpoint path (/)
++ * disk_used           used disk space in GB           mountpoint path (/)
++ * entropy             available entropy               NULL
++ * gid                 GID of current user             NULL
++ * hostname            hostname                        NULL
++ * ipv4                IPv4 address                    interface name (eth0)
++ * ipv6                IPv6 address                    interface name (eth0)
++ * kernel_release      `uname -r`                      NULL
++ * keyboard_indicators caps/num lock indicators        format string (c?n?)
++ *                                                     see keyboard_indicators.c
++ * keymap              layout (variant) of current     NULL
++ *                     keymap
++ * load_avg            load average                    NULL
++ * netspeed_rx         receive network speed           interface name (wlan0)
++ * netspeed_tx         transfer network speed          interface name (wlan0)
++ * num_files           number of files in a directory  path
++ *                                                     (/home/foo/Inbox/cur)
++ * ram_free            free memory in GB               NULL
++ * ram_perc            memory usage in percent         NULL
++ * ram_total           total memory size in GB         NULL
++ * ram_used            used memory in GB               NULL
++ * run_command         custom shell command            command (echo foo)
++ * swap_free           free swap in GB                 NULL
++ * swap_perc           swap usage in percent           NULL
++ * swap_total          total swap size in GB           NULL
++ * swap_used           used swap in GB                 NULL
++ * temp                temperature in degree celsius   sensor file
++ *                                                     (/sys/class/thermal/...)
++ *                                                     NULL on OpenBSD
++ *                                                     thermal zone on FreeBSD
++ *                                                     (tz0, tz1, etc.)
++ * uid                 UID of current user             NULL
++ * uptime              system uptime                   NULL
++ * username            username of current user        NULL
++ * vol_perc            OSS/ALSA volume in percent      mixer file (/dev/mixer)
++ *                                                     NULL on OpenBSD/FreeBSD
++ * wifi_essid          WiFi ESSID                      interface name (wlan0)
++ * wifi_perc           WiFi signal in percent          interface name (wlan0)
++ */
++
++static const Args commands[] = {
++	/* function  format  argument         id  delay(ms) */
++	{run_command, "%s", "date +%H:%M:%S", 1, 1000},
++
++};
+diff --git a/main.c b/main.c
+index 9a74044..289705e 100644
+--- a/main.c
++++ b/main.c
+@@ -1,15 +1,29 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/socket.h>
+-#include <stdarg.h>
+ #include <sys/un.h>
+ #include <unistd.h>
++#include <pthread.h>
+ #include <string.h>
+ #include <signal.h>
+ #include <errno.h>
+ 
+ #define SOCKET_PATH "/tmp/sta"
+ 
++typedef struct{
++	const char *(*func)(const char *);
++	char *fmt;
++	char *parm;
++	int id;
++	int delay;
++}Args;
++
++
++#include "util.h"
++#include "config.h"
++
++pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER;
++
+ typedef struct {
+     int id;
+     char *name;
+@@ -20,14 +34,10 @@ typedef struct {
+     int count;
+ } Pros;
+ 
+-void error(char *t,char *m,...){
+-    va_list args;
+-    va_start(args,m);
+-    fprintf(stderr, "\033[1;31m[E]\033[0m \033[1;33m%s\033[0m:", t);
+-    vfprintf(stderr, m,args);
+-    fprintf(stderr, "\n");
+-    va_end(args);
+-}
++typedef struct {
++    int id2;
++	Pros *list;
++}Potato;
+ 
+ Pros *init(){
+     Pros *list = malloc(sizeof(Pros));
+@@ -48,21 +58,32 @@ void add_pro(Pros *list,int id,char *name){
+ 
+     list->count++;
+     list->process = realloc(list->process, sizeof(Pro) * list->count);
+-    if (!list->process) error("Memory","memory allocation failed.");
++    if (!list->process) {
++		warn("Memory","memory allocation failed.");
++		exit(1);
++	}
+     list->process[list->count -1].name = strdup(name);
+     list->process[list->count -1].id = id;
+ }
+-
+ void show_pros(Pros *list)
+ {
++    for(int i = 0; i < list->count - 1; i++){
++        for(int j = i + 1; j < list->count; j++){
++            if(list->process[i].id > list->process[j].id){
++                Pro temp = list->process[i];
++                list->process[i] = list->process[j];
++                list->process[j] = temp;
++            }
++        }
++    }
+     for(int a = 0; a<list->count;++a){
+         printf("%s",list->process[a].name);
+     }
+-	printf("\n");
++    printf("\n");
+     fflush(stdout);
+ }
+ 
+-void show_help()
++void usage()
+ {
+ 	printf("Usage:\n");
+ 	printf("\t-id        <number>       => process id (id >= 1)\n");
+@@ -72,26 +93,36 @@ void show_help()
+ 	exit(1);
+ }
+ 
+-void args(int *id,const char **name,int argc, char const* argv[])
++void args(int *id,int argc, char const* argv[])
+ {
+ 	for (int i = 1; i < argc; i += 2) {
+ 		if (!strcmp("-h", argv[i]) ||!strcmp("-help", argv[i])) 
+-			show_help();
+-
+-		if (i + 1 >= argc || argv[i+1][0] == '-') 
+-			error("Args", "missing value for %s\nrun: sta -h", argv[i]);
++			usage();
+ 
+ 		if (!strcmp("-id", argv[i])) 
+ 			*id = atoi(argv[i + 1]);
++	}
+ 
+-		else if (!strcmp("-name", argv[i])) 
+-			*name = argv[i + 1];
++	if (*id <= 0) 
++		usage();
+ 
+-	}
++}
+ 
+-	if (*id <= 0 || !*name) 
+-		show_help();
++char *temp_spf(const char *cmd,char *fmt)
++{
++	char *buf = malloc(512);
++	sprintf(buf, fmt,cmd);
++	return buf;
++}
+ 
++void append(Args *command,Pros *list)
++{
++		const char *cmd = command->func(command->parm);
++		if (!cmd) cmd = strdup("N/A");
++		char *tmp =temp_spf(cmd,command->fmt);
++		add_pro(list, command->id, tmp);
++		free(tmp);
++		show_pros(list);
+ }
+ 
+ void clean_up(){
+@@ -99,6 +130,19 @@ void clean_up(){
+     exit(0);
+ }
+ 
++void *worker(void* arg){
++	Potato* data = arg;
++	Args command = commands[data->id2];
++	while (1){
++		pthread_mutex_lock(&list_mutex);
++		append(&command, data->list);
++		pthread_mutex_unlock(&list_mutex);
++
++		usleep(command.delay * 1000);
++	};
++}
++
++
+ int main(int argc, char const* argv[]){
+ 
+     struct sockaddr_un addr;
+@@ -106,19 +150,26 @@ int main(int argc, char const* argv[]){
+     addr.sun_family = AF_UNIX;
+     strcpy(addr.sun_path, SOCKET_PATH);
+     int sock = socket(AF_UNIX, SOCK_STREAM , 0);
+-    if (sock < 0) error("Socket","failed to create socket: %s", strerror(errno));
++    if (sock < 0) warn("Socket","failed to create socket: %s", strerror(errno));
+ 
+     Pros *list = init();
+ 
+     if (access(SOCKET_PATH, F_OK) == 0) {
+ 		int id;
+-		const char *name;
+ 		char buf[256];
+-		args(&id, &name,argc, argv);
+-		snprintf(buf,sizeof(buf),"%d|+|%s",id,name);
++		args(&id,argc, argv);
++		for (int i = 0;i<sizeof(commands)/sizeof(commands[0]);++i){
++			if (id == commands[i].id){
++				const char *cmd = commands[i].func(commands[i].parm);
++				if (!cmd) cmd = strdup("N/A");
++				char *tmp = temp_spf(cmd,commands[i].fmt);
++				snprintf(buf,sizeof(buf),"%d|+|%s",id,tmp);
++				free(tmp);
++			}
++		}
+ 
+         if (connect(sock, (struct sockaddr*)&addr , sizeof(addr)) < 0)
+-            error("Connect","failed: %s", strerror(errno));
++            warn("Connect","failed: %s", strerror(errno));
+ 
+         write(sock, buf, strlen(buf));
+         close(sock);
+@@ -126,13 +177,28 @@ int main(int argc, char const* argv[]){
+     } else {
+         signal(SIGTERM, clean_up);
+         signal(SIGINT, clean_up);
++		unlink(SOCKET_PATH);
++
++		int cmds = sizeof(commands)/sizeof(commands[0]);
++
++		pthread_t tids[cmds];
++		for (int i = 0; i<cmds;++i){
++			if(commands[i].delay){
++				Potato *info = malloc(sizeof(Potato));
++				info->list = list;
++				info->id2 =i;
++				pthread_create(&tids[i], NULL,worker,info);
++
++			}else{
++				append(&commands[i], list);
++			}
++		}
+ 
+-        unlink(SOCKET_PATH);
+         if (bind(sock, (struct sockaddr*)&addr , sizeof(addr)) < 0)
+-            error("Bind","failed: %s", strerror(errno));
++            warn("Bind","failed: %s", strerror(errno));
+ 
+         if (listen(sock, 5) < 0)
+-            error("Listen","failed: %s", strerror(errno));
++            warn("Listen","failed: %s", strerror(errno));
+ 
+         while (1) {
+             int client = accept(sock, NULL, NULL);
+diff --git a/sta b/sta
+new file mode 100755
+index 0000000..6b91afc
+Binary files /dev/null and b/sta differ
+diff --git a/util.h b/util.h
+new file mode 100644
+index 0000000..b26f07d
+--- /dev/null
++++ b/util.h
+@@ -0,0 +1,99 @@
++#include <stdint.h>
++
++
++/* battery */
++const char *battery_perc(const char *);
++const char *battery_remaining(const char *);
++const char *battery_state(const char *);
++
++/* cat */
++const char *cat(const char *path);
++
++/* cpu */
++const char *cpu_freq(const char *unused);
++const char *cpu_perc(const char *unused);
++
++/* datetime */
++const char *datetime(const char *fmt);
++
++/* disk */
++const char *disk_free(const char *path);
++const char *disk_perc(const char *path);
++const char *disk_total(const char *path);
++const char *disk_used(const char *path);
++
++/* entropy */
++const char *entropy(const char *unused);
++
++/* hostname */
++const char *hostname(const char *unused);
++
++/* ip */
++const char *ipv4(const char *interface);
++const char *ipv6(const char *interface);
++
++/* kernel_release */
++const char *kernel_release(const char *unused);
++
++/* keyboard_indicators */
++const char *keyboard_indicators(const char *fmt);
++
++/* keymap */
++const char *keymap(const char *unused);
++
++/* load_avg */
++const char *load_avg(const char *unused);
++
++/* netspeeds */
++const char *netspeed_rx(const char *interface);
++const char *netspeed_tx(const char *interface);
++
++/* num_files */
++const char *num_files(const char *path);
++
++/* ram */
++const char *ram_free(const char *unused);
++const char *ram_perc(const char *unused);
++const char *ram_total(const char *unused);
++const char *ram_used(const char *unused);
++
++/* run_command */
++const char *run_command(const char *cmd);
++
++/* swap */
++const char *swap_free(const char *unused);
++const char *swap_perc(const char *unused);
++const char *swap_total(const char *unused);
++const char *swap_used(const char *unused);
++
++/* temperature */
++const char *temp(const char *);
++
++/* uptime */
++const char *uptime(const char *unused);
++
++/* user */
++const char *gid(const char *unused);
++const char *uid(const char *unused);
++const char *username(const char *unused);
++
++/* volume */
++const char *vol_perc(const char *card);
++
++/* wifi */
++const char *wifi_essid(const char *interface);
++const char *wifi_perc(const char *interface);
++
++/* settings */
++#define LEN(x) (sizeof(x) / sizeof((x)[0]))
++
++extern char *argv0;
++
++void warn(const char *, ...);
++void die(const char *, ...);
++
++int esnprintf(const char *buf, char *str, size_t size, const char *fmt, ...);
++char *bprintf(const char *buf, const char *fmt, ...);
++const char *fmt_human(const char *buf, uintmax_t num, int base);
++int pscanf(const char *buf, const char *path, const char *fmt, ...);
++

// Created by Pi66

// Copyright ©Pi66 2026