From b6cf41ab77a4324b4f4cf0bc9e3d82a5fef9ebd4 Mon Sep 17 00:00:00 2001 From: C. McEnroe Date: Sat, 16 Oct 2021 17:03:31 -0400 Subject: Import refactored xdg.c from pounce --- chat.c | 4 +-- chat.h | 5 ++-- irc.c | 22 ++++++++-------- log.c | 15 +++++++---- xdg.c | 91 +++++++++++++++++++++++++++++++----------------------------------- 5 files changed, 67 insertions(+), 70 deletions(-) diff --git a/chat.c b/chat.c index 54e7e5e..ba6c9a1 100644 --- a/chat.c +++ b/chat.c @@ -149,8 +149,8 @@ static void sandboxEarly(bool log) { char *end = &promises[sizeof(promises)]; if (log) { - const char *logdir = dataMkdir("log"); - int error = unveil(logdir, "wc"); + char buf[PATH_MAX]; + int error = unveil(dataPath(buf, sizeof(buf), "log", 0), "wc"); if (error) err(EX_OSERR, "unveil"); ptr = seprintf(ptr, end, " wpath cpath"); } diff --git a/chat.h b/chat.h index eec0e44..19d2b18 100644 --- a/chat.h +++ b/chat.h @@ -404,11 +404,10 @@ void logFormat(uint id, const time_t *time, const char *format, ...) __attribute__((format(printf, 3, 4))); void logClose(void); -const char *configPath(const char **dirs, const char *path); -const char *dataPath(const char **dirs, const char *path); +char *configPath(char *buf, size_t cap, const char *path, int i); +char *dataPath(char *buf, size_t cap, const char *path, int i); FILE *configOpen(const char *path, const char *mode); FILE *dataOpen(const char *path, const char *mode); -const char *dataMkdir(const char *path); int getopt_config( int argc, char *const *argv, diff --git a/irc.c b/irc.c index 8d5ae81..20e9f91 100644 --- a/irc.c +++ b/irc.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -49,19 +50,20 @@ static struct tls_config *config; void ircConfig( bool insecure, const char *trust, const char *cert, const char *priv ) { + int error = 0; + char buf[PATH_MAX]; + config = tls_config_new(); if (!config) errx(EX_SOFTWARE, "tls_config_new"); - int error = 0; if (insecure) { tls_config_insecure_noverifycert(config); tls_config_insecure_noverifyname(config); } if (trust) { tls_config_insecure_noverifyname(config); - const char *dirs = NULL; - for (const char *path; NULL != (path = configPath(&dirs, trust));) { - error = tls_config_set_ca_file(config, path); + for (int i = 0; configPath(buf, sizeof(buf), trust, i); ++i) { + error = tls_config_set_ca_file(config, buf); if (!error) break; } if (error) errx(EX_NOINPUT, "%s: %s", trust, tls_config_error(config)); @@ -79,21 +81,19 @@ void ircConfig( #endif if (cert) { - const char *dirs = NULL; - for (const char *path; NULL != (path = configPath(&dirs, cert));) { + for (int i = 0; configPath(buf, sizeof(buf), cert, i); ++i) { if (priv) { - error = tls_config_set_cert_file(config, path); + error = tls_config_set_cert_file(config, buf); } else { - error = tls_config_set_keypair_file(config, path, path); + error = tls_config_set_keypair_file(config, buf, buf); } if (!error) break; } if (error) errx(EX_NOINPUT, "%s: %s", cert, tls_config_error(config)); } if (priv) { - const char *dirs = NULL; - for (const char *path; NULL != (path = configPath(&dirs, priv));) { - error = tls_config_set_key_file(config, path); + for (int i = 0; configPath(buf, sizeof(buf), priv, i); ++i) { + error = tls_config_set_key_file(config, buf); if (!error) break; } if (error) errx(EX_NOINPUT, "%s: %s", priv, tls_config_error(config)); diff --git a/log.c b/log.c index c13293a..32d771f 100644 --- a/log.c +++ b/log.c @@ -47,10 +47,15 @@ static int logDir = -1; void logOpen(void) { - dataMkdir(""); - const char *path = dataMkdir("log"); - logDir = open(path, O_RDONLY | O_CLOEXEC); - if (logDir < 0) err(EX_CANTCREAT, "%s", path); + char buf[PATH_MAX]; + int error = mkdir(dataPath(buf, sizeof(buf), "", 0), S_IRWXU); + if (error && errno != EEXIST) err(EX_CANTCREAT, "%s", buf); + + error = mkdir(dataPath(buf, sizeof(buf), "log", 0), S_IRWXU); + if (error && errno != EEXIST) err(EX_CANTCREAT, "%s", buf); + + logDir = open(buf, O_RDONLY | O_CLOEXEC); + if (logDir < 0) err(EX_CANTCREAT, "%s", buf); #ifdef __FreeBSD__ cap_rights_t rights; @@ -58,7 +63,7 @@ void logOpen(void) { &rights, CAP_MKDIRAT, CAP_CREATE, CAP_WRITE, /* for fdopen(3) */ CAP_FCNTL, CAP_FSTAT ); - int error = caph_rights_limit(logDir, &rights); + error = caph_rights_limit(logDir, &rights); if (error) err(EX_OSERR, "cap_rights_limit"); #endif } diff --git a/xdg.c b/xdg.c index 6afeb35..06c242c 100644 --- a/xdg.c +++ b/xdg.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "chat.h" @@ -58,81 +59,73 @@ static const struct Base Data = { .defDirs = "/usr/local/share:/usr/share", }; -static const char * -basePath(struct Base base, const char **dirs, const char *path) { - static char buf[PATH_MAX]; - - if (*dirs) { - if (!**dirs) return NULL; - size_t len = strcspn(*dirs, ":"); - snprintf(buf, sizeof(buf), "%.*s/" SUBDIR "/%s", (int)len, *dirs, path); - *dirs += len; - if (**dirs) *dirs += 1; +static char *basePath( + struct Base base, char *buf, size_t cap, const char *path, int i +) { + if (path[strspn(path, ".")] == '/') { + if (i > 0) return NULL; + snprintf(buf, cap, "%s", path); return buf; } - if (path[strspn(path, ".")] == '/') { - *dirs = ""; - return path; + if (i > 0) { + const char *dirs = getenv(base.envDirs); + if (!dirs) dirs = base.defDirs; + for (; i > 1; --i) { + dirs += strcspn(dirs, ":"); + dirs += (*dirs == ':'); + } + if (!*dirs) return NULL; + snprintf( + buf, cap, "%.*s/" SUBDIR "/%s", + (int)strcspn(dirs, ":"), dirs, path + ); + return buf; } - *dirs = getenv(base.envDirs); - if (!*dirs) *dirs = base.defDirs; - const char *home = getenv("HOME"); const char *baseHome = getenv(base.envHome); if (baseHome) { - snprintf(buf, sizeof(buf), "%s/" SUBDIR "/%s", baseHome, path); + snprintf(buf, cap, "%s/" SUBDIR "/%s", baseHome, path); } else if (home) { - snprintf( - buf, sizeof(buf), "%s/%s/" SUBDIR "/%s", - home, base.defHome, path - ); + snprintf(buf, cap, "%s/%s/" SUBDIR "/%s", home, base.defHome, path); } else { - errx(EX_CONFIG, "HOME unset"); + errx(EX_USAGE, "HOME unset"); } return buf; } -const char *configPath(const char **dirs, const char *path) { - return basePath(Config, dirs, path); +char *configPath(char *buf, size_t cap, const char *path, int i) { + return basePath(Config, buf, cap, path, i); } -const char *dataPath(const char **dirs, const char *path) { - return basePath(Data, dirs, path); +char *dataPath(char *buf, size_t cap, const char *path, int i) { + return basePath(Data, buf, cap, path, i); } FILE *configOpen(const char *path, const char *mode) { - const char *dirs = NULL; - for (const char *abs; NULL != (abs = configPath(&dirs, path));) { - FILE *file = fopen(abs, mode); + char buf[PATH_MAX]; + for (int i = 0; configPath(buf, sizeof(buf), path, i); ++i) { + FILE *file = fopen(buf, mode); if (file) return file; - if (errno != ENOENT) warn("%s", abs); + if (errno != ENOENT) warn("%s", buf); } - dirs = NULL; - warn("%s", configPath(&dirs, path)); + warn("%s", configPath(buf, sizeof(buf), path, 0)); return NULL; } -const char *dataMkdir(const char *path) { - const char *dirs = NULL; - path = dataPath(&dirs, path); - int error = mkdir(path, S_IRWXU); - if (error && errno != EEXIST) err(EX_CANTCREAT, "%s", path); - return path; -} - FILE *dataOpen(const char *path, const char *mode) { - const char *dirs = NULL; - for (const char *abs; NULL != (abs = dataPath(&dirs, path));) { - FILE *file = fopen(abs, mode); + char buf[PATH_MAX]; + for (int i = 0; dataPath(buf, sizeof(buf), path, i); ++i) { + FILE *file = fopen(buf, mode); if (file) return file; - if (errno != ENOENT) warn("%s", abs); + if (errno != ENOENT) warn("%s", buf); + } + if (mode[0] != 'r') { + int error = mkdir(dataPath(buf, sizeof(buf), "", 0), S_IRWXU); + if (error && errno != EEXIST) warn("%s", buf); } - if (mode[0] != 'r') dataMkdir(""); - dirs = NULL; - path = dataPath(&dirs, path); - FILE *file = fopen(path, mode); - if (!file) warn("%s", path); + FILE *file = fopen(dataPath(buf, sizeof(buf), path, 0), mode); + if (!file) warn("%s", buf); return file; } -- cgit 1.4.1-2-gfad0