summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorkatalx2026-02-01 17:51:43 -0500
committerkatalx2026-02-01 17:51:43 -0500
commitb2c27d7b23208f3d51927406198edd6a2e897391 (patch)
tree04d079ffc817f8cac9bbc848f9b6204c1f771300 /main.c
parentb295d429bf9c503b90c1cbadb950ce419ee02f57 (diff)
request documents from gopher & junk
Diffstat (limited to 'main.c')
-rw-r--r--main.c111
1 files changed, 100 insertions, 11 deletions
diff --git a/main.c b/main.c
index 80ab2e3..a886d9b 100644
--- a/main.c
+++ b/main.c
@@ -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;