busybox/scripts/kconfig/confdata.c
<<
>>
Prefs
   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];
 338        char tmpname[256];
 339        char newname[256];
 340        int type, l;
 341        const char *str;
 342        time_t now;
 343        int use_timestamp = 1;
 344        char *env;
 345
 346        dirname[0] = 0;
 347        if (name && name[0]) {
 348                struct stat st;
 349                char *slash;
 350
 351                if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 352                        strcpy(dirname, name);
 353                        strcat(dirname, "/");
 354                        basename = conf_def_filename;
 355                } else if ((slash = strrchr(name, '/'))) {
 356                        int size = slash - name + 1;
 357                        memcpy(dirname, name, size);
 358                        dirname[size] = 0;
 359                        if (slash[1])
 360                                basename = slash + 1;
 361                        else
 362                                basename = conf_def_filename;
 363                } else
 364                        basename = name;
 365        } else
 366                basename = conf_def_filename;
 367
 368        sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
 369        out = fopen(newname, "w");
 370        if (!out)
 371                return 1;
 372        out_h = NULL;
 373        if (!name) {
 374                out_h = fopen(".tmpconfig.h", "w");
 375                if (!out_h)
 376                        return 1;
 377                file_write_dep(NULL);
 378        }
 379        sym = sym_lookup("KERNELVERSION", 0);
 380        sym_calc_value(sym);
 381        time(&now);
 382        env = getenv("KCONFIG_NOTIMESTAMP");
 383        if (env && *env)
 384                use_timestamp = 0;
 385
 386        fprintf(out, _("#\n"
 387                       "# Automatically generated make config: don't edit\n"
 388                       "# Busybox version: %s\n"
 389                       "%s%s"
 390                       "#\n"),
 391                     sym_get_string_value(sym),
 392                     use_timestamp ? "# " : "",
 393                     use_timestamp ? ctime(&now) : "");
 394        if (out_h) {
 395                char buf[sizeof("#define AUTOCONF_TIMESTAMP "
 396                                "\"YYYY-MM-DD HH:MM:SS some_timezone\"\n")];
 397                buf[0] = '\0';
 398                if (use_timestamp) {
 399                        size_t ret = \
 400                                strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
 401                                        "\"%Y-%m-%d %H:%M:%S %Z\"\n", localtime(&now));
 402                        /* if user has Factory timezone or some other odd install, the
 403                         * %Z above will overflow the string leaving us with undefined
 404                         * results ... so let's try again without the timezone.
 405                         */
 406                        if (ret == 0)
 407                                strftime(buf, sizeof(buf), "#define AUTOCONF_TIMESTAMP "
 408                                        "\"%Y-%m-%d %H:%M:%S\"\n", localtime(&now));
 409                } else { /* bbox */
 410                        strcpy(buf, "#define AUTOCONF_TIMESTAMP \"\"\n");
 411                }
 412                fprintf(out_h, "/*\n"
 413                               " * Automatically generated C config: don't edit\n"
 414                               " * Busybox version: %s\n"
 415                               " */\n"
 416                               "%s"
 417                               "\n",
 418                               sym_get_string_value(sym),
 419                               buf);
 420        }
 421        if (!sym_change_count)
 422                sym_clear_all_valid();
 423
 424        menu = rootmenu.list;
 425        while (menu) {
 426                sym = menu->sym;
 427                if (!sym) {
 428                        if (!menu_is_visible(menu))
 429                                goto next;
 430                        str = menu_get_prompt(menu);
 431                        fprintf(out, "\n"
 432                                     "#\n"
 433                                     "# %s\n"
 434                                     "#\n", str);
 435                        if (out_h)
 436                                fprintf(out_h, "\n"
 437                                               "/*\n"
 438                                               " * %s\n"
 439                                               " */\n", str);
 440                } else if (!(sym->flags & SYMBOL_CHOICE)) {
 441                        sym_calc_value(sym);
 442/* bbox: we want to see all syms
 443                        if (!(sym->flags & SYMBOL_WRITE))
 444                                goto next;
 445*/
 446                        sym->flags &= ~SYMBOL_WRITE;
 447                        type = sym->type;
 448                        if (type == S_TRISTATE) {
 449                                sym_calc_value(modules_sym);
 450                                if (modules_sym->curr.tri == no)
 451                                        type = S_BOOLEAN;
 452                        }
 453                        switch (type) {
 454                        case S_BOOLEAN:
 455                        case S_TRISTATE:
 456                                switch (sym_get_tristate_value(sym)) {
 457                                case no:
 458                                        fprintf(out, "# CONFIG_%s is not set\n", sym->name);
 459                                        if (out_h) {
 460                                                fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
 461                                                /* bbox */
 462                                                fprintf(out_h, "#define ENABLE_%s 0\n", sym->name);
 463                                                fprintf(out_h, "#define IF_%s(...)\n", sym->name);
 464                                                fprintf(out_h, "#define IF_NOT_%s(...) __VA_ARGS__\n", sym->name);
 465                                        }
 466                                        break;
 467                                case mod:
 468                                        fprintf(out, "CONFIG_%s=m\n", sym->name);
 469                                        if (out_h)
 470                                                fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 471                                        break;
 472                                case yes:
 473                                        fprintf(out, "CONFIG_%s=y\n", sym->name);
 474                                        if (out_h) {
 475                                                fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 476                                                /* bbox */
 477                                                fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 478                                                fprintf(out_h, "#ifdef MAKE_SUID\n");
 479                                                fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
 480                                                fprintf(out_h, "#else\n");
 481                                                fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
 482                                                fprintf(out_h, "#endif\n");
 483                                                fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 484                                        }
 485                                        break;
 486                                }
 487                                break;
 488                        case S_STRING:
 489                                // fix me
 490                                str = sym_get_string_value(sym);
 491                                fprintf(out, "CONFIG_%s=\"", sym->name);
 492                                if (out_h)
 493                                        fprintf(out_h, "#define CONFIG_%s \"", sym->name);
 494                                do {
 495                                        l = strcspn(str, "\"\\");
 496                                        if (l) {
 497                                                fwrite(str, l, 1, out);
 498                                                if (out_h)
 499                                                        fwrite(str, l, 1, out_h);
 500                                        }
 501                                        str += l;
 502                                        while (*str == '\\' || *str == '"') {
 503                                                fprintf(out, "\\%c", *str);
 504                                                if (out_h)
 505                                                        fprintf(out_h, "\\%c", *str);
 506                                                str++;
 507                                        }
 508                                } while (*str);
 509                                fputs("\"\n", out);
 510                                if (out_h) {
 511                                        fputs("\"\n", out_h);
 512                                        /* bbox */
 513                                        fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 514                                        fprintf(out_h, "#ifdef MAKE_SUID\n");
 515                                        fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
 516                                        fprintf(out_h, "#else\n");
 517                                        fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
 518                                        fprintf(out_h, "#endif\n");
 519                                        fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 520                                }
 521                                break;
 522                        case S_HEX:
 523                                str = sym_get_string_value(sym);
 524                                if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
 525                                        fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 526                                        if (out_h) {
 527                                                fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
 528                                                /* bbox */
 529                                                fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 530                                                fprintf(out_h, "#ifdef MAKE_SUID\n");
 531                                                fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
 532                                                fprintf(out_h, "#else\n");
 533                                                fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
 534                                                fprintf(out_h, "#endif\n");
 535                                                fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 536                                        }
 537                                        break;
 538                                }
 539                        case S_INT:
 540                                str = sym_get_string_value(sym);
 541                                if (!str[0])
 542                                        str = "0";
 543                                fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
 544                                if (out_h) {
 545                                        fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
 546                                        /* bbox */
 547                                        fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
 548                                        fprintf(out_h, "#ifdef MAKE_SUID\n");
 549                                        fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
 550                                        fprintf(out_h, "#else\n");
 551                                        fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
 552                                        fprintf(out_h, "#endif\n");
 553                                        fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
 554                                }
 555                                break;
 556                        }
 557                }
 558
 559        next:
 560                if (menu->list) {
 561                        menu = menu->list;
 562                        continue;
 563                }
 564                if (menu->next)
 565                        menu = menu->next;
 566                else while ((menu = menu->parent)) {
 567                        if (menu->next) {
 568                                menu = menu->next;
 569                                break;
 570                        }
 571                }
 572        }
 573        fclose(out);
 574        if (out_h) {
 575                fclose(out_h);
 576                rename(".tmpconfig.h", "include/autoconf.h");
 577        }
 578        if (!name || basename != conf_def_filename) {
 579                if (!name)
 580                        name = conf_def_filename;
 581                sprintf(tmpname, "%s.old", name);
 582                rename(name, tmpname);
 583        }
 584        sprintf(tmpname, "%s%s", dirname, basename);
 585        if (rename(newname, tmpname))
 586                return 1;
 587
 588        sym_change_count = 0;
 589
 590        return 0;
 591}
 592