summaryrefslogtreecommitdiffstats
path: root/src/lib/home-expand.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/home-expand.c')
-rw-r--r--src/lib/home-expand.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/lib/home-expand.c b/src/lib/home-expand.c
new file mode 100644
index 0000000..282ede9
--- /dev/null
+++ b/src/lib/home-expand.c
@@ -0,0 +1,72 @@
+/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "ipwd.h"
+#include "home-expand.h"
+
+
+int home_try_expand(const char **_path)
+{
+ const char *path = *_path;
+ const char *name, *home, *p;
+ struct passwd pw;
+
+ if (path == NULL || *path != '~')
+ return 0;
+
+ path++;
+ if (*path == '/' || *path == '\0') {
+ home = getenv("HOME");
+ if (*path != '\0') path++;
+ } else {
+ p = strchr(path, '/');
+ if (p == NULL) {
+ name = path;
+ path = "";
+ } else {
+ name = t_strdup_until(path, p);
+ path = p+1;
+ }
+ switch (i_getpwnam(name, &pw)) {
+ case -1:
+ i_error("getpwnam(%s) failed: %m", name);
+ home = NULL;
+ break;
+ case 0:
+ home = NULL;
+ break;
+ default:
+ home = pw.pw_dir;
+ break;
+ }
+ }
+
+ if (home == NULL)
+ return -1;
+
+ if (*path == '\0')
+ *_path = t_strdup(home);
+ else
+ *_path = t_strconcat(home, "/", path, NULL);
+ return 0;
+}
+
+const char *home_expand(const char *path)
+{
+ (void)home_try_expand(&path);
+ return path;
+}
+
+const char *home_expand_tilde(const char *path, const char *home)
+{
+ if (path == NULL || *path != '~')
+ return path;
+
+ if (path[1] == '\0')
+ return home;
+ if (path[1] != '/')
+ return path;
+
+ /* ~/ used */
+ return t_strconcat(home, path + 1, NULL);
+}