conf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. def = (random() % cnt) + 1;
  353. case set_default:
  354. case set_yes:
  355. case set_mod:
  356. case set_no:
  357. cnt = def;
  358. printf("%d\n", cnt);
  359. break;
  360. }
  361. conf_childs:
  362. for (child = menu->list; child; child = child->next) {
  363. if (!child->sym || !menu_is_visible(child))
  364. continue;
  365. if (!--cnt)
  366. break;
  367. }
  368. if (!child)
  369. continue;
  370. if (line[strlen(line) - 1] == '?') {
  371. printf("\n%s\n", get_help(child));
  372. continue;
  373. }
  374. sym_set_choice_value(sym, child->sym);
  375. if (child->list) {
  376. indent += 2;
  377. conf(child->list);
  378. indent -= 2;
  379. }
  380. return 1;
  381. }
  382. }
  383. static void conf(struct menu *menu)
  384. {
  385. struct symbol *sym;
  386. struct property *prop;
  387. struct menu *child;
  388. if (!menu_is_visible(menu))
  389. return;
  390. sym = menu->sym;
  391. prop = menu->prompt;
  392. if (prop) {
  393. const char *prompt;
  394. switch (prop->type) {
  395. case P_MENU:
  396. if (input_mode == ask_silent && rootEntry != menu) {
  397. check_conf(menu);
  398. return;
  399. }
  400. case P_COMMENT:
  401. prompt = menu_get_prompt(menu);
  402. if (prompt)
  403. printf("%*c\n%*c %s\n%*c\n",
  404. indent, '*',
  405. indent, '*', prompt,
  406. indent, '*');
  407. default:
  408. ;
  409. }
  410. }
  411. if (!sym)
  412. goto conf_childs;
  413. if (sym_is_choice(sym)) {
  414. conf_choice(menu);
  415. if (sym->curr.tri != mod)
  416. return;
  417. goto conf_childs;
  418. }
  419. switch (sym->type) {
  420. case S_INT:
  421. case S_HEX:
  422. case S_STRING:
  423. conf_string(menu);
  424. break;
  425. default:
  426. conf_sym(menu);
  427. break;
  428. }
  429. conf_childs:
  430. if (sym)
  431. indent += 2;
  432. for (child = menu->list; child; child = child->next)
  433. conf(child);
  434. if (sym)
  435. indent -= 2;
  436. }
  437. static void check_conf(struct menu *menu)
  438. {
  439. struct symbol *sym;
  440. struct menu *child;
  441. if (!menu_is_visible(menu))
  442. return;
  443. sym = menu->sym;
  444. if (sym && !sym_has_value(sym)) {
  445. if (sym_is_changable(sym) ||
  446. (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
  447. if (!conf_cnt++)
  448. printf(_("*\n* Restart config...\n*\n"));
  449. rootEntry = menu_get_parent_menu(menu);
  450. conf(rootEntry);
  451. }
  452. }
  453. for (child = menu->list; child; child = child->next)
  454. check_conf(child);
  455. }
  456. int main(int ac, char **av)
  457. {
  458. int i = 1;
  459. const char *name;
  460. struct stat tmpstat;
  461. if (ac > i && av[i][0] == '-') {
  462. switch (av[i++][1]) {
  463. case 'o':
  464. input_mode = ask_new;
  465. break;
  466. case 's':
  467. input_mode = ask_silent;
  468. valid_stdin = isatty(0) && isatty(1) && isatty(2);
  469. break;
  470. case 'd':
  471. input_mode = set_default;
  472. break;
  473. case 'D':
  474. input_mode = set_default;
  475. defconfig_file = av[i++];
  476. if (!defconfig_file) {
  477. printf(_("%s: No default config file specified\n"),
  478. av[0]);
  479. exit(1);
  480. }
  481. break;
  482. case 'n':
  483. input_mode = set_no;
  484. break;
  485. case 'm':
  486. input_mode = set_mod;
  487. break;
  488. case 'y':
  489. input_mode = set_yes;
  490. break;
  491. case 'r':
  492. input_mode = set_random;
  493. srandom(time(NULL));
  494. break;
  495. case 'h':
  496. case '?':
  497. fprintf(stderr, "See README for usage info\n");
  498. exit(0);
  499. }
  500. }
  501. name = av[i];
  502. if (!name) {
  503. printf(_("%s: Kconfig file missing\n"), av[0]);
  504. exit(1);
  505. }
  506. conf_parse(name);
  507. //zconfdump(stdout);
  508. switch (input_mode) {
  509. case set_default:
  510. if (!defconfig_file)
  511. defconfig_file = conf_get_default_confname();
  512. if (conf_read(defconfig_file)) {
  513. printf("***\n"
  514. "*** Can't find default configuration \"%s\"!\n"
  515. "***\n", defconfig_file);
  516. exit(1);
  517. }
  518. break;
  519. case ask_silent:
  520. if (stat(".config", &tmpstat)) {
  521. printf(_("***\n"
  522. "*** You have not yet configured your kernel!\n"
  523. "*** (missing kernel .config file)\n"
  524. "***\n"
  525. "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
  526. "*** \"make menuconfig\" or \"make xconfig\").\n"
  527. "***\n"));
  528. exit(1);
  529. }
  530. case ask_all:
  531. case ask_new:
  532. conf_read(NULL);
  533. break;
  534. case set_no:
  535. case set_mod:
  536. case set_yes:
  537. case set_random:
  538. name = getenv("KCONFIG_ALLCONFIG");
  539. if (name && !stat(name, &tmpstat)) {
  540. conf_read_simple(name, S_DEF_USER);
  541. break;
  542. }
  543. switch (input_mode) {
  544. case set_no: name = "allno.config"; break;
  545. case set_mod: name = "allmod.config"; break;
  546. case set_yes: name = "allyes.config"; break;
  547. case set_random: name = "allrandom.config"; break;
  548. default: break;
  549. }
  550. if (!stat(name, &tmpstat))
  551. conf_read_simple(name, S_DEF_USER);
  552. else if (!stat("all.config", &tmpstat))
  553. conf_read_simple("all.config", S_DEF_USER);
  554. break;
  555. default:
  556. break;
  557. }
  558. if (input_mode != ask_silent) {
  559. rootEntry = &rootmenu;
  560. conf(&rootmenu);
  561. if (input_mode == ask_all) {
  562. input_mode = ask_silent;
  563. valid_stdin = 1;
  564. }
  565. } else if (conf_get_changed()) {
  566. name = getenv("KCONFIG_NOSILENTUPDATE");
  567. if (name && *name) {
  568. fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
  569. return 1;
  570. }
  571. } else
  572. goto skip_check;
  573. do {
  574. conf_cnt = 0;
  575. check_conf(&rootmenu);
  576. } while (conf_cnt);
  577. if (conf_write(NULL)) {
  578. fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
  579. return 1;
  580. }
  581. skip_check:
  582. if (input_mode == ask_silent && conf_write_autoconf()) {
  583. fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
  584. return 1;
  585. }
  586. return 0;
  587. }