xref: /linux/scripts/kconfig/conf.c (revision 5a3dc717b3c785242e6d40f08288947cb6751ee4)
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       Same as oldconfig, but quietly, additionally update deps\n");
488 	printf("  --olddefconfig          Same as silentoldconfig but sets new symbols to their default value\n");
489 	printf("  --oldnoconfig           An alias of olddefconfig\n");
490 	printf("  --defconfig <file>      New config with default defined in <file>\n");
491 	printf("  --savedefconfig <file>  Save the minimal current configuration to <file>\n");
492 	printf("  --allnoconfig           New config where all options are answered with no\n");
493 	printf("  --allyesconfig          New config where all options are answered with yes\n");
494 	printf("  --allmodconfig          New config where all options are answered with mod\n");
495 	printf("  --alldefconfig          New config with all symbols set to default\n");
496 	printf("  --randconfig            New config with random answer to all options\n");
497 }
498 
499 int main(int ac, char **av)
500 {
501 	const char *progname = av[0];
502 	int opt;
503 	const char *name, *defconfig_file = NULL /* gcc uninit */;
504 	struct stat tmpstat;
505 
506 	setlocale(LC_ALL, "");
507 	bindtextdomain(PACKAGE, LOCALEDIR);
508 	textdomain(PACKAGE);
509 
510 	tty_stdio = isatty(0) && isatty(1) && isatty(2);
511 
512 	while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
513 		if (opt == 's') {
514 			conf_set_message_callback(NULL);
515 			continue;
516 		}
517 		input_mode = (enum input_mode)opt;
518 		switch (opt) {
519 		case silentoldconfig:
520 			sync_kconfig = 1;
521 			break;
522 		case defconfig:
523 		case savedefconfig:
524 			defconfig_file = optarg;
525 			break;
526 		case randconfig:
527 		{
528 			struct timeval now;
529 			unsigned int seed;
530 			char *seed_env;
531 
532 			/*
533 			 * Use microseconds derived seed,
534 			 * compensate for systems where it may be zero
535 			 */
536 			gettimeofday(&now, NULL);
537 			seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
538 
539 			seed_env = getenv("KCONFIG_SEED");
540 			if( seed_env && *seed_env ) {
541 				char *endp;
542 				int tmp = (int)strtol(seed_env, &endp, 0);
543 				if (*endp == '\0') {
544 					seed = tmp;
545 				}
546 			}
547 			fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
548 			srand(seed);
549 			break;
550 		}
551 		case oldaskconfig:
552 		case oldconfig:
553 		case allnoconfig:
554 		case allyesconfig:
555 		case allmodconfig:
556 		case alldefconfig:
557 		case listnewconfig:
558 		case olddefconfig:
559 			break;
560 		case '?':
561 			conf_usage(progname);
562 			exit(1);
563 			break;
564 		}
565 	}
566 	if (ac == optind) {
567 		printf(_("%s: Kconfig file missing\n"), av[0]);
568 		conf_usage(progname);
569 		exit(1);
570 	}
571 	name = av[optind];
572 	conf_parse(name);
573 	//zconfdump(stdout);
574 	if (sync_kconfig) {
575 		name = conf_get_configname();
576 		if (stat(name, &tmpstat)) {
577 			fprintf(stderr, _("***\n"
578 				"*** Configuration file \"%s\" not found!\n"
579 				"***\n"
580 				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
581 				"*** \"make menuconfig\" or \"make xconfig\").\n"
582 				"***\n"), name);
583 			exit(1);
584 		}
585 	}
586 
587 	switch (input_mode) {
588 	case defconfig:
589 		if (!defconfig_file)
590 			defconfig_file = conf_get_default_confname();
591 		if (conf_read(defconfig_file)) {
592 			printf(_("***\n"
593 				"*** Can't find default configuration \"%s\"!\n"
594 				"***\n"), defconfig_file);
595 			exit(1);
596 		}
597 		break;
598 	case savedefconfig:
599 	case silentoldconfig:
600 	case oldaskconfig:
601 	case oldconfig:
602 	case listnewconfig:
603 	case olddefconfig:
604 		conf_read(NULL);
605 		break;
606 	case allnoconfig:
607 	case allyesconfig:
608 	case allmodconfig:
609 	case alldefconfig:
610 	case randconfig:
611 		name = getenv("KCONFIG_ALLCONFIG");
612 		if (!name)
613 			break;
614 		if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
615 			if (conf_read_simple(name, S_DEF_USER)) {
616 				fprintf(stderr,
617 					_("*** Can't read seed configuration \"%s\"!\n"),
618 					name);
619 				exit(1);
620 			}
621 			break;
622 		}
623 		switch (input_mode) {
624 		case allnoconfig:	name = "allno.config"; break;
625 		case allyesconfig:	name = "allyes.config"; break;
626 		case allmodconfig:	name = "allmod.config"; break;
627 		case alldefconfig:	name = "alldef.config"; break;
628 		case randconfig:	name = "allrandom.config"; break;
629 		default: break;
630 		}
631 		if (conf_read_simple(name, S_DEF_USER) &&
632 		    conf_read_simple("all.config", S_DEF_USER)) {
633 			fprintf(stderr,
634 				_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
635 				name);
636 			exit(1);
637 		}
638 		break;
639 	default:
640 		break;
641 	}
642 
643 	if (sync_kconfig) {
644 		if (conf_get_changed()) {
645 			name = getenv("KCONFIG_NOSILENTUPDATE");
646 			if (name && *name) {
647 				fprintf(stderr,
648 					_("\n*** The configuration requires explicit update.\n\n"));
649 				return 1;
650 			}
651 		}
652 		valid_stdin = tty_stdio;
653 	}
654 
655 	switch (input_mode) {
656 	case allnoconfig:
657 		conf_set_all_new_symbols(def_no);
658 		break;
659 	case allyesconfig:
660 		conf_set_all_new_symbols(def_yes);
661 		break;
662 	case allmodconfig:
663 		conf_set_all_new_symbols(def_mod);
664 		break;
665 	case alldefconfig:
666 		conf_set_all_new_symbols(def_default);
667 		break;
668 	case randconfig:
669 		/* Really nothing to do in this loop */
670 		while (conf_set_all_new_symbols(def_random)) ;
671 		break;
672 	case defconfig:
673 		conf_set_all_new_symbols(def_default);
674 		break;
675 	case savedefconfig:
676 		break;
677 	case oldaskconfig:
678 		rootEntry = &rootmenu;
679 		conf(&rootmenu);
680 		input_mode = silentoldconfig;
681 		/* fall through */
682 	case oldconfig:
683 	case listnewconfig:
684 	case olddefconfig:
685 	case silentoldconfig:
686 		/* Update until a loop caused no more changes */
687 		do {
688 			conf_cnt = 0;
689 			check_conf(&rootmenu);
690 		} while (conf_cnt &&
691 			 (input_mode != listnewconfig &&
692 			  input_mode != olddefconfig));
693 		break;
694 	}
695 
696 	if (sync_kconfig) {
697 		/* silentoldconfig is used during the build so we shall update autoconf.
698 		 * All other commands are only used to generate a config.
699 		 */
700 		if (conf_get_changed() && conf_write(NULL)) {
701 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
702 			exit(1);
703 		}
704 		if (conf_write_autoconf()) {
705 			fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
706 			return 1;
707 		}
708 	} else if (input_mode == savedefconfig) {
709 		if (conf_write_defconfig(defconfig_file)) {
710 			fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
711 				defconfig_file);
712 			return 1;
713 		}
714 	} else if (input_mode != listnewconfig) {
715 		if (conf_write(NULL)) {
716 			fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
717 			exit(1);
718 		}
719 	}
720 	return 0;
721 }
722