From 34569e2b623df164ee965aa508fed274c7c15aaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Wed, 1 Jul 2015 23:22:07 +0200
Subject: [PATCH] Do tilde expansion in resolve_config_filename()
---
liberty.c | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/liberty.c b/liberty.c
index 1ae9df4..a9f30aa 100644
--- a/liberty.c
+++ b/liberty.c
@@ -46,6 +46,7 @@
#include
#include
#include
+#include
#include
#include
@@ -2193,6 +2194,37 @@ get_xdg_config_dirs (struct str_vector *out)
split_str_ignore_empty (xdg_config_dirs, ':', out);
}
+static char *
+try_expand_tilde (const char *filename)
+{
+ size_t until_slash = strcspn (filename, "/");
+ if (!until_slash)
+ {
+ struct str expanded;
+ str_init (&expanded);
+ str_append_env_path (&expanded, "HOME", false);
+ str_append (&expanded, filename);
+ return str_steal (&expanded);
+ }
+
+ int buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);
+ if (buf_len < 0)
+ buf_len = 1024;
+ struct passwd pwd, *success = NULL;
+
+ char *user = xstrndup (filename, until_slash);
+ char *buf = xmalloc (buf_len);
+ while (getpwnam_r (user, &pwd, buf, buf_len, &success) == ERANGE)
+ buf = xrealloc (buf, buf_len <<= 1);
+ free (user);
+
+ char *result = NULL;
+ if (success)
+ result = xstrdup_printf ("%s%s", pwd.pw_dir, filename + until_slash);
+ free (buf);
+ return result;
+}
+
static char *
resolve_config_filename (const char *filename)
{
@@ -2200,6 +2232,16 @@ resolve_config_filename (const char *filename)
if (*filename == '/')
return xstrdup (filename);
+ // We don't want to use wordexp() for this as it may execute /bin/sh
+ if (*filename == '~')
+ {
+ // Paths to home directories ought to be absolute
+ char *expanded = try_expand_tilde (filename + 1);
+ if (expanded)
+ return expanded;
+ print_debug ("failed to expand the home directory in `%s'", filename);
+ }
+
struct str_vector paths;
str_vector_init (&paths);
get_xdg_config_dirs (&paths);