initial
This commit is contained in:
commit
b0613d87eb
3 changed files with 204 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bin
|
40
Makefile
Normal file
40
Makefile
Normal 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
163
src/main.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue