linux/scripts/kconfig/conf.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 <locale.h>
   7#include <ctype.h>
   8#include <limits.h>
   9#include <stdio.h>
  10#include <stdlib.h>
  11#include <string.h>
  12#include <time.h>
  13#include <unistd.h>
  14#include <getopt.h>
  15#include <sys/stat.h>
  16#include <sys/time.h>
  17#include <errno.h>
  18
  19#include "lkc.h"
  20
  21static void conf(struct menu *menu);
  22static void check_conf(struct menu *menu);
  23static void xfgets(char *str, int size, FILE *in);
  24
  25enum input_mode {
  26        oldaskconfig,
  27        silentoldconfig,
  28        oldconfig,
  29        allnoconfig,
  30        allyesconfig,
  31        allmodconfig,
  32        alldefconfig,
  33        randconfig,
  34        defconfig,
  35        savedefconfig,
  36        listnewconfig,
  37        olddefconfig,
  38} input_mode = oldaskconfig;
  39
  40static int indent = 1;
  41static int tty_stdio;
  42static int valid_stdin = 1;
  43static int sync_kconfig;
  44static int conf_cnt;
  45static char line[PATH_MAX];
  46static struct menu *rootEntry;
  47
  48static void print_help(struct menu *menu)
  49{
  50        struct gstr help = str_new();
  51
  52        menu_get_ext_help(menu, &help);
  53
  54        printf("\n%s\n", str_get(&help));
  55        str_free(&help);
  56}
  57
  58static void strip(char *str)
  59{
  60        char *p = str;
  61        int l;
  62
  63        while ((isspace(*p)))
  64                p++;
  65        l = strlen(p);
  66        if (p != str)
  67                memmove(str, p, l + 1);
  68        if (!l)
  69                return;
  70        p = str + l - 1;
  71        while ((isspace(*p)))
  72                *p-- = 0;
  73}
  74
  75static void check_stdin(void)
  76{
  77        if (!valid_stdin) {
  78                printf(_("aborted!\n\n"));
  79                printf(_("Console input/output is redirected. "));
  80                printf(_("Run 'make oldconfig' to update configuration.\n\n"));
  81                exit(1);
  82        }
  83}
  84
  85static int conf_askvalue(struct symbol *sym, const char *def)
  86{
  87        enum symbol_type type = sym_get_type(sym);
  88
  89        if (!sym_has_value(sym))
  90                printf(_("(NEW) "));
  91
  92        line[0] = '\n';
  93        line[1] = 0;
  94
  95        if (!sym_is_changable(sym)) {
  96                printf("%s\n", def);
  97                line[0] = '\n';
  98                line[1] = 0;
  99                return 0;
 100        }
 101
 102        switch (input_mode) {
 103        case oldconfig:
 104        case silentoldconfig:
 105                if (sym_has_value(sym)) {
 106                        printf("%s\n", def);
 107                        return 0;
 108                }
 109                check_stdin();
 110                /* fall through */
 111        case oldaskconfig:
 112                fflush(stdout);
 113                xfgets(line, sizeof(line), stdin);
 114                if (!tty_stdio)
 115                        printf("\n");
 116                return 1;
 117        default:
 118                break;
 119        }
 120
 121        switch (type) {
 122        case S_INT:
 123        case S_HEX:
 124        case S_STRING:
 125                printf("%s\n", def);
 126                return 1;
 127        default:
 128                ;
 129        }
 130        printf("%s", line);
 131        return 1;
 132}
 133
 134static int conf_string(struct menu *menu)
 135{
 136        struct symbol *sym = menu->sym;
 137        const char *def;
 138
 139        while (1) {
 140                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 141                printf("(%s) ", sym->name);
 142                def = sym_get_string_value(sym);
 143                if (sym_get_string_value(sym))
 144                        printf("[%s] ", def);
 145                if (!conf_askvalue(sym, def))
 146                        return 0;
 147                switch (line[0]) {
 148                case '\n':
 149                        break;
 150                case '?':
 151                        /* print help */
 152                        if (line[1] == '\n') {
 153                                print_help(menu);
 154                                def = NULL;
 155                                break;
 156                        }
 157                        /* fall through */
 158                default:
 159                        line[strlen(line)-1] = 0;
 160                        def = line;
 161                }
 162                if (def && sym_set_string_value(sym, def))
 163                        return 0;
 164        }
 165}
 166
 167static int conf_sym(struct menu *menu)
 168{
 169        struct symbol *sym = menu->sym;
 170        tristate oldval, newval;
 171
 172        while (1) {
 173                printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
 174                if (sym->name)
 175                        printf("(%s) ", sym->name);
 176                putchar('[');
 177                oldval = sym_get_tristate_value(sym);
 178                switch (oldval) {
 179                case no:
 180                        putchar('N');
 181                        break;
 182                case mod:
 183                        putchar('M');
 184                        break;
 185                case yes:
 186                        putchar('Y');
 187                        break;
 188                }
 189                if (oldval != no && sym_tristate_within_range(sym, no))
 190                        printf("/n");
 191                if (oldval != mod && sym_tristate_within_range(sym, mod))
 192                        printf("/m");
 193                if (oldval != yes && sym_tristate_within_range(sym, yes))
 194                        printf("/y");
 195                if (menu_has_help(menu))
 196                        printf("/?");
 197                printf("] ");
 198                if (!conf_askvalue(sym, sym_get_string_value(sym)))
 199                        return 0;
 200                strip(line);
 201
 202                switch (line[0]) {
 203                case 'n':
 204                case 'N':
 205                        newval = no;
 206                        if (!line[1] || !strcmp(&line[1], "o"))
 207                                break;
 208                        continue;
 209                case 'm':
 210                case 'M':
 211                        newval = mod;
 212                        if (!line[1])
 213                                break;
 214                        continue;
 215                case 'y':
 216                case 'Y':
 217                        newval = yes;
 218                        if (!line[1] || !strcmp(&line[1], "es"))
 219                                break;
 220                        continue;
 221                case 0:
 222                        newval = oldval;
 223                        break;
 224                case '?':
 225                        goto help;
 226                default:
 227                        continue;
 228                }
 229                if (sym_set_tristate_value(sym, newval))
 230                        return 0;
 231help:
 232                print_help(menu);
 233        }
 234}
 235
 236static int conf_choice(struct menu *menu)
 237{
 238        struct symbol *sym, *def_sym;
 239        struct menu *child;
 240        bool is_new;
 241
 242        sym = menu->sym;
 243        is_new = !sym_has_value(sym);
 244        if (sym_is_changable(sym)) {
 245                conf_sym(menu);
 246                sym_calc_value(sym);
 247                switch (sym_get_tristate_value(sym)) {
 248                case no:
 249                        return 1;
 250                case mod:
 251                        return 0;
 252                case yes:
 253                        break;
 254                }
 255        } else {
 256                switch (sym_get_tristate_value(sym)) {
 257                case no:
 258                        return 1;
 259                case mod:
 260                        printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 261                        return 0;
 262                case yes:
 263                        break;
 264                }
 265        }
 266
 267        while (1) {
 268                int cnt, def;
 269
 270                printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
 271                def_sym = sym_get_choice_value(sym);
 272                cnt = def = 0;
 273                line[0] = 0;
 274                for (child = menu->list; child; child = child->next) {
 275                        if (!menu_is_visible(child))
 276                                continue;
 277                        if (!child->sym) {
 278                                printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
 279                                continue;
 280                        }
 281                        cnt++;
 282                        if (child->sym == def_sym) {
 283                                def = cnt;
 284                                printf("%*c", indent, '>');
 285                        } else
 286                                printf("%*c", indent, ' ');
 287                        printf(" %d. %s", cnt, _(menu_get_prompt(child)));
 288                        if (child->sym->name)
 289                                printf(" (%s)", child->sym->name);
 290                        if (!sym_has_value(child->sym))
 291                                printf(_(" (NEW)"));
 292                        printf("\n");
 293                }
 294                printf(_("%*schoice"), indent - 1, "");
 295                if (cnt == 1) {
 296                        printf("[1]: 1\n");
 297                        goto conf_childs;
 298                }
 299                printf("[1-%d", cnt);
 300                if (menu_has_help(menu))
 301                        printf("?");
 302                printf("]: ");
 303                switch (input_mode) {
 304                case oldconfig:
 305                case silentoldconfig:
 306                        if (!is_new) {
 307                                cnt = def;
 308                                printf("%d\n", cnt);
 309                                break;
 310                        }
 311                        check_stdin();
 312                        /* fall through */
 313                case oldaskconfig:
 314                        fflush(stdout);
 315                        xfgets(line, sizeof(line), stdin);
 316                        strip(line);
 317                        if (line[0] == '?') {
 318                                print_help(menu);
 319                                continue;
 320                        }
 321                        if (!line[0])
 322                                cnt = def;
 323                        else if (isdigit(line[0]))
 324                                cnt = atoi(line);
 325                        else
 326                                continue;
 327                        break;
 328                default:
 329                        break;
 330                }
 331
 332        conf_childs:
 333                for (child = menu->list; child; child = child->next) {
 334                        if (!child->sym || !menu_is_visible(child))
 335                                continue;
 336                        if (!--cnt)
 337                                break;
 338                }
 339                if (!child)
 340                        continue;
 341                if (line[0] && line[strlen(line) - 1] == '?') {
 342                        print_help(child);
 343                        continue;
 344                }
 345                sym_set_choice_value(sym, child->sym);
 346                for (child = child->list; child; child = child->next) {
 347                        indent += 2;
 348                        conf(child);
 349                        indent -= 2;
 350                }
 351                return 1;
 352        }
 353}
 354
 355static void conf(struct menu *menu)
 356{
 357        struct symbol *sym;
 358        struct property *prop;
 359        struct menu *child;
 360
 361        if (!menu_is_visible(menu))
 362                return;
 363
 364        sym = menu->sym;
 365        prop = menu->prompt;
 366        if (prop) {
 367                const char *prompt;
 368
 369                switch (prop->type) {
 370                case P_MENU:
 371                        if ((input_mode == silentoldconfig ||
 372                             input_mode == listnewconfig ||
 373                             input_mode == olddefconfig) &&
 374                            rootEntry != menu) {
 375                                check_conf(menu);
 376                                return;
 377                        }
 378                        /* fall through */
 379                case P_COMMENT:
 380                        prompt = menu_get_prompt(menu);
 381                        if (prompt)
 382                                printf("%*c\n%*c %s\n%*c\n",
 383                                        indent, '*',
 384                                        indent, '*', _(prompt),
 385                                        indent, '*');
 386                default:
 387                        ;
 388                }
 389        }
 390
 391        if (!sym)
 392                goto conf_childs;
 393
 394        if (sym_is_choice(sym)) {
 395                conf_choice(menu);
 396                if (sym->curr.tri != mod)
 397                        return;
 398                goto conf_childs;
 399        }
 400
 401        switch (sym->type) {
 402        case S_INT:
 403        case S_HEX:
 404        case S_STRING:
 405                conf_string(menu);
 406                break;
 407        default:
 408                conf_sym(menu);
 409                break;
 410        }
 411
 412conf_childs:
 413        if (sym)
 414                indent += 2;
 415        for (child = menu->list; child; child = child->next)
 416                conf(child);
 417        if (sym)
 418                indent -= 2;
 419}
 420
 421static void check_conf(struct menu *menu)
 422{
 423        struct symbol *sym;
 424        struct menu *child;
 425
 426        if (!menu_is_visible(menu))
 427                return;
 428
 429        sym = menu->sym;
 430        if (sym && !sym_has_value(sym)) {
 431                if (sym_is_changable(sym) ||
 432                    (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
 433                        if (input_mode == listnewconfig) {
 434                                if (sym->name && !sym_is_choice_value(sym)) {
 435                                        printf("%s%s\n", CONFIG_, sym->name);
 436                                }
 437                        } else if (input_mode != olddefconfig) {
 438                                if (!conf_cnt++)
 439                                        printf(_("*\n* Restart config...\n*\n"));
 440                                rootEntry = menu_get_parent_menu(menu);
 441                                conf(rootEntry);
 442                        }
 443                }
 444        }
 445
 446        for (child = menu->list; child; child = child->next)
 447                check_conf(child);
 448}
 449
 450static struct option long_opts[] = {
 451        {"oldaskconfig",    no_argument,       NULL, oldaskconfig},
 452        {"oldconfig",       no_argument,       NULL, oldconfig},
 453        {"silentoldconfig", no_argument,       NULL, silentoldconfig},
 454        {"defconfig",       optional_argument, NULL, defconfig},
 455        {"savedefconfig",   required_argument, NULL, savedefconfig},
 456        {"allnoconfig",     no_argument,       NULL, allnoconfig},
 457        {"allyesconfig",    no_argument,       NULL, allyesconfig},
 458        {"allmodconfig",    no_argument,       NULL, allmodconfig},
 459        {"alldefconfig",    no_argument,       NULL, alldefconfig},
 460        {"randconfig",      no_argument,       NULL, randconfig},
 461        {"listnewconfig",   no_argument,       NULL, listnewconfig},
 462        {"olddefconfig",    no_argument,       NULL, olddefconfig},
 463        /*
 464         * oldnoconfig is an alias of olddefconfig, because people already
 465         * are dependent on its behavior(sets new symbols to their default
 466         * value but not 'n') with the counter-intuitive name.
 467         */
 468        {"oldnoconfig",     no_argument,       NULL, olddefconfig},
 469        {NULL, 0, NULL, 0}
 470};
 471
 472static void conf_usage(const char *progname)
 473{
 474
 475        printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
 476        printf("[option] is _one_ of the following:\n");
 477        printf("  --listnewconfig         List new options\n");
 478        printf("  --oldaskconfig          Start a new configuration using a line-oriented program\n");
 479        printf("  --oldconfig             Update a configuration using a provided .config as base\n");
 480        printf("  --silentoldconfig       Same as oldconfig, but quietly, additionally update deps\n");
 481        printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
 482        printf("  --oldnoconfig           An alias of olddefconfig\n");
 483        printf("  --defconfig <file>      New config with default defined in <file>\n");
 484        printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
 485        printf("  --allnoconfig           New config where all options are answered with no\n");
 486        printf("  --allyesconfig          New config where all options are answered with yes\n");
 487        printf("  --allmodconfig          New config where all options are answered with mod\n");
 488        printf("  --alldefconfig          New config with all symbols set to default\n");
 489        printf("  --randconfig            New config with random answer to all options\n");
 490}
 491
 492int main(int ac, char **av)
 493{
 494        const char *progname = av[0];
 495        int opt;
 496        const char *name, *defconfig_file = NULL /* gcc uninit */;
 497        struct stat tmpstat;
 498
 499        setlocale(LC_ALL, "");
 500        bindtextdomain(PACKAGE, LOCALEDIR);
 501        textdomain(PACKAGE);
 502
 503        tty_stdio = isatty(0) && isatty(1) && isatty(2);
 504
 505        while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
 506                if (opt == 's') {
 507                        conf_set_message_callback(NULL);
 508                        continue;
 509                }
 510                input_mode = (enum input_mode)opt;
 511                switch (opt) {
 512                case silentoldconfig:
 513                        sync_kconfig = 1;
 514                        break;
 515                case defconfig:
 516                case savedefconfig:
 517                        defconfig_file = optarg;
 518                        break;
 519                case randconfig:
 520                {
 521                        struct timeval now;
 522                        unsigned int seed;
 523                        char *seed_env;
 524
 525                        /*
 526                         * Use microseconds derived seed,
 527                         * compensate for systems where it may be zero
 528                         */
 529                        gettimeofday(&now, NULL);
 530                        seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
 531
 532                        seed_env = getenv("KCONFIG_SEED");
 533                        if( seed_env && *seed_env ) {
 534                                char *endp;
 535                                int tmp = (int)strtol(seed_env, &endp, 0);
 536                                if (*endp == '\0') {
 537                                        seed = tmp;
 538                                }
 539                        }
 540                        fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
 541                        srand(seed);
 542                        break;
 543                }
 544                case oldaskconfig:
 545                case oldconfig:
 546                case allnoconfig:
 547                case allyesconfig:
 548                case allmodconfig:
 549                case alldefconfig:
 550                case listnewconfig:
 551                case olddefconfig:
 552                        break;
 553                case '?':
 554                        conf_usage(progname);
 555                        exit(1);
 556                        break;
 557                }
 558        }
 559        if (ac == optind) {
 560                printf(_("%s: Kconfig file missing\n"), av[0]);
 561                conf_usage(progname);
 562                exit(1);
 563        }
 564        name = av[optind];
 565        conf_parse(name);
 566        //zconfdump(stdout);
 567        if (sync_kconfig) {
 568                name = conf_get_configname();
 569                if (stat(name, &tmpstat)) {
 570                        fprintf(stderr, _("***\n"
 571                                "*** Configuration file \"%s\" not found!\n"
 572                                "***\n"
 573                                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
 574                                "*** \"make menuconfig\" or \"make xconfig\").\n"
 575                                "***\n"), name);
 576                        exit(1);
 577                }
 578        }
 579
 580        switch (input_mode) {
 581        case defconfig:
 582                if (!defconfig_file)
 583                        defconfig_file = conf_get_default_confname();
 584                if (conf_read(defconfig_file)) {
 585                        printf(_("***\n"
 586                                "*** Can't find default configuration \"%s\"!\n"
 587                                "***\n"), defconfig_file);
 588                        exit(1);
 589                }
 590                break;
 591        case savedefconfig:
 592        case silentoldconfig:
 593        case oldaskconfig:
 594        case oldconfig:
 595        case listnewconfig:
 596        case olddefconfig:
 597                conf_read(NULL);
 598                break;
 599        case allnoconfig:
 600        case allyesconfig:
 601        case allmodconfig:
 602        case alldefconfig:
 603        case randconfig:
 604                name = getenv("KCONFIG_ALLCONFIG");
 605                if (!name)
 606                        break;
 607                if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
 608                        if (conf_read_simple(name, S_DEF_USER)) {
 609                                fprintf(stderr,
 610                                        _("*** Can't read seed configuration \"%s\"!\n"),
 611                                        name);
 612                                exit(1);
 613                        }
 614                        break;
 615                }
 616                switch (input_mode) {
 617                case allnoconfig:       name = "allno.config"; break;
 618                case allyesconfig:      name = "allyes.config"; break;
 619                case allmodconfig:      name = "allmod.config"; break;
 620                case alldefconfig:      name = "alldef.config"; break;
 621                case randconfig:        name = "allrandom.config"; break;
 622                default: break;
 623                }
 624                if (conf_read_simple(name, S_DEF_USER) &&
 625                    conf_read_simple("all.config", S_DEF_USER)) {
 626                        fprintf(stderr,
 627                                _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
 628                                name);
 629                        exit(1);
 630                }
 631                break;
 632        default:
 633                break;
 634        }
 635
 636        if (sync_kconfig) {
 637                if (conf_get_changed()) {
 638                        name = getenv("KCONFIG_NOSILENTUPDATE");
 639                        if (name && *name) {
 640                                fprintf(stderr,
 641                                        _("\n*** The configuration requires explicit update.\n\n"));
 642                                return 1;
 643                        }
 644                }
 645                valid_stdin = tty_stdio;
 646        }
 647
 648        switch (input_mode) {
 649        case allnoconfig:
 650                conf_set_all_new_symbols(def_no);
 651                break;
 652        case allyesconfig:
 653                conf_set_all_new_symbols(def_yes);
 654                break;
 655        case allmodconfig:
 656                conf_set_all_new_symbols(def_mod);
 657                break;
 658        case alldefconfig:
 659                conf_set_all_new_symbols(def_default);
 660                break;
 661        case randconfig:
 662                /* Really nothing to do in this loop */
 663                while (conf_set_all_new_symbols(def_random)) ;
 664                break;
 665        case defconfig:
 666                conf_set_all_new_symbols(def_default);
 667                break;
 668        case savedefconfig:
 669                break;
 670        case oldaskconfig:
 671                rootEntry = &rootmenu;
 672                conf(&rootmenu);
 673                input_mode = silentoldconfig;
 674                /* fall through */
 675        case oldconfig:
 676        case listnewconfig:
 677        case olddefconfig:
 678        case silentoldconfig:
 679                /* Update until a loop caused no more changes */
 680                do {
 681                        conf_cnt = 0;
 682                        check_conf(&rootmenu);
 683                } while (conf_cnt &&
 684                         (input_mode != listnewconfig &&
 685                          input_mode != olddefconfig));
 686                break;
 687        }
 688
 689        if (sync_kconfig) {
 690                /* silentoldconfig is used during the build so we shall update autoconf.
 691                 * All other commands are only used to generate a config.
 692                 */
 693                if (conf_get_changed() && conf_write(NULL)) {
 694                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 695                        exit(1);
 696                }
 697                if (conf_write_autoconf()) {
 698                        fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
 699                        return 1;
 700                }
 701        } else if (input_mode == savedefconfig) {
 702                if (conf_write_defconfig(defconfig_file)) {
 703                        fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
 704                                defconfig_file);
 705                        return 1;
 706                }
 707        } else if (input_mode != listnewconfig) {
 708                if (conf_write(NULL)) {
 709                        fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
 710                        exit(1);
 711                }
 712        }
 713        return 0;
 714}
 715
 716/*
 717 * Helper function to facilitate fgets() by Jean Sacren.
 718 */
 719void xfgets(char *str, int size, FILE *in)
 720{
 721        if (fgets(str, size, in) == NULL)
 722                fprintf(stderr, "\nError in reading or end of file.\n");
 723}
 724