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