| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 | /* * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> * Released under the terms of the GNU GPL v2.0. */#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <time.h>#include <sys/stat.h>#define LKC_DIRECT_LINK#include "lkc.h"static void conf(struct menu *menu);static void check_conf(struct menu *menu);enum {	ask_all,	ask_new,	ask_silent,	set_default,	set_yes,	set_mod,	set_no,	set_random} input_mode = ask_all;char *defconfig_file;static int indent = 1;static int valid_stdin = 1;static int conf_cnt;static signed char line[128];static struct menu *rootEntry;static char nohelp_text[] = "Sorry, no help available for this option yet.\n";static void strip(signed char *str){	signed char *p = str;	int l;	while ((isspace(*p)))		p++;	l = strlen(p);	if (p != str)		memmove(str, p, l + 1);	if (!l)		return;	p = str + l - 1;	while ((isspace(*p)))		*p-- = 0;}static void check_stdin(void){	if (!valid_stdin && input_mode == ask_silent) {		printf("aborted!\n\n");		printf("Console input/output is redirected. ");		printf("Run 'make oldconfig' to update configuration.\n\n");		exit(1);	}}static void conf_askvalue(struct symbol *sym, const char *def){	enum symbol_type type = sym_get_type(sym);	tristate val;	if (!sym_has_value(sym))		printf("(NEW) ");	line[0] = '\n';	line[1] = 0;	if (!sym_is_changable(sym)) {		printf("%s\n", def);		line[0] = '\n';		line[1] = 0;		return;	}	switch (input_mode) {	case ask_new:	case ask_silent:		if (sym_has_value(sym)) {			printf("%s\n", def);			return;		}		check_stdin();	case ask_all:		fflush(stdout);		fgets(line, 128, stdin);		return;	case set_default:		printf("%s\n", def);		return;	default:		break;	}	switch (type) {	case S_INT:	case S_HEX:	case S_STRING:		printf("%s\n", def);		return;	default:		;	}	switch (input_mode) {	case set_yes:		if (sym_tristate_within_range(sym, yes)) {			line[0] = 'y';			line[1] = '\n';			line[2] = 0;			break;		}	case set_mod:		if (type == S_TRISTATE) {			if (sym_tristate_within_range(sym, mod)) {				line[0] = 'm';				line[1] = '\n';				line[2] = 0;				break;			}		} else {			if (sym_tristate_within_range(sym, yes)) {				line[0] = 'y';				line[1] = '\n';				line[2] = 0;				break;			}		}	case set_no:		if (sym_tristate_within_range(sym, no)) {			line[0] = 'n';			line[1] = '\n';			line[2] = 0;			break;		}	case set_random:		do {			val = (tristate)(random() % 3);		} while (!sym_tristate_within_range(sym, val));		switch (val) {		case no: line[0] = 'n'; break;		case mod: line[0] = 'm'; break;		case yes: line[0] = 'y'; break;		}		line[1] = '\n';		line[2] = 0;		break;	default:		break;	}	printf("%s", line);}int conf_string(struct menu *menu){	struct symbol *sym = menu->sym;	const char *def, *help;	while (1) {		printf("%*s%s ", indent - 1, "", menu->prompt->text);		printf("(%s) ", sym->name);		def = sym_get_string_value(sym);		if (sym_get_string_value(sym))			printf("[%s] ", def);		conf_askvalue(sym, def);		switch (line[0]) {		case '\n':			break;		case '?':			/* print help */			if (line[1] == '\n') {				help = nohelp_text;				if (menu->sym->help)					help = menu->sym->help;				printf("\n%s\n", menu->sym->help);				def = NULL;				break;			}		default:			line[strlen(line)-1] = 0;			def = line;		}		if (def && sym_set_string_value(sym, def))			return 0;	}}static int conf_sym(struct menu *menu){	struct symbol *sym = menu->sym;	int type;	tristate oldval, newval;	const char *help;	while (1) {		printf("%*s%s ", indent - 1, "", menu->prompt->text);		if (sym->name)			printf("(%s) ", sym->name);		type = sym_get_type(sym);		putchar('[');		oldval = sym_get_tristate_value(sym);		switch (oldval) {		case no:			putchar('N');			break;		case mod:			putchar('M');			break;		case yes:			putchar('Y');			break;		}		if (oldval != no && sym_tristate_within_range(sym, no))			printf("/n");		if (oldval != mod && sym_tristate_within_range(sym, mod))			printf("/m");		if (oldval != yes && sym_tristate_within_range(sym, yes))			printf("/y");		if (sym->help)			printf("/?");		printf("] ");		conf_askvalue(sym, sym_get_string_value(sym));		strip(line);		switch (line[0]) {		case 'n':		case 'N':			newval = no;			if (!line[1] || !strcmp(&line[1], "o"))				break;			continue;		case 'm':		case 'M':			newval = mod;			if (!line[1])				break;			continue;		case 'y':		case 'Y':			newval = yes;			if (!line[1] || !strcmp(&line[1], "es"))				break;			continue;		case 0:			newval = oldval;			break;		case '?':			goto help;		default:			continue;		}		if (sym_set_tristate_value(sym, newval))			return 0;help:		help = nohelp_text;		if (sym->help)			help = sym->help;		printf("\n%s\n", help);	}}static int conf_choice(struct menu *menu){	struct symbol *sym, *def_sym;	struct menu *child;	int type;	bool is_new;	sym = menu->sym;	type = sym_get_type(sym);	is_new = !sym_has_value(sym);	if (sym_is_changable(sym)) {		conf_sym(menu);		sym_calc_value(sym);		switch (sym_get_tristate_value(sym)) {		case no:			return 1;		case mod:			return 0;		case yes:			break;		}	} else {		switch (sym_get_tristate_value(sym)) {		case no:			return 1;		case mod:			printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));			return 0;		case yes:			break;		}	}	while (1) {		int cnt, def;		printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));		def_sym = sym_get_choice_value(sym);		cnt = def = 0;		line[0] = '0';		line[1] = 0;		for (child = menu->list; child; child = child->next) {			if (!menu_is_visible(child))				continue;			if (!child->sym) {				printf("%*c %s\n", indent, '*', menu_get_prompt(child));				continue;			}			cnt++;			if (child->sym == def_sym) {				def = cnt;				printf("%*c", indent, '>');			} else				printf("%*c", indent, ' ');			printf(" %d. %s", cnt, menu_get_prompt(child));			if (child->sym->name)				printf(" (%s)", child->sym->name);			if (!sym_has_value(child->sym))				printf(" (NEW)");			printf("\n");		}		printf("%*schoice", indent - 1, "");		if (cnt == 1) {			printf("[1]: 1\n");			goto conf_childs;		}		printf("[1-%d", cnt);		if (sym->help)			printf("?");		printf("]: ");		switch (input_mode) {		case ask_new:		case ask_silent:			if (!is_new) {				cnt = def;				printf("%d\n", cnt);				break;			}			check_stdin();		case ask_all:			fflush(stdout);			fgets(line, 128, stdin);			strip(line);			if (line[0] == '?') {				printf("\n%s\n", menu->sym->help ?					menu->sym->help : nohelp_text);				continue;			}			if (!line[0])				cnt = def;			else if (isdigit(line[0]))				cnt = atoi(line);			else				continue;			break;		case set_random:			def = (random() % cnt) + 1;		case set_default:		case set_yes:		case set_mod:		case set_no:			cnt = def;			printf("%d\n", cnt);			break;		}	conf_childs:		for (child = menu->list; child; child = child->next) {			if (!child->sym || !menu_is_visible(child))				continue;			if (!--cnt)				break;		}		if (!child)			continue;		if (line[strlen(line) - 1] == '?') {			printf("\n%s\n", child->sym->help ?				child->sym->help : nohelp_text);			continue;		}		sym_set_choice_value(sym, child->sym);		if (child->list) {			indent += 2;			conf(child->list);			indent -= 2;		}		return 1;	}}static void conf(struct menu *menu){	struct symbol *sym;	struct property *prop;	struct menu *child;	if (!menu_is_visible(menu))		return;	sym = menu->sym;	prop = menu->prompt;	if (prop) {		const char *prompt;		switch (prop->type) {		case P_MENU:			if (input_mode == ask_silent && rootEntry != menu) {				check_conf(menu);				return;			}		case P_COMMENT:			prompt = menu_get_prompt(menu);			if (prompt)				printf("%*c\n%*c %s\n%*c\n",					indent, '*',					indent, '*', prompt,					indent, '*');		default:			;		}	}	if (!sym)		goto conf_childs;	if (sym_is_choice(sym)) {		conf_choice(menu);		if (sym->curr.tri != mod)			return;		goto conf_childs;	}	switch (sym->type) {	case S_INT:	case S_HEX:	case S_STRING:		conf_string(menu);		break;	default:		conf_sym(menu);		break;	}conf_childs:	if (sym)		indent += 2;	for (child = menu->list; child; child = child->next)		conf(child);	if (sym)		indent -= 2;}static void check_conf(struct menu *menu){	struct symbol *sym;	struct menu *child;	if (!menu_is_visible(menu))		return;	sym = menu->sym;	if (sym) {		if (sym_is_changable(sym) && !sym_has_value(sym)) {			if (!conf_cnt++)				printf("*\n* Restart config...\n*\n");			rootEntry = menu_get_parent_menu(menu);			conf(rootEntry);		}		if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)			return;	}	for (child = menu->list; child; child = child->next)		check_conf(child);}int main(int ac, char **av){	int i = 1;	const char *name;	struct stat tmpstat;	if (ac > i && av[i][0] == '-') {		switch (av[i++][1]) {		case 'o':			input_mode = ask_new;			break;		case 's':			input_mode = ask_silent;			valid_stdin = isatty(0) && isatty(1) && isatty(2);			break;		case 'd':			input_mode = set_default;			break;		case 'D':			input_mode = set_default;			defconfig_file = av[i++];			if (!defconfig_file) {				printf("%s: No default config file specified\n",					av[0]);				exit(1);			}			break;		case 'n':			input_mode = set_no;			break;		case 'm':			input_mode = set_mod;			break;		case 'y':			input_mode = set_yes;			break;		case 'r':			input_mode = set_random;			srandom(time(NULL));			break;		case 'h':		case '?':			printf("%s [-o|-s] config\n", av[0]);			exit(0);		}	}  	name = av[i];	if (!name) {		printf("%s: configuration file missing\n", av[0]);	}	conf_parse(name);	//zconfdump(stdout);	switch (input_mode) {	case set_default:		if (!defconfig_file)			defconfig_file = conf_get_default_confname();		if (conf_read(defconfig_file)) {			printf("***\n"				"*** Can't find default configuration \"%s\"!\n"				"***\n", defconfig_file);			exit(1);		}		break;	case ask_silent:		if (stat(".config", &tmpstat)) {			printf("***\n"				"*** You have not yet configured uClibc!\n"				"***\n"				"*** Please run some configurator (e.g. \"make oldconfig\" or\n"				"*** \"make menuconfig\" or \"make config\").\n"				"***\n");			exit(1);		}	case ask_all:	case ask_new:		conf_read(NULL);		break;	default:		break;	}	if (input_mode != ask_silent) {		rootEntry = &rootmenu;		conf(&rootmenu);		if (input_mode == ask_all) {			input_mode = ask_silent;			valid_stdin = 1;		}	}	do {		conf_cnt = 0;		check_conf(&rootmenu);	} while (conf_cnt);	if (conf_write(NULL)) {		fprintf(stderr, "\n*** Error during writing of the uClibc configuration.\n\n");		return 1;	}	return 0;}
 |