Split the home-directory logic of `config_userconf' into its own file.
Arrange to only calculate the home directory once.
Most invasively, use this new functionality in place of looking up
`$HOME' and building pathnames by hand.
This change doesn't add much functionality, but it does add a little.
Most notably,
$ unset HOME; disobedience
doesn't segfault any more. More subtly, the logic for finding one's
home directory is now consistent. On Windows, we still use `%APPDATA%';
on Unix, we now /always/ use `$HOME' first, and then fall back to
`getpwuid(getuid)->pw_dir' if that's unset. Previously, the
configuration reader would ignore `$HOME' and use the password database,
while Disobedience used `$HOME' exclusively and crashed if it was
unset. This is all obviously silly.
#include "defs.h"
#include "configuration.h"
#include "hash.h"
+#include "home.h"
#include "selection.h"
#include "kvp.h"
#include "eventdist.h"
/** @brief Initialize @ref rtp_socket and @ref rtp_log if necessary */
static void rtp_init(void) {
if(!rtp_socket) {
- const char *home = getenv("HOME");
- char *dir, *instance;
-
- byte_xasprintf(&dir, "%s/.disorder/", home);
+ const char *dir, *instance;
+ if(!(dir = profile_directory()))
+ disorder_fatal(0, "failed to find profile directory");
mkdir(dir, 02700);
instance = substitute_instance_name();
- byte_xasprintf(&rtp_socket, "%s%s", dir, instance);
- byte_xasprintf(&rtp_log, "%s%s.log", dir, instance);
+ byte_xasprintf(&rtp_socket, "%s/%s", dir, instance);
+ byte_xasprintf(&rtp_log, "%s/%s.log", dir, instance);
}
}
static char *rtp_config_file(void) {
static char *rtp_config;
- const char *home = getenv("HOME");
if(!rtp_config)
- byte_xasprintf(&rtp_config, "%s/.disorder/api", home);
+ rtp_config = profile_filename("api");
return rtp_config;
}
}
void save_settings(void) {
- char *dir, *path, *tmp;
+ const char *dir;
+ char *path, *tmp;
FILE *fp = 0;
size_t n, m, c;
- byte_xasprintf(&dir, "%s/.disorder", getenv("HOME"));
+ if(!(dir = profile_directory())) {
+ fpopup_msg(GTK_MESSAGE_ERROR, "failed to find home directory");
+ goto done;
+ }
byte_xasprintf(&path, "%s/disobedience", dir);
byte_xasprintf(&tmp, "%s.tmp", path);
mkdir(dir, 02700); /* make sure directory exists */
int nvec;
size_t n, m, c;
- byte_xasprintf(&path, "%s/.disorder/disobedience", getenv("HOME"));
- if(!(fp = fopen(path, "r"))) {
+ if(!(path = profile_filename("disobedience")))
+ fpopup_msg(GTK_MESSAGE_ERROR, "failed to find home directory");
+ else if(!(fp = fopen(path, "r"))) {
if(errno != ENOENT)
fpopup_msg(GTK_MESSAGE_ERROR, "error opening %s: %s",
path, strerror(errno));
hash.c hash.h \
heap.h \
hex.c hex.h \
+ home.c home.h \
hostname.c hostname.h \
hreader.h \
ifreq.c ifreq.h \
# include <langinfo.h>
#endif
-#if HAVE_SHLOBJ_H
-# include <Shlobj.h>
-#endif
#include <signal.h>
#include "rights.h"
#include "log.h"
#include "split.h"
#include "syscalls.h"
+#include "home.h"
#include "table.h"
#include "inputline.h"
#include "charset.h"
/** @brief Return the path to user's personal configuration file */
char *config_userconf(void) {
- char *s;
-#if _WIN32
- wchar_t *wpath = 0;
- char *appdata;
- if(SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &wpath) != S_OK)
- disorder_fatal(0, "error calling SHGetKnownFolderPath");
- appdata = win_wtomb(wpath);
- CoTaskMemFree(wpath);
- byte_xasprintf(&s, "%s\\DisOrder\\passwd", appdata);
-#else
- struct passwd *pw;
- if(!(pw = getpwuid(getuid())))
- disorder_fatal(0, "cannot determine our username");
- byte_xasprintf(&s, "%s/.disorder/passwd", pw->pw_dir);
-#endif
- return s;
+ return profile_filename("passwd");
}
#if !_WIN32
--- /dev/null
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2020 Mark Wooding
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+/** @file lib/home.c
+ * @brief Find things in the user's home directory
+ */
+
+#include "common.h"
+
+#include <errno.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if HAVE_PWD_H
+# include <pwd.h>
+#endif
+#if HAVE_SHLOBJ_H
+# include <Shlobj.h>
+#endif
+
+#include "mem.h"
+#include "home.h"
+#include "log.h"
+#include "printf.h"
+
+#if _WIN32
+# define DIRSEP "\\"
+#else
+# define DIRSEP "/"
+#endif
+
+static char *profiledir;
+
+
+/** @brief Return the user's profile directory
+ * @return profile directory
+ * On Unix, this defaults to `$HOME/.disorder/'; on Windows, it's
+ * `%APPDATA%\DisOrder\'. The trailing delimiter is included.
+ */
+const char *profile_directory(void) {
+ char *t;
+
+ if(profiledir) return profiledir;
+#if _WIN32
+ wchar_t *wpath = 0;
+ char *appdata;
+ if(SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &wpath) != S_OK) {
+ disorder_error(0, "error calling SHGetKnownFolderPath");
+ return 0;
+ }
+ t = win_wtomb(wpath);
+ CoTaskMemFree(wpath);
+ byte_xasprintf(&profiledir, "%s\\DisOrder", appdata);
+#else
+ struct passwd *pw;
+ if(!(t = getenv("HOME"))) {
+ if(!(pw = getpwuid(getuid())))
+ disorder_error(0, "user not found in password database");
+ t = pw->pw_dir;
+ }
+ byte_xasprintf(&profiledir, "%s/.disorder", t);
+#endif
+ return profiledir;
+}
+
+/** @brief Return the name of a file within the user's profile directory
+ * @param file Basename of the file desired
+ * @return Full path name of selected file.
+ * This currently doesn't do anything very useful with directory separators
+ * within @a file.
+ */
+char *profile_filename(const char *file) {
+ const char *d;
+ char *t;
+ if(!(d = profile_directory())) return 0;
+ byte_xasprintf(&t, "%s" DIRSEP "%s", d, file);
+ return t;
+}
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/
--- /dev/null
+/*
+ * This file is part of DisOrder
+ * Copyright (C) 2007 Richard Kettlewell
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+/** @file lib/home.h
+ * @brief Find things in the user's home directory
+ */
+
+#ifndef HOME_H
+#define HOME_H
+
+const char *profile_directory(void);
+char *profile_filename(const char *file);
+
+#endif /* HOME_H */
+
+/*
+Local Variables:
+c-basic-offset:2
+comment-column:40
+fill-column:79
+indent-tabs-mode:nil
+End:
+*/