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