commit - f5ccf7ae3254e2e1ae090253ae13e21b16f8d50b
commit + 35e1f40abf408663d468038e22af2c6f2ec34659
blob - 731893b48ab311b07be28cc9781bb004cec09e22
blob + e16501d2dcee4bd502a2a607fd995a5c7310903f
--- Makefile.am
+++ Makefile.am
telescope_SOURCES = compat.h \
compat/*.[ch] \
+ fs.c \
gemini.c \
gemtext.c \
hist.c \
blob - cab5f282060ec52b8f8eb22f0e0ad9a48f0a7523
blob + bd119ecb712192bbcc512815692a08ebb2db55fe
--- gemini.c
+++ gemini.c
#include <tls.h>
#include <unistd.h>
+static struct event imsgev;
static struct tls_config *tlsconf;
static struct imsgbuf *ibuf;
blob - /dev/null
blob + a5847c463c7f75320b500f978acd57640cbf2ba4 (mode 644)
--- /dev/null
+++ fs.c
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "telescope.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void die(void) __attribute__((__noreturn__));
+static void serve_bookmarks(uint32_t);
+static void handle_get(struct imsg*, size_t);
+static void handle_quit(struct imsg*, size_t);
+static void dispatch_imsg(int, short, void*);
+
+static struct event imsgev;
+static struct imsgbuf *ibuf;
+
+static imsg_handlerfn *handlers[] = {
+ [IMSG_GET] = handle_get,
+ [IMSG_QUIT] = handle_quit,
+};
+
+static void __attribute__((__noreturn__))
+die(void)
+{
+ abort(); /* TODO */
+}
+
+static void
+serve_bookmarks(uint32_t peerid)
+{
+ const char *t;
+ char path[PATH_MAX], buf[BUFSIZ];
+ size_t r;
+ FILE *f;
+
+ strlcpy(path, getenv("HOME"), sizeof(path));
+ strlcat(path, "/.telescope/bookmarks.gmi", sizeof(path));
+
+ if ((f = fopen(path, "r")) == NULL) {
+ t = "# error\n\nCan't open ~/.telescope/bookmarks.gmi";
+ imsg_compose(ibuf, IMSG_BUF, peerid, 0, -1, t, strlen(t));
+ imsg_compose(ibuf, IMSG_EOF, peerid, 0, -1, NULL, 0);
+ imsg_flush(ibuf);
+ return;
+ }
+
+ for (;;) {
+ r = fread(buf, 1, sizeof(buf), f);
+ imsg_compose(ibuf, IMSG_BUF, peerid, 0, -1, buf, r);
+ imsg_flush(ibuf);
+ if (r != sizeof(buf))
+ break;
+ }
+
+ imsg_compose(ibuf, IMSG_EOF, peerid, 0, -1, NULL, 0);
+ imsg_flush(ibuf);
+
+ fclose(f);
+}
+
+static void
+handle_get(struct imsg *imsg, size_t datalen)
+{
+ char *data;
+ const char *p;
+
+ data = imsg->data;
+
+ if (data[datalen-1] != '\0')
+ die();
+
+ if (!strcmp(data, "about:new")) {
+ imsg_compose(ibuf, IMSG_BUF, imsg->hdr.peerid, 0, -1,
+ about_new, strlen(about_new));
+ imsg_compose(ibuf, IMSG_EOF, imsg->hdr.peerid, 0, -1, NULL, 0);
+ imsg_flush(ibuf);
+ } else if (!strcmp(data, "about:bookmarks")) {
+ serve_bookmarks(imsg->hdr.peerid);
+ } else {
+ p = "# not found!\n";
+ imsg_compose(ibuf, IMSG_BUF, imsg->hdr.peerid, 0, -1, p, strlen(p));
+ imsg_compose(ibuf, IMSG_EOF, imsg->hdr.peerid, 0, -1, NULL, 0);
+ imsg_flush(ibuf);
+ }
+}
+
+static void
+handle_quit(struct imsg *imsg, size_t datalen)
+{
+ event_loopbreak();
+}
+
+static void
+dispatch_imsg(int fd, short ev, void *d)
+{
+ struct imsgbuf *ibuf = d;
+ struct imsg imsg;
+ ssize_t n;
+ size_t datalen;
+
+ if ((n = imsg_read(ibuf)) == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ return;
+ _exit(1);
+ }
+
+ if (n == 0)
+ _exit(1);
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ _exit(1);
+ if (n == 0)
+ return;
+ datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ handlers[imsg.hdr.type](&imsg, datalen);
+ imsg_free(&imsg);
+ }
+}
+
+int
+fs_main(struct imsgbuf *b)
+{
+ ibuf = b;
+
+ event_init();
+
+ event_set(&imsgev, ibuf->fd, EV_READ | EV_PERSIST, dispatch_imsg, ibuf);
+ event_add(&imsgev, NULL);
+
+ sandbox_fs_process();
+
+ event_dispatch();
+ return 0;
+}
blob - 550c6d1f6a2c846270a261c5c863b4f119ca6fcf
blob + ce229f46156efda7fbd24c38fa125849669a5fd5
--- sandbox.c
+++ sandbox.c
#ifdef __OpenBSD__
# include <err.h>
-# include <stddef.h>
+# include <limits.h>
+# include <stdlib.h>
+# include <string.h>
# include <unistd.h>
void
void
sandbox_ui_process(void)
{
- if (pledge("stdio tty", NULL))
+ if (pledge("stdio tty", NULL) == -1)
err(1, "pledge");
}
+void
+sandbox_fs_process(void)
+{
+ char path[PATH_MAX];
+
+ if (unveil("/tmp", "r") == -1)
+ err(1, "unveil");
+
+ strlcpy(path, getenv("HOME"), sizeof(path));
+ strlcat(path, "/Downloads", sizeof(path));
+ if (unveil(path, "r") == -1)
+ err(1, "unveil");
+
+ strlcpy(path, getenv("HOME"), sizeof(path));
+ strlcat(path, "/.telescope", sizeof(path));
+ if (unveil(path, "r") == -1)
+ err(1, "unveil");
+
+ if (pledge("stdio rpath", NULL) == -1)
+ err(1, "pledge");
+}
+
#else
#warning "No sandbox for this OS"
return;
}
+void
+sandbox_ui_process(void)
+{
+ return;
+}
+
+void
+sandbox_fs_process(void)
+{
+ return;
+}
+
#endif
blob - 9044a5f66221c0e8dafa303ace681e87d1de1a89
blob + 6d3c77320242a17abb3375bb5be608c085a67389
--- telescope.c
+++ telescope.c
#include <string.h>
#include <unistd.h>
-struct event imsgev;
+struct event netev, fsev;
struct tabshead tabshead;
/* the first is also the fallback one */
{ NULL, NULL },
};
-static struct imsgbuf *netibuf;
+static struct imsgbuf *netibuf, *fsibuf;
static void die(void) __attribute__((__noreturn__));
static struct tab *tab_by_id(uint32_t);
static void
dispatch_imsg(int fd, short ev, void *d)
{
- struct imsg imsg;
- size_t datalen;
- ssize_t n;
+ struct imsgbuf *ibuf = d;
+ struct imsg imsg;
+ size_t datalen;
+ ssize_t n;
- if ((n = imsg_read(netibuf)) == -1) {
+ if ((n = imsg_read(ibuf)) == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
die();
}
- if (n == 0) {
- fprintf(stderr, "other side is dead\n");
- exit(0);
- }
+ if (n == 0)
+ _exit(1);
for (;;) {
- if ((n = imsg_get(netibuf, &imsg)) == -1)
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
die();
if (n == 0)
return;
len = sizeof(tab->hist_cur->h)-1;
strlcpy(tab->hist_cur->h, url, len);
- if (!strcmp(url, "about:new"))
- load_page_from_str(tab, about_new);
- else
- load_page_from_str(tab, "# not found\n");
+ gemtext_initparser(&tab->page);
+
+ imsg_compose(fsibuf, IMSG_GET, tab->id, 0, -1,
+ tab->hist_cur->h, len+1);
+ imsg_flush(fsibuf);
}
void
int
main(void)
{
- struct imsgbuf main_ibuf, network_ibuf;
- int imsg_fds[2];
+ struct imsgbuf network_ibuf, fs_ibuf;
+ int net_fds[2], fs_fds[2];
+ pid_t pid;
+ pid = getpid();
+
signal(SIGCHLD, SIG_IGN);
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fs_fds) == -1)
err(1, "socketpair");
switch (fork()) {
err(1, "fork");
case 0:
/* child */
- setproctitle("client");
- close(imsg_fds[0]);
- imsg_init(&network_ibuf, imsg_fds[1]);
- exit(client_main(&network_ibuf));
+ setproctitle("(%d) fs", pid);
+ close(fs_fds[0]);
+ imsg_init(&fs_ibuf, fs_fds[1]);
+ exit(fs_main(&fs_ibuf));
+ default:
+ close(fs_fds[1]);
+ imsg_init(&fs_ibuf, fs_fds[0]);
+ fsibuf = &fs_ibuf;
}
- setproctitle("ui");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, net_fds) == -1)
+ err(1, "socketpair");
- close(imsg_fds[1]);
- imsg_init(&main_ibuf, imsg_fds[0]);
- netibuf = &main_ibuf;
+ switch (fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ /* child */
+ setproctitle("(%d) client", pid);
+ close(net_fds[0]);
+ close(fs_fds[0]);
+ imsg_init(&network_ibuf, net_fds[1]);
+ exit(client_main(&network_ibuf));
+ default:
+ close(net_fds[1]);
+ imsg_init(&network_ibuf, net_fds[0]);
+ netibuf = &network_ibuf;
+ }
+ setproctitle("(%d) ui", pid);
+
TAILQ_INIT(&tabshead);
event_init();
- event_set(&imsgev, netibuf->fd, EV_READ | EV_PERSIST, dispatch_imsg, netibuf);
- event_add(&imsgev, NULL);
+ event_set(&netev, netibuf->fd, EV_READ | EV_PERSIST, dispatch_imsg, netibuf);
+ event_add(&netev, NULL);
+ event_set(&fsev, fsibuf->fd, EV_READ | EV_PERSIST, dispatch_imsg, fsibuf);
+ event_add(&fsev, NULL);
+
ui_init();
sandbox_ui_process();
imsg_compose(netibuf, IMSG_QUIT, 0, 0, -1, NULL, 0);
imsg_flush(netibuf);
+ imsg_compose(fsibuf, IMSG_QUIT, 0, 0, -1, NULL, 0);
+ imsg_flush(fsibuf);
+
ui_end();
return 0;
blob - 382a95116c89beb11b4d9a2975dbe37d594463e4
blob + dbbcaa9440b78c25e03f3b714416d3349db6abcb
--- telescope.h
+++ telescope.h
#define GEMINI_URL_LEN 1024
enum imsg_type {
+ /* ui <-> client */
IMSG_GET, /* data is URL, peerid the tab id */
IMSG_ERR,
IMSG_CHECK_CERT,
TAILQ_ENTRY(keymap) keymaps;
};
-extern struct event imsgev;
+/* fs.c */
+int fs_main(struct imsgbuf*);
/* gemini.c */
-int client_main(struct imsgbuf *b);
+int client_main(struct imsgbuf*);
/* gemtext.c */
void gemtext_initparser(struct parser*);
/* sandbox.c */
void sandbox_network_process(void);
void sandbox_ui_process(void);
+void sandbox_fs_process(void);
/* telescope.c */
void load_about_url(struct tab*, const char*);