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