This commit is contained in:
Freya Murphy 2023-04-22 00:48:41 -04:00
commit b0613d87eb
3 changed files with 204 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
bin

40
Makefile Normal file
View file

@ -0,0 +1,40 @@
CC = gcc
INCFLAGS = -Isrc
CCFLAGS = -std=gnu99 -Wall -Wextra -pedantic -O2
CCFLAGS += $(INCFLAGS)
LDFLAGS += $(INCFLAGS)
BIN = bin
APP = $(BIN)/app
SRC = $(shell find src -name "*.c")
OBJ = $(SRC:%.c=$(BIN)/%.o)
.PHONY: dirs run clean build install uninstall
EOF: clean build
dirs:
mkdir -p ./$(BIN)
mkdir -p ./$(BIN)/src
run: build
$(APP)
build: dirs ${OBJ}
${CC} -o $(APP) $(filter %.o,$^) $(LDFLAGS)
$(BIN)/%.o: %.c
$(CC) -o $@ -c $< $(CCFLAGS)
clean:
rm -rf $(APP)
rm -rf $(BIN)
install:
cp $(APP) /usr/local/bin/ritfetch
uninstall:
rm /usr/local/bin/ritfetch

163
src/main.c Normal file
View file

@ -0,0 +1,163 @@
#undef _POSIX_C_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#define LINE_LENGTH 256
#define NUM_LENGTH 32
#define MAX_LINES 64
#define INIT_BUFFER_LEN 8
static char* get_line(char* buf, int len, FILE* file) {
char* ptr = fgets(buf, len, file);
if (ptr == NULL) return NULL;
buf[strcspn(buf, "\n")] = 0;
return ptr;
}
#define LINE(buf, line) buf + line * LINE_LENGTH
#define MAX(a, b) a > b ? a : b
static char* read_logo(FILE* file, uint16_t* height) {
uint16_t capacity = INIT_BUFFER_LEN;
uint16_t h = 0;
char* buf = malloc(LINE_LENGTH * capacity);
while (h < MAX_LINES && get_line(LINE(buf, h), LINE_LENGTH - 1, file) != NULL) {
h++;
if (h == capacity) {
capacity *= 2;
buf = realloc(buf, LINE_LENGTH * capacity);
}
}
*height = h;
return buf;
}
static char* read_data(FILE* file, uint16_t* height, uint16_t* offset) {
uint16_t capacity = INIT_BUFFER_LEN;
uint16_t h = 2, o = 0;
char accent_color[NUM_LENGTH], normal_color[NUM_LENGTH], offset_buffer[NUM_LENGTH], title_buffer[LINE_LENGTH];
char* end;
if (get_line(offset_buffer, NUM_LENGTH - 1, file) == NULL) {
printf("error: data file missing offset\n");
exit(EXIT_FAILURE);
}
o = strtol(offset_buffer, &end, 10);
if (offset_buffer == end) {
printf("error: data offset is not a valid numver\n");
exit(EXIT_FAILURE);
}
*offset = o;
if (get_line(accent_color, NUM_LENGTH - 1, file) == NULL) {
printf("error: data file missing accent color\n");
exit(EXIT_FAILURE);
}
if (get_line(normal_color, NUM_LENGTH - 1, file) == NULL) {
printf("error: data file missing normal color\n");
exit(EXIT_FAILURE);
}
if (get_line(title_buffer, LINE_LENGTH - 1, file) == NULL) {
printf("error: data file missing title\n");
exit(EXIT_FAILURE);
}
char* buf = malloc(LINE_LENGTH * capacity);
// funny stuff be goofy ahh'ing here
size_t title_len = strlen(title_buffer);
snprintf(LINE(buf, 1), LINE_LENGTH, "\x1b[%sm", normal_color);
size_t ansi_len = strlen(LINE(buf, 1));
memset(LINE(buf, 1) + ansi_len, '~', title_len);
(LINE(buf, 1))[title_len + ansi_len] = 0;
snprintf(LINE(buf, 0), LINE_LENGTH, "\x1b[%sm%s", accent_color, title_buffer);
char key[LINE_LENGTH];
char value[LINE_LENGTH];
while(h < MAX_LINES) {
if (get_line(key, LINE_LENGTH - 1, file) == NULL) break;
if (get_line(value, LINE_LENGTH - 1, file) == NULL) break;
#pragma GCC diagnostic ignored "-Wformat-truncation"
snprintf(LINE(buf, h), LINE_LENGTH, "\x1b[%sm%s\x1b[%sm: %s", accent_color, key, normal_color, value);
h++;
if (h == capacity) {
capacity *= 2;
buf = realloc(buf, LINE_LENGTH * capacity);
}
}
*height = h;
return buf;
}
__attribute__ ((__format__(printf, 1, 2)))
static FILE* run_command(const char* format, ...) {
va_list valist;
va_start(valist, format);
char buf[LINE_LENGTH];
vsnprintf(buf, LINE_LENGTH, format, valist);
FILE* out = popen(buf, "r");
if (out == NULL) {
printf("error: failed to run command %s: %s\n", buf, strerror(errno));
exit(EXIT_FAILURE);
}
return out;
}
static void close_command(FILE* out) {
int code = pclose(out);
if (code != 0) {
printf("error: command errored with exit code %d\n", code);
exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv) {
if (argc != 2) {
printf("usage: ritfetch domain\n");
return EXIT_FAILURE;
}
FILE* out;
out = run_command("curl -Lsf %s/.well-known/ritfetch/logo", argv[1]);
uint16_t logo_height;
char* logo = read_logo(out, &logo_height);
close_command(out);
out = run_command("curl -Lsf %s/.well-known/ritfetch/data", argv[1]);
uint16_t data_height, offset;
char* data = read_data(out, &data_height, &offset);
close_command(out);
uint16_t max_height = MAX(logo_height, data_height);
for (uint16_t i = 0; i < max_height; i++) {
if (i < logo_height) {
printf("%s", LINE(logo, i));
}
if (i < data_height) {
printf("\x1b[%uG\x1b[m", offset);
printf("%s", LINE(data, i));
}
printf("\n");
}
free(data);
free(logo);
return EXIT_SUCCESS;
}