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