From a64f1a4ea2962e534673e27d85d92703c64201b0 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 9 Aug 2018 00:24:49 -0400 Subject: Add URL detection, listing and opening Might also add /copy, like /open. --- url.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 url.c (limited to 'url.c') diff --git a/url.c b/url.c new file mode 100644 index 0000000..33652ff --- /dev/null +++ b/url.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2018 Curtis McEnroe + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "chat.h" + +static const char *SCHEMES[] = { + "https:", + "http:", + "ftp:", +}; +static const size_t SCHEMES_LEN = sizeof(SCHEMES) / sizeof(SCHEMES[0]); + +enum { RING_LEN = 16 }; +static char *ring[RING_LEN]; +static size_t last; +static_assert(!(RING_LEN & (RING_LEN - 1)), "power of two RING_LEN"); + +static void push(const char *url, size_t len) { + free(ring[last]); + ring[last++] = strndup(url, len); + last &= RING_LEN - 1; +} + +void urlScan(const char *str) { + while (str[0]) { + size_t len = 1; + for (size_t i = 0; i < SCHEMES_LEN; ++i) { + if (strncmp(str, SCHEMES[i], strlen(SCHEMES[i]))) continue; + len = strcspn(str, " >\""); + push(str, len); + } + str = &str[len]; + } +} + +void urlList(void) { + uiHide(); + for (size_t i = 0; i < RING_LEN; ++i) { + char *url = ring[(i + last) & (RING_LEN - 1)]; + if (url) printf("%s\n", url); + } +} + +void urlOpen(size_t i) { + char *url = ring[(last - i) & (RING_LEN - 1)]; + if (!url) return; + + int fd[2]; + int error = pipe(fd); + if (error) err(EX_OSERR, "pipe"); + + pid_t pid = fork(); + if (pid < 0) err(EX_OSERR, "fork"); + + if (!pid) { + close(STDIN_FILENO); + dup2(fd[1], STDOUT_FILENO); + dup2(fd[1], STDERR_FILENO); + execlp("open", "open", url, NULL); + perror("open"); + exit(EX_CONFIG); + } + close(fd[1]); + + // FIXME: This should technically go on the main event loop. + char buf[256]; + ssize_t len = read(fd[0], buf, sizeof(buf) - 1); + if (len < 0) err(EX_IOERR, "read"); + if (len) { + buf[len] = '\0'; + len = strcspn(buf, "\n"); + uiFmt("%.*s", (int)len, buf); + } + close(fd[0]); +} -- cgit 1.4.1