1 /* Get home directory */
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/stat.h> /* OS/2 needs this after sys/types.h */
12 #ifdef HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 
16 #include "elinks.h"
17 
18 #include "config/home.h"
19 #include "config/options.h"
20 #include "intl/gettext/libintl.h"
21 #include "main/main.h"
22 #include "osdep/osdep.h"
23 #include "util/memory.h"
24 #include "util/string.h"
25 
26 
27 unsigned char *elinks_home = NULL;
28 int first_use = 0;
29 
30 static inline void
strip_trailing_dir_sep(unsigned char * path)31 strip_trailing_dir_sep(unsigned char *path)
32 {
33 	int i;
34 
35 	for (i = strlen(path) - 1; i > 0; i--)
36 		if (!dir_sep(path[i]))
37 			break;
38 
39 	path[i + 1] = 0;
40 }
41 
42 static unsigned char *
test_confdir(unsigned char * home,unsigned char * path,unsigned char * error_message)43 test_confdir(unsigned char *home, unsigned char *path,
44 	     unsigned char *error_message)
45 {
46 	struct stat st;
47 	unsigned char *confdir;
48 
49 	if (!path || !*path) return NULL;
50 
51 	if (home && *home && !dir_sep(*path))
52 		confdir = straconcat(home, "/", path, NULL);
53 	else
54 		confdir = stracpy(path);
55 
56 	if (!confdir) return NULL;
57 
58 	strip_trailing_dir_sep(confdir);
59 
60 	if (stat(confdir, &st)) {
61 		if (!mkdir(confdir, 0700)) {
62 #if 0
63 		/* I've no idea if following is needed for newly created
64 		 * directories.  It's bad thing to do it everytime. --pasky */
65 #ifdef HAVE_CHMOD
66 			chmod(home_elinks, 0700);
67 #endif
68 #endif
69 			return confdir;
70 		}
71 
72 	} else if (S_ISDIR(st.st_mode)) {
73 		first_use = 0;
74 		return confdir;
75 	}
76 
77 	if (error_message) {
78 		usrerror(gettext(error_message), path, confdir);
79 		sleep(3);
80 	}
81 
82 	mem_free(confdir);
83 
84 	return NULL;
85 }
86 
87 /* TODO: Check possibility to use <libgen.h> dirname. */
88 static unsigned char *
elinks_dirname(unsigned char * path)89 elinks_dirname(unsigned char *path)
90 {
91 	int i;
92 	unsigned char *dir;
93 
94 	if (!path) return NULL;
95 
96 	dir = stracpy(path);
97 	if (!dir) return NULL;
98 
99 	for (i = strlen(dir) - 1; i >= 0; i--)
100 		if (dir_sep(dir[i]))
101 			break;
102 
103 	dir[i + 1] = 0;
104 
105 	return dir;
106 }
107 
108 static unsigned char *
get_home(void)109 get_home(void)
110 {
111 	unsigned char *home_elinks;
112 	unsigned char *envhome = getenv("HOME");
113 	unsigned char *home = envhome ? stracpy(envhome)
114 				      : elinks_dirname(program.path);
115 
116 	if (home)
117 		strip_trailing_dir_sep(home);
118 
119 	home_elinks = test_confdir(home,
120 				   get_cmd_opt_str("config-dir"),
121 				   N_("Commandline options -config-dir set to %s, "
122 				      "but could not create directory %s."));
123 	if (home_elinks) goto end;
124 
125 	home_elinks = test_confdir(home, getenv("ELINKS_CONFDIR"),
126 				   N_("ELINKS_CONFDIR set to %s, "
127 				      "but could not create directory %s."));
128 	if (home_elinks) goto end;
129 
130 	home_elinks = test_confdir(home, ".elinks", NULL);
131 	if (home_elinks) goto end;
132 
133 	home_elinks = test_confdir(home, "elinks", NULL);
134 
135 end:
136 	if (home_elinks)
137 		add_to_strn(&home_elinks, "/");
138 	mem_free_if(home);
139 
140 	return home_elinks;
141 }
142 
143 void
init_home(void)144 init_home(void)
145 {
146 	first_use = 1;
147 	elinks_home = get_home();
148 	if (!elinks_home) {
149 		ERROR(gettext("Unable to find or create ELinks config "
150 		      "directory. Please check if you have $HOME "
151 		      "variable set correctly and if you have "
152 		      "write permission to your home directory."));
153 		sleep(3);
154 		return;
155 	}
156 }
157 
158 void
done_home(void)159 done_home(void)
160 {
161 	mem_free_if(elinks_home);
162 }
163