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