source: MondoRescue/branches/stable/mindi-busybox/scripts/config/confdata.c @ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 13 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 10.2 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 <unistd.h>
12
13#define LKC_DIRECT_LINK
14#include "lkc.h"
15
16const char conf_def_filename[] = ".config";
17
18const char conf_defname[] = "defconfig";
19
20const char *conf_confnames[] = {
21    ".config",
22    conf_defname,
23    NULL,
24};
25
26static char *conf_expand_value(const char *in)
27{
28    struct symbol *sym;
29    const char *src;
30    static char res_value[SYMBOL_MAXLENGTH];
31    char *dst, name[SYMBOL_MAXLENGTH];
32
33    res_value[0] = 0;
34    dst = name;
35    while ((src = strchr(in, '$'))) {
36        strncat(res_value, in, src - in);
37        src++;
38        dst = name;
39        while (isalnum(*src) || *src == '_')
40            *dst++ = *src++;
41        *dst = 0;
42        sym = sym_lookup(name, 0);
43        sym_calc_value(sym);
44        strcat(res_value, sym_get_string_value(sym));
45        in = src;
46    }
47    strcat(res_value, in);
48
49    return res_value;
50}
51
52char *conf_get_default_confname(void)
53{
54    struct stat buf;
55    static char fullname[PATH_MAX+1];
56    char *env, *name;
57
58    name = conf_expand_value(conf_defname);
59    env = getenv(SRCTREE);
60    if (env) {
61        sprintf(fullname, "%s/%s", env, name);
62        if (!stat(fullname, &buf))
63            return fullname;
64    }
65    return name;
66}
67
68int conf_read(const char *name)
69{
70    FILE *in = NULL;
71    char line[1024];
72    char *p, *p2;
73    int lineno = 0;
74    struct symbol *sym;
75    struct property *prop;
76    struct expr *e;
77    int i;
78
79    if (name) {
80        in = zconf_fopen(name);
81    } else {
82        const char **names = conf_confnames;
83        while ((name = *names++)) {
84            name = conf_expand_value(name);
85            in = zconf_fopen(name);
86            if (in) {
87                printf("#\n"
88                       "# using defaults found in %s\n"
89                       "#\n", name);
90                break;
91            }
92        }
93    }
94
95    if (!in)
96        return 1;
97
98    for_all_symbols(i, sym) {
99        sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
100        sym->flags &= ~SYMBOL_VALID;
101        switch (sym->type) {
102        case S_INT:
103        case S_HEX:
104        case S_STRING:
105            free(sym->user.val);
106        default:
107            sym->user.val = NULL;
108            sym->user.tri = no;
109        }
110    }
111
112    while (fgets(line, sizeof(line), in)) {
113        lineno++;
114        sym = NULL;
115        switch (line[0]) {
116        case '#':
117            if (line[1]!=' ')
118                continue;
119            p = strchr(line + 2, ' ');
120            if (!p)
121                continue;
122            *p++ = 0;
123            if (strncmp(p, "is not set", 10))
124                continue;
125            sym = sym_find(line + 2);
126            if (!sym) {
127                fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
128                break;
129            }
130            switch (sym->type) {
131            case S_BOOLEAN:
132            case S_TRISTATE:
133                sym->user.tri = no;
134                sym->flags &= ~SYMBOL_NEW;
135                break;
136            default:
137                ;
138            }
139            break;
140
141        case 'A' ... 'Z':
142            p = strchr(line, '=');
143            if (!p)
144                continue;
145            *p++ = 0;
146            p2 = strchr(p, '\n');
147            if (p2)
148                *p2 = 0;
149            sym = sym_find(line);
150            if (!sym) {
151                fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
152                break;
153            }
154            switch (sym->type) {
155            case S_TRISTATE:
156                if (p[0] == 'm') {
157                    sym->user.tri = mod;
158                    sym->flags &= ~SYMBOL_NEW;
159                    break;
160                }
161            case S_BOOLEAN:
162                if (p[0] == 'y') {
163                    sym->user.tri = yes;
164                    sym->flags &= ~SYMBOL_NEW;
165                    break;
166                }
167                if (p[0] == 'n') {
168                    sym->user.tri = no;
169                    sym->flags &= ~SYMBOL_NEW;
170                    break;
171                }
172                break;
173            case S_STRING:
174                if (*p++ != '"')
175                    break;
176                for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
177                    if (*p2 == '"') {
178                        *p2 = 0;
179                        break;
180                    }
181                    memmove(p2, p2 + 1, strlen(p2));
182                }
183                if (!p2) {
184                    fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
185                    exit(1);
186                }
187            case S_INT:
188            case S_HEX:
189                if (sym_string_valid(sym, p)) {
190                    sym->user.val = strdup(p);
191                    sym->flags &= ~SYMBOL_NEW;
192                } else {
193                    fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
194                    exit(1);
195                }
196                break;
197            default:
198                ;
199            }
200            break;
201        case '\n':
202            break;
203        default:
204            continue;
205        }
206        if (sym && sym_is_choice_value(sym)) {
207            struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
208            switch (sym->user.tri) {
209            case no:
210                break;
211            case mod:
212                if (cs->user.tri == yes)
213                    /* warn? */;
214                break;
215            case yes:
216                if (cs->user.tri != no)
217                    /* warn? */;
218                cs->user.val = sym;
219                break;
220            }
221            cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
222            cs->flags &= ~SYMBOL_NEW;
223        }
224    }
225    fclose(in);
226
227    if (modules_sym)
228        sym_calc_value(modules_sym);
229    for_all_symbols(i, sym) {
230        sym_calc_value(sym);
231        if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
232            if (sym->visible == no)
233                sym->flags |= SYMBOL_NEW;
234            switch (sym->type) {
235            case S_STRING:
236            case S_INT:
237            case S_HEX:
238                if (!sym_string_within_range(sym, sym->user.val))
239                    sym->flags |= SYMBOL_NEW;
240            default:
241                break;
242            }
243        }
244        if (!sym_is_choice(sym))
245            continue;
246        prop = sym_get_choice_prop(sym);
247        for (e = prop->expr; e; e = e->left.expr)
248            if (e->right.sym->visible != no)
249                sym->flags |= e->right.sym->flags & SYMBOL_NEW;
250    }
251
252    sym_change_count = 1;
253
254    return 0;
255}
256
257struct menu *next_menu(struct menu *menu)
258{
259    if (menu->list) return menu->list;
260    do {
261        if (menu->next) {
262            menu = menu->next;
263            break;
264        }
265    } while ((menu = menu->parent));
266
267    return menu;
268}
269
270#define SYMBOL_FORCEWRITE (1<<31)
271
272int conf_write(const char *name)
273{
274    FILE *out, *out_h;
275    struct symbol *sym;
276    struct menu *menu;
277    const char *basename;
278    char dirname[128], tmpname[128], newname[128];
279    int type, l;
280    const char *str;
281
282    /* busybox`s code */
283    const char *opt_name;
284    int use_flg;
285
286    dirname[0] = 0;
287    if (name && name[0]) {
288        struct stat st;
289        char *slash;
290
291        if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
292            strcpy(dirname, name);
293            strcat(dirname, "/");
294            basename = conf_def_filename;
295        } else if ((slash = strrchr(name, '/'))) {
296            int size = slash - name + 1;
297            memcpy(dirname, name, size);
298            dirname[size] = 0;
299            if (slash[1])
300                basename = slash + 1;
301            else
302                basename = conf_def_filename;
303        } else
304            basename = name;
305    } else
306        basename = conf_def_filename;
307
308    sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
309    out = fopen(newname, "w");
310    if (!out)
311        return 1;
312    out_h = NULL;
313    if (!name) {
314        out_h = fopen(".tmpconfig.h", "w");
315        if (!out_h)
316            return 1;
317    }
318    fprintf(out, "#\n"
319             "# Automatically generated make config: don't edit\n"
320             "#\n");
321
322    /* busybox`s code */
323    if (out_h) {
324        fprintf(out_h, "#ifndef BB_CONFIG_H\n#define BB_CONFIG_H\n");
325        fprintf(out_h, "/*\n"
326                 " * Automatically generated header file: don't edit\n"
327                 " */\n\n"
328                 "/* Version Number */\n"
329                 "#define BB_VER \"%s\"\n"
330                 "#define BB_BT \"%s\"\n",
331                 getenv("VERSION"),
332                 getenv("BUILDTIME"));
333        if (getenv("EXTRA_VERSION"))
334            fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
335                     getenv("EXTRA_VERSION"));
336        fprintf(out_h, "\n");
337    }
338    /* end busybox`s code */
339
340    if (!sym_change_count)
341        sym_clear_all_valid();
342
343    /* Force write of all non-duplicate symbols. */
344
345    /* Write out everything by default. */
346    for(menu = rootmenu.list; menu; menu = next_menu(menu))
347        if (menu->sym) menu->sym->flags |= SYMBOL_FORCEWRITE;
348
349    menu = rootmenu.list;
350    while (menu) {
351        sym = menu->sym;
352        if (!sym) {
353            if (!menu_is_visible(menu))
354                goto next;
355            str = menu_get_prompt(menu);
356            fprintf(out, "\n"
357                     "#\n"
358                     "# %s\n"
359                     "#\n", str);
360            if (out_h)
361                fprintf(out_h, "\n"
362                           "/*\n"
363                           " * %s\n"
364                           " */\n", str);
365        } else if (!(sym->flags & SYMBOL_CHOICE)) {
366            sym_calc_value(sym);
367            if (!(sym->flags & SYMBOL_FORCEWRITE))
368                goto next;
369
370            sym->flags &= ~SYMBOL_FORCEWRITE;
371            type = sym->type;
372            if (type == S_TRISTATE) {
373                sym_calc_value(modules_sym);
374                if (modules_sym->curr.tri == no)
375                    type = S_BOOLEAN;
376            }
377
378            /* busybox`s code */
379            opt_name = strchr(sym->name, '_');
380            if(opt_name == NULL)
381                opt_name = sym->name;
382            else
383                opt_name++;
384            use_flg = 1;
385            /* end busybox`s code */
386
387            switch (type) {
388            case S_BOOLEAN:
389            case S_TRISTATE:
390                switch (sym_get_tristate_value(sym)) {
391                case no:
392                    fprintf(out, "# %s is not set\n", sym->name);
393                    if (out_h)
394                        fprintf(out_h, "#undef %s\n", sym->name);
395                    use_flg = 0;    /* busybox`s code */
396                    break;
397                case mod:
398#if 0   /* busybox`s code */
399                    fprintf(out, "%s=m\n", sym->name);
400                    if (out_h)
401                        fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
402#endif  /* busybox`s code */
403                    break;
404                case yes:
405                    fprintf(out, "%s=y\n", sym->name);
406                    if (out_h)
407                        fprintf(out_h, "#define %s 1\n", sym->name);
408                    break;
409                }
410                break;
411            case S_STRING:
412                // fix me
413                str = sym_get_string_value(sym);
414                fprintf(out, "%s=\"", sym->name);
415                if (out_h)
416                    fprintf(out_h, "#define %s \"", sym->name);
417                do {
418                    l = strcspn(str, "\"\\");
419                    if (l) {
420                        fwrite(str, l, 1, out);
421                        if (out_h)
422                            fwrite(str, l, 1, out_h);
423                    }
424                    str += l;
425                    while (*str == '\\' || *str == '"') {
426                        fprintf(out, "\\%c", *str);
427                        if (out_h)
428                            fprintf(out_h, "\\%c", *str);
429                        str++;
430                    }
431                } while (*str);
432                fputs("\"\n", out);
433                if (out_h)
434                    fputs("\"\n", out_h);
435                break;
436            case S_HEX:
437                str = sym_get_string_value(sym);
438                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
439                    fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
440                    if (out_h)
441                        fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
442                    break;
443                }
444            case S_INT:
445                str = sym_get_string_value(sym);
446                fprintf(out, "%s=%s\n", sym->name, *str ? str : "0");
447                if (out_h)
448                    fprintf(out_h, "#define %s %s\n", sym->name, str);
449                break;
450            }
451            /* busybox`s code */
452            if (out_h) {
453                fprintf(out_h, "#define ENABLE_%s %d\n", opt_name, use_flg);
454                fprintf(out_h, "#define USE_%s(...)%s\n", opt_name,
455                    (use_flg ? "  __VA_ARGS__" : ""));
456                fprintf(out_h, "#define SKIP_%s(...)%s\n\n", opt_name,
457                    (use_flg ? "" : "  __VA_ARGS__"));
458            }
459            /* end busybox`s code */
460        }
461next:
462        menu = next_menu(menu);
463    }
464    fclose(out);
465    if (out_h) {
466        fprintf(out_h, "#endif /* BB_CONFIG_H */\n");   /* busybox`s code */
467        fclose(out_h);
468        rename(".tmpconfig.h", "include/bb_config.h");  /* busybox`s config name */
469        file_write_dep(NULL);
470    }
471    if (!name || basename != conf_def_filename) {
472        if (!name)
473            name = conf_def_filename;
474        sprintf(tmpname, "%s.old", name);
475        rename(name, tmpname);
476    }
477    sprintf(tmpname, "%s%s", dirname, basename);
478    if (rename(newname, tmpname))
479        return 1;
480
481    sym_change_count = 0;
482
483    return 0;
484}
Note: See TracBrowser for help on using the repository browser.