summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--dynarr.h59
-rw-r--r--main.c111
3 files changed, 160 insertions, 12 deletions
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 <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <err.h>
+
+#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 <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;