commit 0ef1c734c3aae443797691b268cf10a9d5d85ea1
Author: amrfti <andrew@kloet.net>
Date: Thu, 10 Jul 2025 10:12:18 -0400
initial commit
Diffstat:
8 files changed, 220 insertions(+), 0 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2025 Andrew Kloet <andrew@kloet.net>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
@@ -0,0 +1,32 @@
+CC = cc
+CFLAGS = -Wall -Wextra -O3
+CURL_LIBS = -lcurl
+
+SOURCES = sb-cpu.c sb-date.c sb-memory.c sb-time.c sb-weather.c
+
+EXECUTABLES = $(SOURCES:.c=)
+
+all: $(EXECUTABLES)
+
+sb-weather: sb-weather.c
+ $(CC) $(CFLAGS) $< -o $@ $(CURL_LIBS)
+
+sb-cpu: sb-cpu.c
+ $(CC) $(CFLAGS) $< -o $@
+
+sb-date: sb-date.c
+ $(CC) $(CFLAGS) $< -o $@
+
+sb-memory: sb-memory.c
+ $(CC) $(CFLAGS) $< -o $@
+
+sb-time: sb-time.c
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm -f $(EXECUTABLES)
+
+install: all
+ cp $(EXECUTABLES) /usr/local/bin
+
+.PHONY: all clean
diff --git a/README b/README
@@ -0,0 +1,15 @@
+Tiny programs for Linux which print useful info. Suited for piping into other programs which handle window manager statusbar, like Suckless' DWM.
+Compile with `make`. Install with `make install`.
+
+```
+$ ./sb-cpu
+CPU: 2%
+$ ./sb-memory
+Mem: 34%
+$ ./sb-weather glasgow
+27°C Overcast
+$ ./sb-time
+10:10am
+$ ./sb-date
+Jul 10 2025
+```
diff --git a/sb-cpu.c b/sb-cpu.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <unistd.h>
+
+typedef struct {
+ long long idle;
+ long long total;
+} cpu_stats_t;
+
+static int read_cpu_stats(cpu_stats_t *stats) {
+ FILE *fp = fopen("/proc/stat", "r");
+ if (!fp)
+ return 1;
+
+ long long user, nice, system, idle, iowait, irq, softirq;
+ int ret = fscanf(fp, "cpu %lld %lld %lld %lld %lld %lld %lld", &user, &nice,
+ &system, &idle, &iowait, &irq, &softirq);
+ fclose(fp);
+
+ if (ret != 7)
+ return 1;
+
+ stats->idle = idle + iowait;
+ stats->total = user + nice + system + idle + iowait + irq + softirq;
+ return 0;
+}
+
+static double calculate_usage(cpu_stats_t *prev, cpu_stats_t *curr) {
+ long long diff_total = curr->total - prev->total;
+ long long diff_idle = curr->idle - prev->idle;
+
+ if (diff_total == 0)
+ return 0.0;
+ return 100.0 * (diff_total - diff_idle) / diff_total;
+}
+
+int main() {
+ cpu_stats_t prev, curr;
+
+ if (read_cpu_stats(&prev) < 0) {
+ fprintf(stderr, "Error reading CPU stats\n");
+ return 1;
+ }
+
+ sleep(1);
+
+ if (read_cpu_stats(&curr) < 0) {
+ fprintf(stderr, "Error reading CPU stats\n");
+ return 1;
+ }
+
+ printf("CPU: %.0f%%\n", calculate_usage(&prev, &curr));
+ return 0;
+}
diff --git a/sb-date.c b/sb-date.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <time.h>
+
+int main() {
+ time_t t = time(NULL);
+ struct tm tm = *localtime(&t);
+
+ const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ printf("%s %02d %d\n", months[tm.tm_mon], tm.tm_mday, tm.tm_year + 1900);
+
+ return 0;
+}
diff --git a/sb-memory.c b/sb-memory.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+int main() {
+ FILE *fp = fopen("/proc/meminfo", "r");
+ if (!fp)
+ return 1;
+
+ long long total = 0, available = 0;
+ char line[256];
+ while (fgets(line, sizeof(line), fp) && (!total || !available)) {
+ sscanf(line, "MemTotal: %lld kB", &total);
+ sscanf(line, "MemAvailable: %lld kB", &available);
+ }
+ fclose(fp);
+
+ printf("Mem: %.0f%%\n", (double)(total - available) / total * 100);
+ return 0;
+}
diff --git a/sb-time.c b/sb-time.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <time.h>
+
+int main() {
+ time_t t = time(NULL);
+ char time_str[10];
+
+ strftime(time_str, sizeof(time_str), "%I:%M%P", localtime(&t));
+ printf("%s\n", time_str);
+ return 0;
+}
diff --git a/sb-weather.c b/sb-weather.c
@@ -0,0 +1,58 @@
+#include <curl/curl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WEATHER_FORMAT "?format=%f+%C"
+#define MAX_SIZE 1024
+
+size_t write_callback(void *ptr, size_t size, size_t nmemb, char *data) {
+ strncat(data, ptr, size * nmemb);
+ return size * nmemb;
+}
+
+int main(int argc, char *argv[]) {
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <location>\n", argv[0]);
+ return 1;
+ }
+
+ char url[MAX_SIZE], weather_data[MAX_SIZE] = {0}, cache_path[MAX_SIZE];
+ const char *cache_dir = getenv("XDG_CACHE_HOME") ?: "/tmp";
+
+ snprintf(url, sizeof(url), "https://wttr.in/%s%s", argv[1], WEATHER_FORMAT);
+ snprintf(cache_path, sizeof(cache_path), "%s/weatherreport", cache_dir);
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ CURL *curl = curl_easy_init();
+ if (!curl)
+ return 1;
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, weather_data);
+
+ if (curl_easy_perform(curl) != CURLE_OK) {
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ return 1;
+ }
+
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+
+ // Remove '+' character
+ for (char *p = weather_data; *p; p++) {
+ if (*p == '+')
+ memmove(p, p + 1, strlen(p));
+ }
+
+ FILE *fp = fopen(cache_path, "w");
+ if (fp) {
+ fputs(weather_data, fp);
+ fclose(fp);
+ }
+
+ printf("%s\n", weather_data);
+ return 0;
+}