conf.c 12 KB

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