1 /* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "ipwd.h"
5 #include "home-expand.h"
6 
7 
home_try_expand(const char ** _path)8 int home_try_expand(const char **_path)
9 {
10 	const char *path = *_path;
11 	const char *name, *home, *p;
12 	struct passwd pw;
13 
14 	if (path == NULL || *path != '~')
15 		return 0;
16 
17 	path++;
18 	if (*path == '/' || *path == '\0') {
19 		home = getenv("HOME");
20 		if (*path != '\0') path++;
21 	} else {
22 		p = strchr(path, '/');
23 		if (p == NULL) {
24 			name = path;
25 			path = "";
26 		} else {
27 			name = t_strdup_until(path, p);
28 			path = p+1;
29 		}
30 		switch (i_getpwnam(name, &pw)) {
31 		case -1:
32 			i_error("getpwnam(%s) failed: %m", name);
33 			home = NULL;
34 			break;
35 		case 0:
36 			home = NULL;
37 			break;
38 		default:
39 			home = pw.pw_dir;
40 			break;
41 		}
42 	}
43 
44 	if (home == NULL)
45 		return -1;
46 
47 	if (*path == '\0')
48 		*_path = t_strdup(home);
49 	else
50 		*_path = t_strconcat(home, "/", path, NULL);
51 	return 0;
52 }
53 
home_expand(const char * path)54 const char *home_expand(const char *path)
55 {
56 	(void)home_try_expand(&path);
57 	return path;
58 }
59 
home_expand_tilde(const char * path,const char * home)60 const char *home_expand_tilde(const char *path, const char *home)
61 {
62 	if (path == NULL || *path != '~')
63 		return path;
64 
65 	if (path[1] == '\0')
66 		return home;
67 	if (path[1] != '/')
68 		return path;
69 
70 	/* ~/ used */
71 	return t_strconcat(home, path + 1, NULL);
72 }
73