Blob
Date:
Sun Apr 24 12:14:54 2022
UTC
Message:
move load session stuff to session.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.*//** Handles config and runtime files*/#include "compat.h"#include <sys/stat.h>#include <sys/types.h>#include <dirent.h>#include <errno.h>#include <limits.h>#include <libgen.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "pages.h"#include "parser.h"#include "session.h"#include "telescope.h"#include "utils.h"#include "fs.h"#ifndef nitems#define nitems(x) (sizeof(x) / sizeof(x[0]))#endifstatic int select_non_dot(const struct dirent *);static int select_non_dotdot(const struct dirent *);static size_t join_path(char*, const char*, const char*, size_t);static void getenv_default(char*, const char*, const char*, size_t);static void mkdirs(const char*, mode_t);static void init_paths(void);/** Where to store user data. These are all equal to ~/.telescope if* it exists.*/char config_path_base[PATH_MAX];char data_path_base[PATH_MAX];char cache_path_base[PATH_MAX];char ctlsock_path[PATH_MAX];char config_path[PATH_MAX];char lockfile_path[PATH_MAX];char bookmark_file[PATH_MAX];char known_hosts_file[PATH_MAX], known_hosts_tmp[PATH_MAX];char crashed_file[PATH_MAX];char session_file[PATH_MAX], session_file_tmp[PATH_MAX];char history_file[PATH_MAX], history_file_tmp[PATH_MAX];static intselect_non_dot(const struct dirent *d){return strcmp(d->d_name, ".");}static intselect_non_dotdot(const struct dirent *d){return strcmp(d->d_name, ".") && strcmp(d->d_name, "..");}static voidsend_dir(struct tab *tab, const char *path){struct dirent **names;int (*selector)(const struct dirent *) = select_non_dot;int i, len;#if notyet/** need something to fake a redirect*/if (!has_suffix(path, "/")) {if (asprintf(&s, "%s/", path) == -1)die();send_hdr(peerid, 30, s);free(s);return;}#endifif (!strcmp(path, "/"))selector = select_non_dotdot;if ((len = scandir(path, &names, selector, alphasort)) == -1) {load_page_from_str(tab, "# failure reading the directory\n");return;}parser_init(tab, gemtext_initparser);parser_parsef(tab, "# Index of %s\n\n", path);for (i = 0; i < len; ++i) {const char *sufx = "";if (names[i]->d_type == DT_DIR)sufx = "/";parser_parsef(tab, "=> %s%s\n", names[i]->d_name, sufx);}parser_free(tab);free(names);}static intis_dir(FILE *fp){struct stat sb;if (fstat(fileno(fp), &sb) == -1)return 0;return S_ISDIR(sb.st_mode);}static parserinitfile_type(const char *path){const struct mapping {const char *ext;parserinit fn;} ms[] = {{"diff", textpatch_initparser},{"gemini", gemtext_initparser},{"gmi", gemtext_initparser},{"markdown", textplain_initparser},{"md", textplain_initparser},{"patch", gemtext_initparser},{NULL, NULL},}, *m;const char *dot;if ((dot = strrchr(path, '.')) == NULL)return textplain_initparser;dot++;for (m = ms; m->ext != NULL; ++m)if (!strcmp(m->ext, dot))return m->fn;return textplain_initparser;}voidfs_load_url(struct tab *tab, const char *url){const char *bpath = "bookmarks.gmi", *fallback = "# Not found\n";parserinit initfn = gemtext_initparser;char path[PATH_MAX];FILE *fp = NULL;size_t i;char buf[BUFSIZ];struct page {const char *name;const char *path;const uint8_t *data;size_t len;} pages[] = {{"about", NULL, about_about, about_about_len},{"blank", NULL, about_blank, about_blank_len},{"bookmarks", bpath, bookmarks, bookmarks_len},{"crash", NULL, about_crash, about_crash_len},{"help", NULL, about_help, about_help_len},{"license", NULL, about_license, about_license_len},{"new", NULL, about_new, about_new_len},}, *page = NULL;if (!strncmp(url, "about:", 6)) {url += 6;for (i = 0; page == NULL && i < nitems(pages); ++i) {if (!strcmp(url, pages[i].name))page = &pages[i];}if (page == NULL)goto done;strlcpy(path, data_path_base, sizeof(path));strlcat(path, "/", sizeof(path));if (page->path != NULL)strlcat(path, page->path, sizeof(path));else {strlcat(path, "page/about_", sizeof(path));strlcat(path, page->name, sizeof(path));strlcat(path, ".gmi", sizeof(path));}fallback = page->data;} else if (!strncmp(url, "file://", 7)) {url += 7;strlcpy(path, url, sizeof(path));initfn = file_type(url);} elsegoto done;if ((fp = fopen(path, "r")) == NULL)goto done;if (is_dir(fp)) {fclose(fp);send_dir(tab, path);goto done;}parser_init(tab, initfn);for (;;) {size_t r;r = fread(buf, 1, sizeof(buf), fp);if (!parser_parse(tab, buf, r))break;if (r != sizeof(buf))break;}parser_free(tab);done:if (fp != NULL)fclose(fp);elseload_page_from_str(tab, fallback);}static size_tjoin_path(char *buf, const char *lhs, const char *rhs, size_t buflen){strlcpy(buf, lhs, buflen);return strlcat(buf, rhs, buflen);}static voidgetenv_default(char *buf, const char *name, const char *def, size_t buflen){size_t ret;char *home, *env;if ((home = getenv("HOME")) == NULL)errx(1, "HOME is not defined");if ((env = getenv(name)) != NULL)ret = strlcpy(buf, env, buflen);elseret = join_path(buf, home, def, buflen);if (ret >= buflen)errx(1, "buffer too small for %s", name);}static voidmkdirs(const char *path, mode_t mode){char copy[PATH_MAX+1], orig[PATH_MAX+1], *parent;strlcpy(copy, path, sizeof(copy));strlcpy(orig, path, sizeof(orig));parent = dirname(copy);if (!strcmp(parent, "/"))return;mkdirs(parent, mode);if (mkdir(orig, mode) != 0) {if (errno == EEXIST)return;err(1, "can't mkdir %s", orig);}}static voidinit_paths(void){char xdg_config_base[PATH_MAX];char xdg_data_base[PATH_MAX];char xdg_cache_base[PATH_MAX];char old_path[PATH_MAX];char *home;struct stat info;/* old path */if ((home = getenv("HOME")) == NULL)errx(1, "HOME is not defined");join_path(old_path, home, "/.telescope", sizeof(old_path));/* if ~/.telescope exists, use that instead of xdg dirs */if (stat(old_path, &info) == 0 && S_ISDIR(info.st_mode)) {join_path(config_path_base, home, "/.telescope",sizeof(config_path_base));join_path(data_path_base, home, "/.telescope",sizeof(data_path_base));join_path(cache_path_base, home, "/.telescope",sizeof(cache_path_base));return;}/* xdg paths */getenv_default(xdg_config_base, "XDG_CONFIG_HOME", "/.config",sizeof(xdg_config_base));getenv_default(xdg_data_base, "XDG_DATA_HOME", "/.local/share",sizeof(xdg_data_base));getenv_default(xdg_cache_base, "XDG_CACHE_HOME", "/.cache",sizeof(xdg_cache_base));join_path(config_path_base, xdg_config_base, "/telescope",sizeof(config_path_base));join_path(data_path_base, xdg_data_base, "/telescope",sizeof(data_path_base));join_path(cache_path_base, xdg_cache_base, "/telescope",sizeof(cache_path_base));mkdirs(xdg_config_base, S_IRWXU);mkdirs(xdg_data_base, S_IRWXU);mkdirs(xdg_cache_base, S_IRWXU);mkdirs(config_path_base, S_IRWXU);mkdirs(data_path_base, S_IRWXU);mkdirs(cache_path_base, S_IRWXU);}intfs_init(void){init_paths();join_path(ctlsock_path, cache_path_base, "/ctl",sizeof(ctlsock_path));join_path(config_path, config_path_base, "/config",sizeof(config_path));join_path(lockfile_path, cache_path_base, "/lock",sizeof(lockfile_path));join_path(bookmark_file, data_path_base, "/bookmarks.gmi",sizeof(bookmark_file));join_path(known_hosts_file, data_path_base, "/known_hosts",sizeof(known_hosts_file));join_path(known_hosts_tmp, cache_path_base,"/known_hosts.tmp.XXXXXXXXXX", sizeof(known_hosts_tmp));join_path(session_file, cache_path_base, "/session",sizeof(session_file));join_path(session_file_tmp, cache_path_base, "/session.XXXXXXXXXX",sizeof(session_file));join_path(history_file, cache_path_base, "/history",sizeof(history_file));join_path(history_file_tmp, cache_path_base, "/history.XXXXXXXXXX",sizeof(history_file));join_path(crashed_file, cache_path_base, "/crashed",sizeof(crashed_file));return 1;}
Omar Polo