summary refs log tree commit diff
diff options
context:
space:
mode:
authorC. McEnroe2020-02-10 19:57:10 -0500
committerC. McEnroe2020-02-10 19:57:10 -0500
commit99480a42e56e70707822934ffeb56f0454afc127 (patch)
tree798c7d1bc8193dccc745682cb4e76d60610fb2ed
parente6c18403e22bde5a785b7172903f640d03cb8a35 (diff)
Factor out XDG base directory code
And add warnings to configOpen, since that's the only way to be accurate
if a weird error occurs.
-rw-r--r--Makefile1
-rw-r--r--chat.c4
-rw-r--r--chat.h2
-rw-r--r--config.c41
-rw-r--r--ui.c67
-rw-r--r--xdg.c134
6 files changed, 140 insertions, 109 deletions
diff --git a/Makefile b/Makefile
index 89af9b3..b1ffede 100644
--- a/Makefile
+++ b/Makefile
@@ -15,6 +15,7 @@ OBJS += handle.o
 OBJS += irc.o
 OBJS += ui.o
 OBJS += url.o
+OBJS += xdg.o
 
 dev: tags all
 
diff --git a/chat.c b/chat.c
index e8713bb..1ae7090 100644
--- a/chat.c
+++ b/chat.c
@@ -154,11 +154,11 @@ int main(int argc, char *argv[]) {
 	FILE *privFile = NULL;
 	if (cert) {
 		certFile = configOpen(cert, "r");
-		if (!certFile) err(EX_NOINPUT, "%s", cert);
+		if (!certFile) return EX_NOINPUT;
 	}
 	if (priv) {
 		privFile = configOpen(priv, "r");
-		if (!privFile) err(EX_NOINPUT, "%s", priv);
+		if (!privFile) return EX_NOINPUT;
 	}
 	ircConfig(insecure, certFile, privFile);
 	if (certFile) fclose(certFile);
diff --git a/chat.h b/chat.h
index 47a6163..03a0a50 100644
--- a/chat.h
+++ b/chat.h
@@ -189,6 +189,8 @@ void urlOpenMatch(size_t id, const char *str);
 void urlCopyMatch(size_t id, const char *str);
 
 FILE *configOpen(const char *path, const char *mode);
+FILE *dataOpen(const char *path, const char *mode);
+
 int getopt_config(
 	int argc, char *const *argv,
 	const char *optstring, const struct option *longopts, int *longindex
diff --git a/config.c b/config.c
index 3bf56c0..3a87948 100644
--- a/config.c
+++ b/config.c
@@ -24,42 +24,6 @@
 
 #include "chat.h"
 
-FILE *configOpen(const char *path, const char *mode) {
-	if (path[0] == '/' || path[0] == '.') goto local;
-
-	const char *home = getenv("HOME");
-	const char *configHome = getenv("XDG_CONFIG_HOME");
-	const char *configDirs = getenv("XDG_CONFIG_DIRS");
-
-	char buf[PATH_MAX];
-	if (configHome) {
-		snprintf(buf, sizeof(buf), "%s/" XDG_SUBDIR "/%s", configHome, path);
-	} else {
-		if (!home) goto local;
-		snprintf(buf, sizeof(buf), "%s/.config/" XDG_SUBDIR "/%s", home, path);
-	}
-	FILE *file = fopen(buf, mode);
-	if (file) return file;
-	if (errno != ENOENT) return NULL;
-
-	if (!configDirs) configDirs = "/etc/xdg";
-	while (*configDirs) {
-		size_t len = strcspn(configDirs, ":");
-		snprintf(
-			buf, sizeof(buf), "%.*s/" XDG_SUBDIR "/%s",
-			(int)len, configDirs, path
-		);
-		file = fopen(buf, mode);
-		if (file) return file;
-		if (errno != ENOENT) return NULL;
-		configDirs += len;
-		if (*configDirs) configDirs++;
-	}
-
-local:
-	return fopen(path, mode);
-}
-
 #define WS "\t "
 
 static const char *path;
@@ -92,10 +56,7 @@ int getopt_config(
 				num = 0;
 				path = argv[optind++];
 				file = configOpen(path, "r");
-				if (!file) {
-					warn("%s", path);
-					return clean('?');
-				}
+				if (!file) return clean('?');
 			} else {
 				return clean(-1);
 			}
diff --git a/ui.c b/ui.c
index ecf7e60..9601aaa 100644
--- a/ui.c
+++ b/ui.c
@@ -21,13 +21,11 @@
 #include <curses.h>
 #include <err.h>
 #include <errno.h>
-#include <limits.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <sysexits.h>
 #include <term.h>
 #include <termios.h>
@@ -858,71 +856,6 @@ void uiRead(void) {
 	inputUpdate();
 }
 
-static FILE *dataOpen(const char *path, const char *mode) {
-	if (path[0] == '/' || path[0] == '.') goto local;
-
-	const char *home = getenv("HOME");
-	const char *dataHome = getenv("XDG_DATA_HOME");
-	const char *dataDirs = getenv("XDG_DATA_DIRS");
-
-	char homePath[PATH_MAX];
-	if (dataHome) {
-		snprintf(
-			homePath, sizeof(homePath),
-			"%s/" XDG_SUBDIR "/%s", dataHome, path
-		);
-	} else {
-		if (!home) goto local;
-		snprintf(
-			homePath, sizeof(homePath),
-			"%s/.local/share/" XDG_SUBDIR "/%s", home, path
-		);
-	}
-	FILE *file = fopen(homePath, mode);
-	if (file) return file;
-	if (errno != ENOENT) {
-		warn("%s", homePath);
-		return NULL;
-	}
-
-	char buf[PATH_MAX];
-	if (!dataDirs) dataDirs = "/usr/local/share:/usr/share";
-	while (*dataDirs) {
-		size_t len = strcspn(dataDirs, ":");
-		snprintf(
-			buf, sizeof(buf), "%.*s/" XDG_SUBDIR "/%s",
-			(int)len, dataDirs, path
-		);
-		file = fopen(buf, mode);
-		if (file) return file;
-		if (errno != ENOENT) {
-			warn("%s", buf);
-			return NULL;
-		}
-		dataDirs += len;
-		if (*dataDirs) dataDirs++;
-	}
-
-	if (mode[0] != 'r') {
-		char *base = strrchr(homePath, '/');
-		*base = '\0';
-		int error = mkdir(homePath, S_IRWXU);
-		if (error && errno != EEXIST) {
-			warn("%s", homePath);
-			return NULL;
-		}
-		*base = '/';
-		file = fopen(homePath, mode);
-		if (!file) warn("%s", homePath);
-		return file;
-	}
-
-local:
-	file = fopen(path, mode);
-	if (!file) warn("%s", path);
-	return file;
-}
-
 static const size_t Signatures[] = {
 	0x6C72696774616301,
 };
diff --git a/xdg.c b/xdg.c
new file mode 100644
index 0000000..6e33210
--- /dev/null
+++ b/xdg.c
@@ -0,0 +1,134 @@
+/* Copyright (C) 2019, 2020  C. McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "chat.h"
+
+FILE *configOpen(const char *path, const char *mode) {
+	if (path[0] == '/' || path[0] == '.') goto local;
+
+	const char *home = getenv("HOME");
+	const char *configHome = getenv("XDG_CONFIG_HOME");
+	const char *configDirs = getenv("XDG_CONFIG_DIRS");
+
+	char buf[PATH_MAX];
+	if (configHome) {
+		snprintf(buf, sizeof(buf), "%s/" XDG_SUBDIR "/%s", configHome, path);
+	} else {
+		if (!home) goto local;
+		snprintf(buf, sizeof(buf), "%s/.config/" XDG_SUBDIR "/%s", home, path);
+	}
+	FILE *file = fopen(buf, mode);
+	if (file) return file;
+	if (errno != ENOENT) {
+		warn("%s", buf);
+		return NULL;
+	}
+
+	if (!configDirs) configDirs = "/etc/xdg";
+	while (*configDirs) {
+		size_t len = strcspn(configDirs, ":");
+		snprintf(
+			buf, sizeof(buf), "%.*s/" XDG_SUBDIR "/%s",
+			(int)len, configDirs, path
+		);
+		file = fopen(buf, mode);
+		if (file) return file;
+		if (errno != ENOENT) {
+			warn("%s", buf);
+			return NULL;
+		}
+		configDirs += len;
+		if (*configDirs) configDirs++;
+	}
+
+local:
+	file = fopen(path, mode);
+	if (!file) warn("%s", path);
+	return file;
+}
+
+FILE *dataOpen(const char *path, const char *mode) {
+	if (path[0] == '/' || path[0] == '.') goto local;
+
+	const char *home = getenv("HOME");
+	const char *dataHome = getenv("XDG_DATA_HOME");
+	const char *dataDirs = getenv("XDG_DATA_DIRS");
+
+	char homePath[PATH_MAX];
+	if (dataHome) {
+		snprintf(
+			homePath, sizeof(homePath),
+			"%s/" XDG_SUBDIR "/%s", dataHome, path
+		);
+	} else {
+		if (!home) goto local;
+		snprintf(
+			homePath, sizeof(homePath),
+			"%s/.local/share/" XDG_SUBDIR "/%s", home, path
+		);
+	}
+	FILE *file = fopen(homePath, mode);
+	if (file) return file;
+	if (errno != ENOENT) {
+		warn("%s", homePath);
+		return NULL;
+	}
+
+	char buf[PATH_MAX];
+	if (!dataDirs) dataDirs = "/usr/local/share:/usr/share";
+	while (*dataDirs) {
+		size_t len = strcspn(dataDirs, ":");
+		snprintf(
+			buf, sizeof(buf), "%.*s/" XDG_SUBDIR "/%s",
+			(int)len, dataDirs, path
+		);
+		file = fopen(buf, mode);
+		if (file) return file;
+		if (errno != ENOENT) {
+			warn("%s", buf);
+			return NULL;
+		}
+		dataDirs += len;
+		if (*dataDirs) dataDirs++;
+	}
+
+	if (mode[0] != 'r') {
+		char *base = strrchr(homePath, '/');
+		*base = '\0';
+		int error = mkdir(homePath, S_IRWXU);
+		if (error && errno != EEXIST) {
+			warn("%s", homePath);
+			return NULL;
+		}
+		*base = '/';
+		file = fopen(homePath, mode);
+		if (!file) warn("%s", homePath);
+		return file;
+	}
+
+local:
+	file = fopen(path, mode);
+	if (!file) warn("%s", path);
+	return file;
+}