diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..01bc02a --- /dev/null +++ b/src/main.c @@ -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; +} |