From b2c27d7b23208f3d51927406198edd6a2e897391 Mon Sep 17 00:00:00 2001 From: katalx Date: Sun, 1 Feb 2026 17:51:43 -0500 Subject: request documents from gopher & junk --- Makefile | 2 +- dynarr.h | 59 +++++++++++++++++++++++++++++++++ main.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 dynarr.h diff --git a/Makefile b/Makefile index c8e803b..d78fc6d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -EXE = xmenu +EXE = wlb OBJ != find . -name '*.c' | sed -e 's/\.c$$/.o/' -e 's|^\./||' CFLAGS += -Wall -Wpedantic diff --git a/dynarr.h b/dynarr.h new file mode 100644 index 0000000..327d5e7 --- /dev/null +++ b/dynarr.h @@ -0,0 +1,59 @@ +#ifndef DYNARR_H +#define DYNARR_H + +#include +#include +#include +#include + +#define DYNARR(T) struct { uint32_t n, c_; T *v; } + +#define DA_INIT_CAP 32 +#define DA_ELEM(da, n) ((n) * sizeof(*(da)->v)) +#define DA_BIT_CEIL ( + +static inline uint32_t da_bit_ceil(uint32_t x) { + return x ? 1U << (32 - __builtin_clz(x - 1)) : 0; +} + +/* malloc */ + +#define DA_FIT(da, n) do {\ + if ((n) > (da)->c_) {\ + (da)->c_ = da_bit_ceil((uint32_t)(n));\ + (da)->v = realloc((da)->v, DA_ELEM(da, (da)->c_));\ + }\ + if (!(da)->v) err(1, "dynarr fit");\ +} while(0) +#define DA_GROW(da, n_) DA_FIT(da, (da)->n + (n_)) +#define DA_PUSH(da, ...) do {\ + DA_GROW(da, 1);\ + (da)->v[(da)->n++] = (__VA_ARGS__);\ +} while(0) +#define DA_PUSH_MULT(da, o, n_) do {\ + DA_GROW(da, n_);\ + memcpy((da)->v + (da)->n, (o), DA_ELEM(da, n_));\ + (da)->n += (n_);\ +} while(0) + +/* arena */ + +#define DA_AFIT(da, a, n) do {\ + if ((n) > (da)->c_) {\ + uint32_t da_fit_c = da_bit_ceil((uint32_t)(n));\ + (da)->v = resize(a, (da)->v, (da)->c_, da_fit_c);\ + (da)->c_ = da_fit_c;\ + }\ +} while(0) +#define DA_AGROW(da, a, n_) DA_AFIT(da, a, (da)->n + (n_)) +#define DA_APUSH(da, a, ...) do {\ + DA_AGROW(da, a, 1);\ + (da)->v[(da)->n++] = (__VA_ARGS__);\ +} while(0) +#define DA_APUSH_MULT(da, a, o, n_) do {\ + DA_AGROW(da, a, n_);\ + memcpy((da)->v + (da)->n, (o), DA_ELEM(da, n_));\ + (da)->n += (n_);\ +} while(0) + +#endif diff --git a/main.c b/main.c index 80ab2e3..a886d9b 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -8,6 +9,7 @@ #define ARENA_IMPL #define STR_IMPL +#include "dynarr.h" #include "arena.h" #include "str.h" @@ -208,6 +210,100 @@ parse_request(Str url, Request *req) return 0; } +/* documents */ + +typedef enum { + DOC_ERROR, + DOC_TEXT, + DOC_GOPHERMAP, + DOC_UNKNOWN +} DocType; + +typedef struct { + Arena arena; + DocType type; + Str src; +} Doc; + +int +doc_parse(Doc *d, Str src, DocType t) +{ +} + +/* fetching documents */ + +ssize_t +write_str(int fd, Str s) +{ + return write(fd, s.s, s.n); +} + +Str +read_all(int fd, Arena *a) +{ + DYNARR(char) r = { 0 }; + for (;;) { + DA_AFIT(&r, a, r.n + 1024); + ssize_t n = read(fd, r.v + r.n, r.c_ - r.n); + if (n <= 0) break; + r.n += n; + } + return (Str) { r.v, r.n }; +} + +DocType +fetch_gopher(Str *buf, Request req, Arena *perm, Arena *scratch) +{ + DocType t = DOC_UNKNOWN; + if (req.path.n == 0) { + t = DOC_GOPHERMAP; + } else { + switch (req.path.s[0]) { + case '0': t = DOC_TEXT; break; + case '1': t = DOC_GOPHERMAP; break; + default: + /* don't bother fetching */ + *buf = S(""); + return DOC_UNKNOWN; + } + req.path = str_skip(req.path, 1); + } + + int s = addr_conn(req.host, req.port, scratch); + if (s == -1) return DOC_ERROR; + write_str(s, req.path); + write_str(s, S("\r\n")); + *buf = read_all(s, perm); + close(s); + + return t; +} + +DocType +fetch_file(Str *buf, Request req, Arena *perm, Arena *scratch) +{ + int f = open(str_to_cstr(req.path, scratch), O_RDONLY); + if (f == -1) return DOC_ERROR; + *buf = read_all(f, perm); + close(f); + return DOC_TEXT; +} + +DocType +fetch(Str *buf, Request req, Arena *perm, Arena *scratch) +{ + switch (req.proto) { + case PROT_GOPHER: + return fetch_gopher(buf, req, perm, scratch); + case PROT_FILE: + return fetch_file(buf, req, perm, scratch); + default: + *buf = S(""); + fprintf(stderr, "unknown type to fetch file\n"); + return DOC_ERROR; + } +} + int main(void) { @@ -215,22 +311,15 @@ main(void) Request req = { 0 }; addr_init(); - printf("%d\n", parse_request(S("gopher://sdf.org/users/solderpunk"), &req)); + printf("parse_request() -> %d\n", parse_request(S("file://main.c"), &req)); printf("host = %.*s\n", (int)req.host.n, req.host.s); printf("path = %.*s\n", (int)req.path.n, req.path.s); printf("prot = %d\n", req.proto); printf("port = %d\n", req.port); - int s = addr_conn(req.host, req.port, &scratch); - write(s, req.path.s, req.path.n); - write(s, "\r\n", 2); - for (;;) { - char buf[256]; - int n = read(s, buf, 256); - if (n <= 0) break; - fwrite(buf, 1, n, stdout); - } - close(s); + Str buf = { 0 }; + printf("fetch() -> %d\n", fetch(&buf, req, &scratch, &scratch)); + printf("%.*s\n", (int)buf.n, buf.s); addr_fini(); return 0; -- cgit v1.2.3