chiark / gitweb /
lib/home.c: Introduce functions for building pathmames in home directories.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 4 Jun 2020 19:13:11 +0000 (20:13 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 15 Jun 2020 11:58:53 +0000 (12:58 +0100)
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.

disobedience/disobedience.h
disobedience/rtp.c
disobedience/settings.c
lib/Makefile.am
lib/configuration.c
lib/home.c [new file with mode: 0644]
lib/home.h [new file with mode: 0644]

index ab74592932efba1170d9835ab48cc7b130b2090f..94e302287fae209ba7a5f4d99c38cb433e95715b 100644 (file)
@@ -42,6 +42,7 @@
 #include "defs.h"
 #include "configuration.h"
 #include "hash.h"
+#include "home.h"
 #include "selection.h"
 #include "kvp.h"
 #include "eventdist.h"
index 40e1ea203232fbdcd2c108d3509b021e310ca13e..3629b67e5bcf5d80fe8fe8e6fa42ffacda8263e7 100644 (file)
@@ -65,14 +65,13 @@ static char *substitute_instance_name(void) {
 /** @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);
   }
 }
 
@@ -202,9 +201,8 @@ void stop_rtp(void) {
 
 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;
 }
 
index 2c4ffeb3c32f2d2e50e680e8d28ce8e03579918c..18af6c1c8e590cc78593bacfeeab0e09ed29f09d 100644 (file)
@@ -150,11 +150,15 @@ void init_styles(void) {
 }
 
 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 */
@@ -206,8 +210,9 @@ void load_settings(void) {
   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));
index a6a362fb9406fe96663d309d2e105712d7908d68..249bd98b79b32e45134c1fab538142655b991fca 100644 (file)
@@ -52,6 +52,7 @@ libdisorder_a_SOURCES=charset.c charsetf.c charset.h  \
        hash.c hash.h                                   \
        heap.h                                          \
        hex.c hex.h                                     \
+       home.c home.h                                   \
        hostname.c hostname.h                           \
        hreader.h                                       \
        ifreq.c ifreq.h                                 \
index b5561dc1ade3e9cd88189bb65a87b474e58ad115..17f9ec7b4ed137f4f3b60aed9de3dac574b51233 100644 (file)
@@ -37,9 +37,6 @@
 # include <langinfo.h>
 #endif
 
-#if HAVE_SHLOBJ_H
-# include <Shlobj.h>
-#endif
 #include <signal.h>
 
 #include "rights.h"
@@ -48,6 +45,7 @@
 #include "log.h"
 #include "split.h"
 #include "syscalls.h"
+#include "home.h"
 #include "table.h"
 #include "inputline.h"
 #include "charset.h"
@@ -1673,22 +1671,7 @@ char *config_private(void) {
 
 /** @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
diff --git a/lib/home.c b/lib/home.c
new file mode 100644 (file)
index 0000000..5426f76
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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:
+*/
diff --git a/lib/home.h b/lib/home.h
new file mode 100644 (file)
index 0000000..1956808
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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:
+*/