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