1 |
vapier 10/12/04 12:20:43 |
2 |
|
3 |
Modified: main.c |
4 |
Log: |
5 |
refactor portage env parsing code so we support "source" keyword in files and we handle multiple stacked parents |
6 |
|
7 |
Revision Changes Path |
8 |
1.176 portage-utils/main.c |
9 |
|
10 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/main.c?rev=1.176&view=markup |
11 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/main.c?rev=1.176&content-type=text/plain |
12 |
diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/main.c?r1=1.175&r2=1.176 |
13 |
|
14 |
Index: main.c |
15 |
=================================================================== |
16 |
RCS file: /var/cvsroot/gentoo-projects/portage-utils/main.c,v |
17 |
retrieving revision 1.175 |
18 |
retrieving revision 1.176 |
19 |
diff -u -r1.175 -r1.176 |
20 |
--- main.c 4 Dec 2010 11:15:56 -0000 1.175 |
21 |
+++ main.c 4 Dec 2010 12:20:43 -0000 1.176 |
22 |
@@ -1,7 +1,7 @@ |
23 |
/* |
24 |
* Copyright 2005-2008 Gentoo Foundation |
25 |
* Distributed under the terms of the GNU General Public License v2 |
26 |
- * $Header: /var/cvsroot/gentoo-projects/portage-utils/main.c,v 1.175 2010/12/04 11:15:56 vapier Exp $ |
27 |
+ * $Header: /var/cvsroot/gentoo-projects/portage-utils/main.c,v 1.176 2010/12/04 12:20:43 vapier Exp $ |
28 |
* |
29 |
* Copyright 2005-2008 Ned Ludd - <solar@g.o> |
30 |
* Copyright 2005-2008 Mike Frysinger - <vapier@g.o> |
31 |
@@ -425,8 +425,7 @@ |
32 |
return &e; |
33 |
} |
34 |
|
35 |
-char *strincr_var(const char *, char *, char *, const size_t); |
36 |
-char *strincr_var(const char *name, char *s, char *value, const size_t value_len) |
37 |
+static char *strincr_var(const char *name, const char *s, char *value, const size_t value_len) |
38 |
{ |
39 |
char buf[BUFSIZ]; |
40 |
char *p; |
41 |
@@ -464,34 +463,122 @@ |
42 |
remove_extra_space(value); |
43 |
/* we should sort here */ |
44 |
|
45 |
- return (char *) value; |
46 |
+ return value; |
47 |
} |
48 |
|
49 |
-void initialize_portage_env(void) |
50 |
+typedef enum { _Q_BOOL, _Q_STR, _Q_ISTR } var_types; |
51 |
+typedef struct { |
52 |
+ const char *name; |
53 |
+ const size_t name_len; |
54 |
+ const var_types type; |
55 |
+ char *value; |
56 |
+ const size_t value_len; |
57 |
+} env_vars; |
58 |
+ |
59 |
+static void set_portage_env_var(const env_vars var, const char *value) |
60 |
{ |
61 |
- char nocolor = 0; |
62 |
- int i, f; |
63 |
- ssize_t profilelen; |
64 |
- struct stat st; |
65 |
+ switch (var.type) { |
66 |
+ case _Q_BOOL: *var.value = 1; break; |
67 |
+ case _Q_STR: strncpy(var.value, value, var.value_len); break; |
68 |
+ case _Q_ISTR: strincr_var(var.name, value, var.value, var.value_len); break; |
69 |
+ } |
70 |
+} |
71 |
+ |
72 |
+/* Helper to read a portage env file (e.g. make.conf) */ |
73 |
+static void read_portage_env_file(const char *file, const env_vars vars[]) |
74 |
+{ |
75 |
+ size_t i; |
76 |
FILE *fp; |
77 |
char buf[BUFSIZE], *s, *p; |
78 |
- char *e = (char *) EPREFIX; |
79 |
|
80 |
- char profile[_Q_PATH_MAX], portage_file[_Q_PATH_MAX]; |
81 |
- const char *files[] = { |
82 |
- portage_file, |
83 |
+ IF_DEBUG(fprintf(stderr, "profile %s\n", file)); |
84 |
+ |
85 |
+ fp = fopen(file, "r"); |
86 |
+ if (fp == NULL) |
87 |
+ return; |
88 |
+ |
89 |
+ while (fgets(buf, sizeof(buf), fp) != NULL) { |
90 |
+ rmspace(buf); |
91 |
+ if (*buf == '#' || *buf == '\0') |
92 |
+ continue; |
93 |
+ |
94 |
+ /* Handle "source" keyword */ |
95 |
+ if (!strncmp(buf, "source ", 7)) |
96 |
+ read_portage_env_file(buf + 7, vars); |
97 |
+ |
98 |
+ /* look for our desired variables and grab their value */ |
99 |
+ for (i = 0; vars[i].name; ++i) { |
100 |
+ if (buf[vars[i].name_len] != '=' && buf[vars[i].name_len] != ' ') |
101 |
+ continue; |
102 |
+ if (strncmp(buf, vars[i].name, vars[i].name_len)) |
103 |
+ continue; |
104 |
+ |
105 |
+ /* make sure we handle spaces between the varname, the =, and the value: |
106 |
+ * VAR=val VAR = val VAR="val" |
107 |
+ */ |
108 |
+ s = buf + vars[i].name_len; |
109 |
+ if ((p = strchr(s, '=')) != NULL) |
110 |
+ s = p + 1; |
111 |
+ while (isspace(*s)) |
112 |
+ ++s; |
113 |
+ if (*s == '"' || *s == '\'') { |
114 |
+ ++s; |
115 |
+ s[strlen(s)-1] = '\0'; |
116 |
+ } |
117 |
+ |
118 |
+ set_portage_env_var(vars[i], s); |
119 |
+ } |
120 |
+ } |
121 |
+ |
122 |
+ fclose(fp); |
123 |
+} |
124 |
+ |
125 |
+/* Helper to recursively read stacked make.defaults in profiles */ |
126 |
+static void read_portage_profile(const char *profile, const env_vars vars[]) |
127 |
+{ |
128 |
+ size_t profile_len, sub_len; |
129 |
+ char profile_file[_Q_PATH_MAX], *sub_file; |
130 |
+ char buf[BUFSIZE], *s; |
131 |
+ |
132 |
+ /* initialize the base profile path */ |
133 |
+ profile_len = strlen(profile); |
134 |
+ if (profile_len > sizeof(profile_file) - 20) |
135 |
+ return; |
136 |
+ strncpy(profile_file, profile, sizeof(profile_file)); |
137 |
+ profile_file[profile_len] = '/'; |
138 |
+ sub_file = profile_file + profile_len + 1; |
139 |
+ sub_len = sizeof(profile_file) - profile_len - 1; |
140 |
+ |
141 |
+ /* first consume the profile's make.defaults */ |
142 |
+ strncpy(sub_file, "make.defaults", sub_len); |
143 |
+ read_portage_env_file(profile_file, vars); |
144 |
+ |
145 |
+ /* now walk all the parents */ |
146 |
+ strncpy(sub_file, "parent", sub_len); |
147 |
+ if (eat_file(profile_file, buf, sizeof(buf)) == 0) |
148 |
+ return; |
149 |
+ rmspace(buf); |
150 |
+ |
151 |
+ s = strtok(buf, "\n"); |
152 |
+ while (s) { |
153 |
+ strncpy(sub_file, s, sub_len); |
154 |
+ read_portage_profile(profile_file, vars); |
155 |
+ s = strtok(NULL, "\n"); |
156 |
+ } |
157 |
+} |
158 |
+ |
159 |
+void initialize_portage_env(void) |
160 |
+{ |
161 |
+ size_t i; |
162 |
+ char *s; |
163 |
+ |
164 |
+ static const char * const files[] = { |
165 |
EPREFIX "/etc/make.globals", |
166 |
EPREFIX "/etc/make.conf", |
167 |
EPREFIX "/etc/portage/make.conf", |
168 |
}; |
169 |
- typedef enum { _Q_BOOL, _Q_STR, _Q_ISTR } var_types; |
170 |
- struct { |
171 |
- const char *name; |
172 |
- const size_t name_len; |
173 |
- const var_types type; |
174 |
- char *value; |
175 |
- const size_t value_len; |
176 |
- } vars_to_read[] = { |
177 |
+ char nocolor = 0; |
178 |
+ const env_vars vars_to_read[] = { |
179 |
{"ACCEPT_LICENSE", 14, _Q_STR, accept_license, sizeof(accept_license)}, |
180 |
{"INSTALL_MASK", 12, _Q_ISTR, install_mask, sizeof(install_mask)}, |
181 |
{"ARCH", 4, _Q_STR, portarch, sizeof(portarch)}, |
182 |
@@ -502,102 +589,36 @@ |
183 |
{"PORTAGE_BINHOST", 15, _Q_STR, binhost, sizeof(binhost)}, |
184 |
{"PORTAGE_TMPDIR", 14, _Q_STR, port_tmpdir, sizeof(port_tmpdir)}, |
185 |
{"PKGDIR", 6, _Q_STR, pkgdir, sizeof(pkgdir)}, |
186 |
- {"ROOT", 4, _Q_STR, portroot, sizeof(portroot)} |
187 |
+ {"ROOT", 4, _Q_STR, portroot, sizeof(portroot)}, |
188 |
+ { }, |
189 |
}; |
190 |
|
191 |
s = getenv("Q_VDB"); /* #257251 */ |
192 |
if (s) { |
193 |
strncpy(portvdb, s, sizeof(portvdb)); |
194 |
portvdb[sizeof(portvdb) - 1] = '\0'; |
195 |
- } else if ((i = strlen(e)) > 1) { |
196 |
+ } else if ((i = strlen(EPREFIX)) > 1) { |
197 |
memmove(portvdb + i, portvdb, strlen(portvdb)); |
198 |
- memcpy(portvdb, e + 1, i - 1); |
199 |
+ memcpy(portvdb, EPREFIX + 1, i - 1); |
200 |
portvdb[i - 1] = '/'; |
201 |
} |
202 |
|
203 |
- if ((p = strchr(portroot, '/')) != NULL) |
204 |
- if (strlen(p) != 1) |
205 |
+ if ((s = strchr(portroot, '/')) != NULL) |
206 |
+ if (strlen(s) != 1) |
207 |
strncat(portroot, "/", sizeof(portroot)); |
208 |
|
209 |
- f = 0; |
210 |
- profilelen = readlink(EPREFIX "/etc/make.profile", profile, sizeof(profile) - 1); |
211 |
- if (profilelen == -1) |
212 |
- strcpy(profile, EPREFIX "/etc/make.profile"); |
213 |
- else |
214 |
- profile[profilelen]='\0'; |
215 |
- |
216 |
- if (profile[0] != '/') { |
217 |
- memmove(profile+5+strlen(EPREFIX), profile, strlen(profile)+1); |
218 |
- memcpy(profile, EPREFIX "/etc/", strlen(EPREFIX) + 5); |
219 |
- } |
220 |
- do { |
221 |
- if (f == 0) |
222 |
- snprintf(portage_file, sizeof(portage_file), "%s/make.defaults", profile); |
223 |
- IF_DEBUG(fprintf(stderr, "profile %s\n", files[f])); |
224 |
+ /* walk all the stacked profiles */ |
225 |
+ read_portage_profile(EPREFIX "/etc/make.profile", vars_to_read); |
226 |
|
227 |
- if ((fp=fopen(files[f], "r")) != NULL) { |
228 |
- while (fgets(buf, sizeof(buf), fp) != NULL) { |
229 |
- rmspace(buf); |
230 |
- if (*buf == '#' || *buf == '\0') |
231 |
- continue; |
232 |
- for (i=0; i < ARR_SIZE(vars_to_read); ++i) { |
233 |
- if (buf[vars_to_read[i].name_len] != '=' && buf[vars_to_read[i].name_len] != ' ') |
234 |
- continue; |
235 |
- if (strncmp(buf, vars_to_read[i].name, vars_to_read[i].name_len)) |
236 |
- continue; |
237 |
- |
238 |
- /* make sure we handle spaces between the varname, the =, and the value: |
239 |
- * VAR=val VAR = val VAR="val" |
240 |
- */ |
241 |
- s = buf + vars_to_read[i].name_len; |
242 |
- if ((p = strchr(s, '=')) != NULL) |
243 |
- s = p + 1; |
244 |
- while (isspace(*s)) |
245 |
- ++s; |
246 |
- if (*s == '"' || *s == '\'') { |
247 |
- ++s; |
248 |
- s[strlen(s)-1] = '\0'; |
249 |
- } |
250 |
- |
251 |
- switch (vars_to_read[i].type) { |
252 |
- case _Q_BOOL: *vars_to_read[i].value = 1; break; |
253 |
- case _Q_STR: strncpy(vars_to_read[i].value, s, vars_to_read[i].value_len); break; |
254 |
- case _Q_ISTR: strincr_var(vars_to_read[i].name, s, vars_to_read[i].value, vars_to_read[i].value_len); break; |
255 |
- } |
256 |
- } |
257 |
- } |
258 |
- fclose(fp); |
259 |
- } |
260 |
- |
261 |
- if (f > 0) { |
262 |
- if (++f < ARR_SIZE(files)) |
263 |
- continue; |
264 |
- else |
265 |
- break; |
266 |
- } |
267 |
- |
268 |
- /* everything below here is to figure out what the next parent is */ |
269 |
- snprintf(portage_file, sizeof(portage_file), "%s/parent", profile); |
270 |
- if (stat(portage_file, &st) == 0) { |
271 |
- eat_file(portage_file, buf, sizeof(buf)); |
272 |
- rmspace(buf); |
273 |
- portage_file[strlen(portage_file)-7] = '\0'; |
274 |
- snprintf(profile, sizeof(profile), "%s/%s", portage_file, buf); |
275 |
- } else { |
276 |
- f = 1; |
277 |
- } |
278 |
- } while (1); |
279 |
+ /* now read all the config files */ |
280 |
+ for (i = 0; i < ARR_SIZE(files); ++i) |
281 |
+ read_portage_env_file(files[i], vars_to_read); |
282 |
|
283 |
/* finally, check the env */ |
284 |
- for (i=0; i < ARR_SIZE(vars_to_read); ++i) { |
285 |
+ for (i = 0; vars_to_read[i].name; ++i) { |
286 |
s = getenv(vars_to_read[i].name); |
287 |
- if (s != NULL) { |
288 |
- switch (vars_to_read[i].type) { |
289 |
- case _Q_BOOL: *vars_to_read[i].value = 1; break; |
290 |
- case _Q_STR: strncpy(vars_to_read[i].value, s, vars_to_read[i].value_len); break; |
291 |
- case _Q_ISTR: strincr_var(vars_to_read[i].name, s, vars_to_read[i].value, vars_to_read[i].value_len); break; |
292 |
- } |
293 |
- } |
294 |
+ if (s != NULL) |
295 |
+ set_portage_env_var(vars_to_read[i], s); |
296 |
if (getenv("DEBUG") IF_DEBUG(|| 1)) { |
297 |
fprintf(stderr, "%s = ", vars_to_read[i].name); |
298 |
switch (vars_to_read[i].type) { |
299 |
@@ -607,8 +628,8 @@ |
300 |
} |
301 |
} |
302 |
} |
303 |
- if ((p = strchr(portroot, '/')) != NULL) |
304 |
- if (strlen(p) != 1) |
305 |
+ if ((s = strchr(portroot, '/')) != NULL) |
306 |
+ if (strlen(s) != 1) |
307 |
strncat(portroot, "/", sizeof(portroot)); |
308 |
|
309 |
if (getenv("PORTAGE_QUIET") != NULL) |