diff options
| author | katalx | 2026-02-01 17:51:43 -0500 |
|---|---|---|
| committer | katalx | 2026-02-01 17:51:43 -0500 |
| commit | b2c27d7b23208f3d51927406198edd6a2e897391 (patch) | |
| tree | 04d079ffc817f8cac9bbc848f9b6204c1f771300 /main.c | |
| parent | b295d429bf9c503b90c1cbadb950ce419ee02f57 (diff) | |
request documents from gopher & junk
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 111 |
1 files changed, 100 insertions, 11 deletions
@@ -1,5 +1,6 @@ #include <stdio.h> #include <unistd.h> +#include <fcntl.h> #include <limits.h> #include <sys/socket.h> #include <netinet/in.h> @@ -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; |
