initial commit
This commit is contained in:
19
LICENSE
Normal file
19
LICENSE
Normal file
@@ -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.
|
||||
32
Makefile
Normal file
32
Makefile
Normal file
@@ -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
|
||||
15
README
Normal file
15
README
Normal file
@@ -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
|
||||
```
|
||||
53
sb-cpu.c
Normal file
53
sb-cpu.c
Normal file
@@ -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;
|
||||
}
|
||||
14
sb-date.c
Normal file
14
sb-date.c
Normal file
@@ -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;
|
||||
}
|
||||
18
sb-memory.c
Normal file
18
sb-memory.c
Normal file
@@ -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;
|
||||
}
|
||||
11
sb-time.c
Normal file
11
sb-time.c
Normal file
@@ -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;
|
||||
}
|
||||
58
sb-weather.c
Normal file
58
sb-weather.c
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user