source: MondoRescue/branches/3.3/mindi-busybox/scripts/kconfig/confdata.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 13.8 KB
Line 
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <sys/stat.h>
7#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12#include <unistd.h>
13
14#define LKC_DIRECT_LINK
15#include "lkc.h"
16
17static void conf_warning(const char *fmt, ...)
18 __attribute__ ((format (printf, 1, 2)));
19
20static const char *conf_filename;
21static int conf_lineno, conf_warnings, conf_unsaved;
22
23const char conf_def_filename[] = ".config";
24
25const char conf_defname[] = "/dev/null"; //bbox
26
27const char *conf_confnames[] = {
28 conf_def_filename,
29 conf_defname,
30 NULL,
31};
32
33static void conf_warning(const char *fmt, ...)
34{
35 va_list ap;
36 va_start(ap, fmt);
37 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
38 vfprintf(stderr, fmt, ap);
39 fprintf(stderr, "\n");
40 va_end(ap);
41 conf_warnings++;
42}
43
44static char *conf_expand_value(const char *in)
45{
46 struct symbol *sym;
47 const char *src;
48 static char res_value[SYMBOL_MAXLENGTH];
49 char *dst, name[SYMBOL_MAXLENGTH];
50
51 res_value[0] = 0;
52 dst = name;
53 while ((src = strchr(in, '$'))) {
54 strncat(res_value, in, src - in);
55 src++;
56 dst = name;
57 while (isalnum(*src) || *src == '_')
58 *dst++ = *src++;
59 *dst = 0;
60 sym = sym_lookup(name, 0);
61 sym_calc_value(sym);
62 strcat(res_value, sym_get_string_value(sym));
63 in = src;
64 }
65 strcat(res_value, in);
66
67 return res_value;
68}
69
70char *conf_get_default_confname(void)
71{
72 struct stat buf;
73 static char *fullname = NULL;
74 char *env, *name;
75
76 name = conf_expand_value(conf_defname);
77 env = getenv(SRCTREE);
78 if (env) {
79 fullname = realloc(fullname, strlen(env) + strlen(name) + 2);
80 sprintf(fullname, "%s/%s", env, name);
81 if (!stat(fullname, &buf))
82 return fullname;
83 }
84 return name;
85}
86
87int conf_read_simple(const char *name)
88{
89 FILE *in = NULL;
90 char line[1024];
91 char *p, *p2;
92 struct symbol *sym;
93 int i;
94
95 if (name) {
96 in = zconf_fopen(name);
97 } else {
98 const char **names = conf_confnames;
99 while ((name = *names++)) {
100 name = conf_expand_value(name);
101 in = zconf_fopen(name);
102 if (in) {
103 printf(_("#\n"
104 "# using defaults found in %s\n"
105 "#\n"), name);
106 break;
107 }
108 }
109 }
110 if (!in)
111 return 1;
112
113 conf_filename = name;
114 conf_lineno = 0;
115 conf_warnings = 0;
116 conf_unsaved = 0;
117
118 for_all_symbols(i, sym) {
119 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
120 if (sym_is_choice(sym))
121 sym->flags &= ~SYMBOL_NEW;
122 sym->flags &= ~SYMBOL_VALID;
123 switch (sym->type) {
124 case S_INT:
125 case S_HEX:
126 case S_STRING:
127 free(sym->user.val);
128 default:
129 sym->user.val = NULL;
130 sym->user.tri = no;
131 }
132 }
133
134 while (fgets(line, sizeof(line), in)) {
135 conf_lineno++;
136 sym = NULL;
137 switch (line[0]) {
138 case '#':
139 if (memcmp(line + 2, "CONFIG_", 7))
140 continue;
141 p = strchr(line + 9, ' ');
142 if (!p)
143 continue;
144 *p++ = 0;
145 if (strncmp(p, "is not set", 10))
146 continue;
147 sym = sym_find(line + 9);
148 if (!sym) {
149 conf_warning("trying to assign nonexistent symbol %s", line + 9);
150 break;
151 } else if (!(sym->flags & SYMBOL_NEW)) {
152 conf_warning("trying to reassign symbol %s", sym->name);
153 break;
154 }
155 switch (sym->type) {
156 case S_BOOLEAN:
157 case S_TRISTATE:
158 sym->user.tri = no;
159 sym->flags &= ~SYMBOL_NEW;
160 break;
161 default:
162 ;
163 }
164 break;
165 case 'C':
166 if (memcmp(line, "CONFIG_", 7)) {
167 conf_warning("unexpected data");
168 continue;
169 }
170 p = strchr(line + 7, '=');
171 if (!p)
172 continue;
173 *p++ = 0;
174 p2 = strchr(p, '\n');
175 if (p2)
176 *p2 = 0;
177 sym = sym_find(line + 7);
178 if (!sym) {
179 conf_warning("trying to assign nonexistent symbol %s", line + 7);
180 break;
181 } else if (!(sym->flags & SYMBOL_NEW)) {
182 conf_warning("trying to reassign symbol %s", sym->name);
183 break;
184 }
185 switch (sym->type) {
186 case S_TRISTATE:
187 if (p[0] == 'm') {
188 sym->user.tri = mod;
189 sym->flags &= ~SYMBOL_NEW;
190 break;
191 }
192 case S_BOOLEAN:
193 if (p[0] == 'y') {
194 sym->user.tri = yes;
195 sym->flags &= ~SYMBOL_NEW;
196 break;
197 }
198 if (p[0] == 'n') {
199 sym->user.tri = no;
200 sym->flags &= ~SYMBOL_NEW;
201 break;
202 }
203 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
204 break;
205 case S_STRING:
206 if (*p++ != '"')
207 break;
208 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
209 if (*p2 == '"') {
210 *p2 = 0;
211 break;
212 }
213 memmove(p2, p2 + 1, strlen(p2));
214 }
215 if (!p2) {
216 conf_warning("invalid string found");
217 continue;
218 }
219 case S_INT:
220 case S_HEX:
221 if (sym_string_valid(sym, p)) {
222 sym->user.val = strdup(p);
223 sym->flags &= ~SYMBOL_NEW;
224 } else {
225 if (p[0]) /* bbox */
226 conf_warning("symbol value '%s' invalid for %s", p, sym->name);
227 continue;
228 }
229 break;
230 default:
231 ;
232 }
233 break;
234 case '\n':
235 break;
236 default:
237 conf_warning("unexpected data");
238 continue;
239 }
240 if (sym && sym_is_choice_value(sym)) {
241 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
242 switch (sym->user.tri) {
243 case no:
244 break;
245 case mod:
246 if (cs->user.tri == yes) {
247 conf_warning("%s creates inconsistent choice state", sym->name);
248 cs->flags |= SYMBOL_NEW;
249 }
250 break;
251 case yes:
252 if (cs->user.tri != no) {
253 conf_warning("%s creates inconsistent choice state", sym->name);
254 cs->flags |= SYMBOL_NEW;
255 } else
256 cs->user.val = sym;
257 break;
258 }
259 cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
260 }
261 }
262 fclose(in);
263
264 if (modules_sym)
265 sym_calc_value(modules_sym);
266 return 0;
267}
268
269int conf_read(const char *name)
270{
271 struct symbol *sym;
272 struct property *prop;
273 struct expr *e;
274 int i;
275
276 if (conf_read_simple(name))
277 return 1;
278
279 for_all_symbols(i, sym) {
280 sym_calc_value(sym);
281 if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
282 goto sym_ok;
283 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
284 /* check that calculated value agrees with saved value */
285 switch (sym->type) {
286 case S_BOOLEAN:
287 case S_TRISTATE:
288 if (sym->user.tri != sym_get_tristate_value(sym))
289 break;
290 if (!sym_is_choice(sym))
291 goto sym_ok;
292 default:
293 if (!strcmp(sym->curr.val, sym->user.val))
294 goto sym_ok;
295 break;
296 }
297 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
298 /* no previous value and not saved */
299 goto sym_ok;
300 conf_unsaved++;
301 /* maybe print value in verbose mode... */
302 sym_ok:
303 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
304 if (sym->visible == no)
305 sym->flags |= SYMBOL_NEW;
306 switch (sym->type) {
307 case S_STRING:
308 case S_INT:
309 case S_HEX:
310 if (!sym_string_within_range(sym, sym->user.val)) {
311 sym->flags |= SYMBOL_NEW;
312 sym->flags &= ~SYMBOL_VALID;
313 }
314 default:
315 break;
316 }
317 }
318 if (!sym_is_choice(sym))
319 continue;
320 prop = sym_get_choice_prop(sym);
321 for (e = prop->expr; e; e = e->left.expr)
322 if (e->right.sym->visible != no)
323 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
324 }
325
326 sym_change_count = conf_warnings || conf_unsaved;
327
328 return 0;
329}
330
331int conf_write(const char *name)
332{
333 FILE *out, *out_h;
334 struct symbol *sym;
335 struct menu *menu;
336 const char *basename;
337 char dirname[128], tmpname[128], newname[128];
338 int type, l;
339 const char *str;
340 time_t now;
341 int use_timestamp = 1;
342 char *env;
343
344 dirname[0] = 0;
345 if (name && name[0]) {
346 struct stat st;
347 char *slash;
348
349 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
350 strcpy(dirname, name);
351 strcat(dirname, "/");
352 basename = conf_def_filename;
353 } else if ((slash = strrchr(name, '/'))) {
354 int size = slash - name + 1;
355 memcpy(dirname, name, size);
356 dirname[size] = 0;
357 if (slash[1])
358 basename = slash + 1;
359 else
360 basename = conf_def_filename;
361 } else
362 basename = name;
363 } else
364 basename = conf_def_filename;
365
366 sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
367 out = fopen(newname, "w");
368 if (!out)
369 return 1;
370 out_h = NULL;
371 if (!name) {
372 out_h = fopen(".tmpconfig.h", "w");
373 if (!out_h)
374 return 1;
375 file_write_dep(NULL);
376 }
377 sym = sym_lookup("KERNELVERSION", 0);
378 sym_calc_value(sym);
379 time(&now);
380 env = getenv("KCONFIG_NOTIMESTAMP");
381 if (env && *env)
382 use_timestamp = 0;
383
384 fprintf(out, _("#\n"
385 "# Automatically generated make config: don't edit\n"
386 "# Busybox version: %s\n"
387 "%s%s"
388 "#\n"),
389 sym_get_string_value(sym),
390 use_timestamp ? "# " : "",
391 use_timestamp ? ctime(&now) : "");
392 if (out_h) {
393 char buf[sizeof("#define AUTOCONF_TIMESTAMP "
394 "\"YYYY-MM-DD HH:MM:SS some_timezone\"\n")];
395 buf[0] = '\0';
396 if (use_timestamp) {
397 size_t ret = \
398 strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
399 "\"%Y-%m-%d %H:%M:%S %Z\"\n", localtime(&now));
400 /* if user has Factory timezone or some other odd install, the
401 * %Z above will overflow the string leaving us with undefined
402 * results ... so let's try again without the timezone.
403 */
404 if (ret == 0)
405 strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
406 "\"%Y-%m-%d %H:%M:%S\"\n", localtime(&now));
407 } else { /* bbox */
408 strcpy(buf, "#define AUTOCONF_TIMESTAMP \"\"\n");
409 }
410 fprintf(out_h, "/*\n"
411 " * Automatically generated C config: don't edit\n"
412 " * Busybox version: %s\n"
413 " */\n"
414 "%s"
415 "\n",
416 sym_get_string_value(sym),
417 buf);
418 }
419 if (!sym_change_count)
420 sym_clear_all_valid();
421
422 menu = rootmenu.list;
423 while (menu) {
424 sym = menu->sym;
425 if (!sym) {
426 if (!menu_is_visible(menu))
427 goto next;
428 str = menu_get_prompt(menu);
429 fprintf(out, "\n"
430 "#\n"
431 "# %s\n"
432 "#\n", str);
433 if (out_h)
434 fprintf(out_h, "\n"
435 "/*\n"
436 " * %s\n"
437 " */\n", str);
438 } else if (!(sym->flags & SYMBOL_CHOICE)) {
439 sym_calc_value(sym);
440/* bbox: we want to see all syms
441 if (!(sym->flags & SYMBOL_WRITE))
442 goto next;
443*/
444 sym->flags &= ~SYMBOL_WRITE;
445 type = sym->type;
446 if (type == S_TRISTATE) {
447 sym_calc_value(modules_sym);
448 if (modules_sym->curr.tri == no)
449 type = S_BOOLEAN;
450 }
451 switch (type) {
452 case S_BOOLEAN:
453 case S_TRISTATE:
454 switch (sym_get_tristate_value(sym)) {
455 case no:
456 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
457 if (out_h) {
458 fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
459 /* bbox */
460 fprintf(out_h, "#define ENABLE_%s 0\n", sym->name);
461 fprintf(out_h, "#define IF_%s(...)\n", sym->name);
462 fprintf(out_h, "#define IF_NOT_%s(...) __VA_ARGS__\n", sym->name);
463 }
464 break;
465 case mod:
466 fprintf(out, "CONFIG_%s=m\n", sym->name);
467 if (out_h)
468 fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
469 break;
470 case yes:
471 fprintf(out, "CONFIG_%s=y\n", sym->name);
472 if (out_h) {
473 fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
474 /* bbox */
475 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
476 fprintf(out_h, "#ifdef MAKE_SUID\n");
477 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
478 fprintf(out_h, "#else\n");
479 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
480 fprintf(out_h, "#endif\n");
481 fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
482 }
483 break;
484 }
485 break;
486 case S_STRING:
487 // fix me
488 str = sym_get_string_value(sym);
489 fprintf(out, "CONFIG_%s=\"", sym->name);
490 if (out_h)
491 fprintf(out_h, "#define CONFIG_%s \"", sym->name);
492 do {
493 l = strcspn(str, "\"\\");
494 if (l) {
495 fwrite(str, l, 1, out);
496 if (out_h)
497 fwrite(str, l, 1, out_h);
498 }
499 str += l;
500 while (*str == '\\' || *str == '"') {
501 fprintf(out, "\\%c", *str);
502 if (out_h)
503 fprintf(out_h, "\\%c", *str);
504 str++;
505 }
506 } while (*str);
507 fputs("\"\n", out);
508 if (out_h) {
509 fputs("\"\n", out_h);
510 /* bbox */
511 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
512 fprintf(out_h, "#ifdef MAKE_SUID\n");
513 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
514 fprintf(out_h, "#else\n");
515 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
516 fprintf(out_h, "#endif\n");
517 fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
518 }
519 break;
520 case S_HEX:
521 str = sym_get_string_value(sym);
522 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
523 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
524 if (out_h) {
525 fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
526 /* bbox */
527 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
528 fprintf(out_h, "#ifdef MAKE_SUID\n");
529 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
530 fprintf(out_h, "#else\n");
531 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
532 fprintf(out_h, "#endif\n");
533 fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
534 }
535 break;
536 }
537 case S_INT:
538 str = sym_get_string_value(sym);
539 if (!str[0])
540 str = "0";
541 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
542 if (out_h) {
543 fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
544 /* bbox */
545 fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
546 fprintf(out_h, "#ifdef MAKE_SUID\n");
547 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
548 fprintf(out_h, "#else\n");
549 fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
550 fprintf(out_h, "#endif\n");
551 fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
552 }
553 break;
554 }
555 }
556
557 next:
558 if (menu->list) {
559 menu = menu->list;
560 continue;
561 }
562 if (menu->next)
563 menu = menu->next;
564 else while ((menu = menu->parent)) {
565 if (menu->next) {
566 menu = menu->next;
567 break;
568 }
569 }
570 }
571 fclose(out);
572 if (out_h) {
573 fclose(out_h);
574 rename(".tmpconfig.h", "include/autoconf.h");
575 }
576 if (!name || basename != conf_def_filename) {
577 if (!name)
578 name = conf_def_filename;
579 sprintf(tmpname, "%s.old", name);
580 rename(name, tmpname);
581 }
582 sprintf(tmpname, "%s%s", dirname, basename);
583 if (rename(newname, tmpname))
584 return 1;
585
586 sym_change_count = 0;
587
588 return 0;
589}
Note: See TracBrowser for help on using the repository browser.