commit - /dev/null
commit + c2820569ceee27bab3e5efdaeba7a592f16dec4e
blob - /dev/null
blob + f450a100e11d76f70c224b585d173f1986cccbfd (mode 644)
--- /dev/null
+++ LICENSE
+Copyright (c) 2024 Gonzalo Rodriguez (gonzalo@x61.sh)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
blob - /dev/null
blob + cd5a4b054a640aa6d7bb8f294e0f8b5b5ffc46a0 (mode 644)
--- /dev/null
+++ Makefile
+.POSIX:
+
+CC ?= cc
+LIBS =
+OPTFLAGS = -O3
+DBGFLAGS = -O0 -g
+CFLAGS = -pipe -Wall -Werror -march=native
+INCLUDEDIR = -I.
+
+all: build
+
+build: clean
+ ${CC} ${DBGFLAGS} ${CFLAGS} ${INCLUDEDIR} -o termbar ${LIBS} termbarc.c
+
+opt: clean
+ ${CC} ${OPTFLAGS} ${CFLAGS} ${INCLUDEDIR} -o termbar ${LIBS} termbarc.c
+
+install:
+ install -s termbar ${HOME}/bin/termbar
+ install termbar.conf ${HOME}/.termbar.conf
+
+clean:
+ rm -f termbar
+
+uninstall:
+ rm -f ${HOME}/bin/termbar
+ rm -f ${HOME}/.termbar.conf
+
+debug: build
+ egdb -q ./termbar -ex "break main" -ex "run"
blob - /dev/null
blob + 90bdf7aa38f65e18cc634dcfe50303871601f354 (mode 644)
--- /dev/null
+++ README.md
+# Termbar in C
+
+termbar(in C) is a status bar for cwm (or other wm) on OpenBSD (no idea if works on
+linux or other OS and also I don't care).
+
+The idea was to make my original [termbar](https://github.com/gonzalo-/termbar/) in C and
+I took inspiration from [sdk's cbar](https://git.uugrn.org/sdk/cbar), it's hardly
+modified but yet, helped me a lot.
+
+CAVEATS: This is a testing and still developing version, I tested in a couple machines
+so it might not work on yours or probably put on fire your laptop, so be careful and don't
+complain much, if you have some feedback you know where you can find me.
+
+![Termbar](termbar.png)
+
+## Features
+
+termbar for now can show you, a "logo" (or name), hostname, cpu speed and temp,
+free mem, window id, load average, battery status (probably only in thinkpads), public IP,
+private IP and if you are connected to a VPN.
+
+The battery percentage it will turn red if your machine is not connected to the AC as
+the VPN output will be "No VPN" in red if there is no wg(4) present or tunnel up (still on
+testing).
+
+If your CPU has no sensors or not supported it will show an "x" next to the CPU speed, you
+will probably see this on a VM or old machine (not very much tested).
+
+## Usage
+
+termbar has now a config file (which you should have in ~/.termbar.conf after the install),
+you have an example [here](termbar.conf) with all the options available:
+
+```
+logo=termbar
+date=yes
+cpu=yes
+bat=yes
+mem=yes
+load=yes
+net=yes
+winid=yes
+hostname=yes
+interface=iwm0
+vpn=yes
+```
+
+The only 2 options you can play with are "logo" and "interface", "logo" will just print
+something you put there and "interface" will be use to get the internal ip of your
+machine.
+
+With the other options are pretty straigforward, "yes" to show the information on termbar
+and "no" to hide it.
+
+## Display
+
+For displaying termbar in your cwm or maybe another wm, you need to create a thin xterm that
+will show the output, for this you can add a similar line in your .xsession:
+
+```
+...
+# Termbar
+exec xterm -fs 12 -bg "black" -fg "grey" -name termbar -class termbar -T termbar -e ~/bin/termbar &
+...
+exec cwm
+```
+
+For cwm I usually let a gap on the top of the screen for termbar with the follow on my .cwmrc:
+
+```
+...
+gap 35 5 5 5
+...
+```
+
+The full files for cwm and .xsession are [here.](https://github.com/gonzalo-/termbar/).
+
+You probably can use termbar also in tmux as status bar, you might want to add or modify your
+~/.tmux.conf to something like:
+
+```
+...
+set -g status-right "#{exec ~/bin/termbar}"
+...
+```
+
+## Dependencies
+
+In the current state you just need curl to check your public ip.
+
+```
+$ doas pkg_add curl
+```
+
+## Build
+
+You have all you need in your OpenBSD base installation, so by cloning the repo
+and building is as easy as:
+
+```
+$ git clone https://github.com/gonzalo-/termbarc/
+$ cd termbarc
+$ make
+rm -f termbar
+cc -O0 -g -pipe -Wall -Werror -march=native -I. -o termbar termbarc.c
+```
+
+## Installation
+
+termbar will go to your ${HOME}/bin directory, if you want to put it somewhere
+else you should modify the Makefile, otherwise make sure you have a ~/bin
+directory and then:
+
+```
+$ make install
+install -s termbar /home/gonzalo/bin/termbar
+install termbar.conf /home/gonzalo/.termbar.conf
+```
+
+## Uninstall
+
+If termbar it's not for you, you can uninstall it with:
+
+```
+$ make uninstall
+rm -f /home/gonzalo/bin/termbar
+rm -f /home/gonzalo/.termbar.conf
+```
blob - /dev/null
blob + 8c42c38ce752d381fd60c2b51cc069df3d3abcab (mode 644)
--- /dev/null
+++ termbar.conf
+logo=Termbar
+date=yes
+cpu=yes
+bat=yes
+mem=yes
+load=yes
+net=yes
+winid=yes
+hostname=no
+interface=iwm0
+vpn=yes
blob - /dev/null
blob + c6164c52fe96136bc348652c18cb28faa7ed08b8 (mode 644)
Binary files /dev/null and termbar.png differ
blob - /dev/null
blob + 7730a0abb3af12011d42b28c10b2070c8eb186b2 (mode 644)
--- /dev/null
+++ termbarc.c
+/*
+ * Copyright (c) 2024 Gonzalo Rodriguez (gonzalo@x61.sh)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <ifaddrs.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <sys/sysctl.h>
+#include <sys/sensors.h>
+#include <machine/apmvar.h>
+
+#include <wchar.h>
+#include <time.h>
+#include <locale.h>
+
+#include <termbarc.h>
+
+struct Config {
+ char *logo;
+ char *interface;
+ int show_hostname;
+ int show_date;
+ int show_cpu;
+ int show_mem;
+ int show_bat;
+ int show_load;
+ int show_winid;
+ int show_net;
+ int show_vpn;
+};
+
+char *extract_logo(const char *line)
+{
+ if (strstr(line, "logo=")) {
+ const char *logo_start = strchr(line, '=') + 1;
+ const char *logo_end = NULL;
+
+ // Find the end of the logo string
+ const char *cursor = logo_start;
+ while (*cursor && *cursor != ' ' && *cursor != '\n') {
+ cursor++;
+ }
+ logo_end = cursor;
+
+ // Calculate the length of the logo string
+ size_t logo_length = logo_end - logo_start;
+
+ // Allocate memory for the logo and copy it
+ char *logo = (char *) malloc((logo_length + 1) * sizeof(char));
+ if (logo == NULL) {
+ perror("No logo.");
+ exit(EXIT_FAILURE);
+ }
+ strncpy(logo, logo_start, logo_length);
+ logo[logo_length] = '\0';
+ return logo;
+ }
+ return NULL;
+}
+
+struct Config config_file()
+{
+ struct Config config = { NULL, 0, 0, 0, 0, 0, 0, 0, 0 };
+ const char *home_dir = getenv("HOME");
+ if (home_dir == NULL) {
+ fprintf(stderr, "Error: HOME environment variable not set\n");
+ exit(EXIT_FAILURE);
+ }
+
+ const char *config_file_names[] = { "termbar.conf", ".termbar.conf" };
+ FILE *file = NULL;
+ char config_file_path[256];
+
+ for (int i = 0; i < 2; ++i) {
+ snprintf(config_file_path, sizeof(config_file_path), "%s/%s",
+ home_dir, config_file_names[i]);
+ file = fopen(config_file_path, "r");
+ if (file != NULL) {
+ break; // File found, exit loop
+ }
+ }
+
+ if (file == NULL) {
+ fprintf(stderr, "Error: Unable to open config file\n");
+ exit(EXIT_FAILURE);
+ }
+
+ char line[MAX_LINE_LENGTH];
+
+ while (fgets(line, sizeof(line), file)) {
+ line[strcspn(line, "\n")] = '\0';
+
+ char *logo = extract_logo(line);
+ if (logo != NULL) {
+ config.logo = logo;
+ continue; // Move to the next line
+ }
+ // Extract interface option
+ if (strstr(line, "interface=")) {
+ const char *interface_start = strchr(line, '=') + 1;
+ size_t interface_length = strlen(interface_start);
+ config.interface = malloc(interface_length + 1);
+ if (config.interface == NULL) {
+ perror("Memory allocation failed");
+ exit(EXIT_FAILURE);
+ }
+ strncpy(config.interface, interface_start,
+ interface_length);
+ config.interface[interface_length] = '\0';
+ }
+ // Check confs
+ if (strstr(line, "date=yes")) {
+ config.show_date = 1;
+ } else if (strstr(line, "cpu=yes")) {
+ config.show_cpu = 1;
+ } else if (strstr(line, "load=yes")) {
+ config.show_load = 1;
+ } else if (strstr(line, "bat=yes")) {
+ config.show_bat = 1;
+ } else if (strstr(line, "net=yes")) {
+ config.show_net = 1;
+ } else if (strstr(line, "mem=yes")) {
+ config.show_mem = 1;
+ } else if (strstr(line, "winid=yes")) {
+ config.show_winid = 1;
+ } else if (strstr(line, "hostname=yes")) {
+ config.show_hostname = 1;
+ } else if (strstr(line, "vpn=yes")) {
+ config.show_vpn = 1;
+ }
+ }
+
+ fclose(file);
+ return config;
+}
+
+void update_public_ip()
+{
+ FILE *fp;
+ char buffer[128];
+
+ // to-do I need a better thing than curl
+ fp = popen("/usr/local/bin/curl -s ifconfig.me", "r");
+ if (fp == NULL) {
+ perror("popen");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fgets(buffer, sizeof(buffer), fp) != NULL) {
+ // Copy the public IP address to the global variable
+ strncpy(public_ip, buffer, MAX_IP_LENGTH);
+ // Remove trailing newline character, if any
+ public_ip[strcspn(public_ip, "\n")] = '\0';
+ }
+ pclose(fp);
+}
+
+char *get_hostname()
+{
+ static char hostname[HOSTNAME_MAX_LENGTH];
+
+ if (gethostname(hostname, HOSTNAME_MAX_LENGTH) == -1) {
+ perror("gethostname");
+ exit(EXIT_FAILURE);
+ }
+
+ return hostname;
+}
+
+void update_internal_ip(struct Config config)
+{
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_in *sa;
+
+ if (getifaddrs(&ifap) == -1) {
+ perror("getifaddrs");
+ exit(EXIT_FAILURE);
+ }
+ // Search for the specified interface or fallback to lo0
+ if (config.interface == NULL || strlen(config.interface) == 0) {
+ strlcpy(internal_ip, "lo0", sizeof(internal_ip));
+ } else {
+ // Search for the specified interface
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, config.interface) == 0 &&
+ ifa->ifa_addr != NULL
+ && ifa->ifa_addr->sa_family == AF_INET) {
+ sa = (struct sockaddr_in *) ifa->ifa_addr;
+ inet_ntop(AF_INET, &(sa->sin_addr), internal_ip,
+ sizeof(internal_ip));
+ break;
+ }
+ }
+ }
+
+ freeifaddrs(ifap);
+}
+
+void update_vpn()
+{
+ struct ifaddrs *ifap, *ifa;
+ int has_wg_interface = 0;
+
+ if (getifaddrs(&ifap) == -1) {
+ perror("getifaddrs");
+ exit(EXIT_FAILURE);
+ }
+ // Check for wgX interfaces
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if (strncmp(ifa->ifa_name, "wg", 2) == 0
+ && ifa->ifa_flags & IFF_UP) {
+ has_wg_interface = 1;
+ break;
+ }
+ }
+
+ freeifaddrs(ifap);
+
+ if (has_wg_interface)
+ printf(" %sVPN%s", GREEN, RESET);
+ else
+ printf(" %sNo VPN%s", RED, RESET);
+}
+
+unsigned long long update_mem()
+{
+ int mib[2];
+ size_t len;
+ unsigned long long freemem;
+
+ mib[0] = CTL_VM;
+ mib[1] = VM_UVMEXP;
+
+ len = sizeof(struct uvmexp);
+
+ struct uvmexp uvm_stats;
+
+ if (sysctl(mib, 2, &uvm_stats, &len, NULL, 0) == -1) {
+ perror("sysctl");
+ exit(EXIT_FAILURE);
+ }
+
+ freemem =
+ (unsigned long long) uvm_stats.free *
+ (unsigned long long) uvm_stats.pagesize / (1024 * 1024);
+
+ return freemem;
+}
+
+void update_cpu_base_speed()
+{
+ int temp;
+ size_t templen = sizeof(temp);
+
+ int mib[5] = { CTL_HW, HW_CPUSPEED };
+
+ if (sysctl(mib, 2, &temp, &templen, NULL, 0) == -1)
+ snprintf(cpu_base_speed, sizeof(cpu_base_speed), "no_freq");
+ else
+ snprintf(cpu_base_speed, sizeof(cpu_base_speed), "%4dMhz",
+ temp);
+}
+
+void update_cpu_avg_speed()
+{
+ uint64_t freq;
+ size_t len = sizeof(freq);
+ int mib[2] = { CTL_HW, HW_CPUSPEED };
+
+ if (sysctl(mib, 2, &freq, &len, NULL, 0) == -1) {
+ perror("sysctl");
+ return;
+ }
+ snprintf(cpu_avg_speed, sizeof(cpu_avg_speed), "%4lluMhz", freq);
+}
+
+void update_system_load(double *load_avg)
+{
+ double load[3]; // Take 1, 5, and 15-minute load averages
+
+ if (getloadavg(load, 3) == -1) {
+ perror("getloadavg");
+ exit(EXIT_FAILURE);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ load_avg[i] = load[i];
+ }
+}
+
+void update_cpu_temp()
+{
+ struct sensor sensor;
+ size_t templen = sizeof(sensor);
+ int temp = -1;
+
+ static int temp_mib = -1;
+
+ if (temp_mib == -1) {
+ for (temp_mib = 0; temp_mib < 20; temp_mib++) {
+ int mib[5] = { CTL_HW, HW_SENSORS, temp_mib, SENSOR_TEMP, 0 }; // acpitz0.temp0 (x395)
+ if (sysctl(mib, 5, &sensor, &templen, NULL, 0) != -1)
+ break;
+ }
+ }
+
+ if (temp_mib != -1) {
+ int mib[5] = { CTL_HW, HW_SENSORS, temp_mib, SENSOR_TEMP, 0 };
+ if (sysctl(mib, 5, &sensor, &templen, NULL, 0) != -1) {
+ temp = (sensor.value - 273150000) / 1000000.0;
+ if (temp >= 0 && temp <= 100) { // hmmm could be more than 100?
+ snprintf(cpu_temp, sizeof(cpu_temp),
+ "%d\302\260C", temp);
+ return;
+ }
+ }
+ }
+ // If no valid temperature reading found, set to "x"
+ // specially for VMs
+ snprintf(cpu_temp, sizeof(cpu_temp), "x");
+}
+
+void update_battery()
+{
+ int fd;
+ struct apm_power_info pi;
+
+ if ((fd = open("/dev/apm", O_RDONLY)) == -1 ||
+ ioctl(fd, APM_IOC_GETPOWER, &pi) == -1 || close(fd) == -1) {
+ strlcpy(battery_percent, "N/A", sizeof(battery_percent));
+ return;
+ }
+
+ if (pi.battery_state == APM_BATT_UNKNOWN ||
+ pi.battery_state == APM_BATTERY_ABSENT) {
+ strlcpy(battery_percent, "N/A", sizeof(battery_percent));
+ return;
+ }
+
+ if (pi.ac_state == APM_AC_ON) {
+ snprintf(battery_percent, sizeof(battery_percent), "%d%%",
+ pi.battery_life);
+ } else {
+ snprintf(battery_percent, sizeof(battery_percent), "%s%d%%%s",
+ RED, pi.battery_life, RESET);
+ }
+}
+
+void update_datetime()
+{
+ time_t rawtime;
+ struct tm *timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime(datetime, sizeof(datetime), "%a %d %b %H:%M", timeinfo);
+}
+
+void update_windowid(char *window_id)
+{
+ const char *command =
+ "xprop -root 32c '\\t$0' _NET_CURRENT_DESKTOP | cut -f 2";
+
+ FILE *pipe = popen(command, "r");
+ if (pipe == NULL) {
+ fprintf(stderr,
+ "Error: Failed to open pipe for command execution");
+ strlcpy(window_id, "N/A", MAX_OUTPUT_LENGTH);
+ return;
+ }
+
+ char output[MAX_OUTPUT_LENGTH];
+ if (fgets(output, MAX_OUTPUT_LENGTH, pipe) == NULL) {
+ fprintf(stderr, "Error: Failed to read command output");
+ strlcpy(window_id, "N/A", MAX_OUTPUT_LENGTH);
+ pclose(pipe);
+ return;
+ }
+
+ pclose(pipe);
+
+ size_t len = strlen(output);
+ if (len > 0 && output[len - 1] == '\n') {
+ output[len - 1] = '\0';
+ }
+
+ strlcpy(window_id, output, MAX_OUTPUT_LENGTH);
+}
+
+int main(int argc, const char *argv[])
+{
+ // We all want UTF8
+ setlocale(LC_CTYPE, "C");
+ setlocale(LC_ALL, "en_US.UTF-8");
+
+ // Read the config file
+ struct Config config = config_file();
+ if (config.logo == NULL) {
+ fprintf(stderr,
+ "Error: Unable to read name from config file\n");
+ return 1;
+ }
+ // Hide cursor
+ printf("\e[?25l");
+
+ while (1) {
+ printf("\r\e[K");
+ if (config.show_winid) {
+ update_windowid(window_id);
+ printf("%s[%s]%s", RESET, window_id, RESET);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.logo != NULL && strlen(config.logo) > 0) {
+ printf("%s%s%s", GREEN, config.logo, RESET);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_hostname) {
+ char *hostname = get_hostname();
+ printf(" %s ", hostname);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_date) {
+ update_datetime();
+ printf(" %s ", datetime);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_cpu) {
+ update_cpu_temp();
+ update_cpu_avg_speed();
+ update_cpu_base_speed();
+ printf(" %sCPU:%s %s (%s) ", GREEN, RESET,
+ cpu_avg_speed, cpu_temp);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_mem) {
+ free_memory = update_mem();
+ printf(" %sMem:%s %.0llu MB ", GREEN, RESET,
+ free_memory);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_load) {
+ update_system_load(system_load);
+ printf(" %sLoad:%s %.2f ", GREEN, RESET,
+ system_load[0]);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_bat) {
+ update_battery();
+ printf(" %sBat:%s %s ", GREEN, RESET, battery_percent);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_net) {
+ update_public_ip();
+ update_internal_ip(config);
+ printf(" %sIPs:%s %s ~ %s ", GREEN, RESET, public_ip,
+ internal_ip);
+ printf("%s|%s", PURPLE, RESET);
+ }
+ if (config.show_vpn) {
+ update_vpn();
+ }
+
+ fflush(stdout);
+ if (argc == 2)
+ if (strcmp("-1", argv[1]) >= 0)
+ return 0;
+ usleep(3000000);
+ }
+ return 0;
+}
blob - /dev/null
blob + cf69de91a16819a6cc2b1e73dfacf9d77241652a (mode 644)
--- /dev/null
+++ termbarc.h
+/*
+ * Copyright (c) 2024 Gonzalo Rodriguez (gonzalo@x61.sh)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define INET_ADDRSTRLEN 16
+#define MAX_IP_LENGTH 32
+#define MAX_LINE_LENGTH 256
+#define MAX_OUTPUT_LENGTH 16
+#define HOSTNAME_MAX_LENGTH 256
+
+// Define ANSI escape codes for color formatting
+#define PURPLE "\x1b[38;2;138;43;226m"
+#define ORANGE "\x1b[38;2;255;165;0m"
+#define GREEN "\x1b[38;2;0;128;0m"
+#define YELLOW "\x1b[38;2;255;255;0m"
+#define RED "\x1b[38;2;255;0;0m"
+#define RESET "\x1b[0m"
+
+static char battery_percent[32];
+static char cpu_temp[32];
+static char cpu_base_speed[32];
+static char cpu_avg_speed[32];
+static char datetime[32];
+static char public_ip[MAX_IP_LENGTH];
+static char internal_ip[INET_ADDRSTRLEN];
+char vpn_status[16];
+char mem_info[32];
+char window_id[MAX_OUTPUT_LENGTH];
+double system_load[3];
+unsigned long long free_memory;