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