10a9064fbSMasahiro Yamada /* 20a9064fbSMasahiro Yamada * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 30a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0. 40a9064fbSMasahiro Yamada */ 50a9064fbSMasahiro Yamada 60a9064fbSMasahiro Yamada #include <locale.h> 70a9064fbSMasahiro Yamada #include <ctype.h> 80a9064fbSMasahiro Yamada #include <stdio.h> 90a9064fbSMasahiro Yamada #include <stdlib.h> 100a9064fbSMasahiro Yamada #include <string.h> 110a9064fbSMasahiro Yamada #include <time.h> 120a9064fbSMasahiro Yamada #include <unistd.h> 130a9064fbSMasahiro Yamada #include <getopt.h> 140a9064fbSMasahiro Yamada #include <sys/stat.h> 150a9064fbSMasahiro Yamada #include <sys/time.h> 160a9064fbSMasahiro Yamada #include <errno.h> 170a9064fbSMasahiro Yamada 180a9064fbSMasahiro Yamada #include "lkc.h" 190a9064fbSMasahiro Yamada 200a9064fbSMasahiro Yamada static void conf(struct menu *menu); 210a9064fbSMasahiro Yamada static void check_conf(struct menu *menu); 220a9064fbSMasahiro Yamada static void xfgets(char *str, int size, FILE *in); 230a9064fbSMasahiro Yamada 240a9064fbSMasahiro Yamada enum input_mode { 250a9064fbSMasahiro Yamada oldaskconfig, 260a9064fbSMasahiro Yamada silentoldconfig, 270a9064fbSMasahiro Yamada oldconfig, 280a9064fbSMasahiro Yamada allnoconfig, 290a9064fbSMasahiro Yamada allyesconfig, 300a9064fbSMasahiro Yamada allmodconfig, 310a9064fbSMasahiro Yamada alldefconfig, 320a9064fbSMasahiro Yamada randconfig, 330a9064fbSMasahiro Yamada defconfig, 340a9064fbSMasahiro Yamada savedefconfig, 350a9064fbSMasahiro Yamada listnewconfig, 360a9064fbSMasahiro Yamada olddefconfig, 370a9064fbSMasahiro Yamada } input_mode = oldaskconfig; 380a9064fbSMasahiro Yamada 390a9064fbSMasahiro Yamada static int indent = 1; 400a9064fbSMasahiro Yamada static int tty_stdio; 410a9064fbSMasahiro Yamada static int valid_stdin = 1; 420a9064fbSMasahiro Yamada static int sync_kconfig; 430a9064fbSMasahiro Yamada static int conf_cnt; 440a9064fbSMasahiro Yamada static char line[128]; 450a9064fbSMasahiro Yamada static struct menu *rootEntry; 460a9064fbSMasahiro Yamada 470a9064fbSMasahiro Yamada static void print_help(struct menu *menu) 480a9064fbSMasahiro Yamada { 490a9064fbSMasahiro Yamada struct gstr help = str_new(); 500a9064fbSMasahiro Yamada 510a9064fbSMasahiro Yamada menu_get_ext_help(menu, &help); 520a9064fbSMasahiro Yamada 530a9064fbSMasahiro Yamada printf("\n%s\n", str_get(&help)); 540a9064fbSMasahiro Yamada str_free(&help); 550a9064fbSMasahiro Yamada } 560a9064fbSMasahiro Yamada 570a9064fbSMasahiro Yamada static void strip(char *str) 580a9064fbSMasahiro Yamada { 590a9064fbSMasahiro Yamada char *p = str; 600a9064fbSMasahiro Yamada int l; 610a9064fbSMasahiro Yamada 620a9064fbSMasahiro Yamada while ((isspace(*p))) 630a9064fbSMasahiro Yamada p++; 640a9064fbSMasahiro Yamada l = strlen(p); 650a9064fbSMasahiro Yamada if (p != str) 660a9064fbSMasahiro Yamada memmove(str, p, l + 1); 670a9064fbSMasahiro Yamada if (!l) 680a9064fbSMasahiro Yamada return; 690a9064fbSMasahiro Yamada p = str + l - 1; 700a9064fbSMasahiro Yamada while ((isspace(*p))) 710a9064fbSMasahiro Yamada *p-- = 0; 720a9064fbSMasahiro Yamada } 730a9064fbSMasahiro Yamada 740a9064fbSMasahiro Yamada static void check_stdin(void) 750a9064fbSMasahiro Yamada { 760a9064fbSMasahiro Yamada if (!valid_stdin) { 770a9064fbSMasahiro Yamada printf(_("aborted!\n\n")); 780a9064fbSMasahiro Yamada printf(_("Console input/output is redirected. ")); 790a9064fbSMasahiro Yamada printf(_("Run 'make oldconfig' to update configuration.\n\n")); 800a9064fbSMasahiro Yamada exit(1); 810a9064fbSMasahiro Yamada } 820a9064fbSMasahiro Yamada } 830a9064fbSMasahiro Yamada 840a9064fbSMasahiro Yamada static int conf_askvalue(struct symbol *sym, const char *def) 850a9064fbSMasahiro Yamada { 860a9064fbSMasahiro Yamada enum symbol_type type = sym_get_type(sym); 870a9064fbSMasahiro Yamada 880a9064fbSMasahiro Yamada if (!sym_has_value(sym)) 890a9064fbSMasahiro Yamada printf(_("(NEW) ")); 900a9064fbSMasahiro Yamada 910a9064fbSMasahiro Yamada line[0] = '\n'; 920a9064fbSMasahiro Yamada line[1] = 0; 930a9064fbSMasahiro Yamada 940a9064fbSMasahiro Yamada if (!sym_is_changable(sym)) { 950a9064fbSMasahiro Yamada printf("%s\n", def); 960a9064fbSMasahiro Yamada line[0] = '\n'; 970a9064fbSMasahiro Yamada line[1] = 0; 980a9064fbSMasahiro Yamada return 0; 990a9064fbSMasahiro Yamada } 1000a9064fbSMasahiro Yamada 1010a9064fbSMasahiro Yamada switch (input_mode) { 1020a9064fbSMasahiro Yamada case oldconfig: 1030a9064fbSMasahiro Yamada case silentoldconfig: 1040a9064fbSMasahiro Yamada if (sym_has_value(sym)) { 1050a9064fbSMasahiro Yamada printf("%s\n", def); 1060a9064fbSMasahiro Yamada return 0; 1070a9064fbSMasahiro Yamada } 1080a9064fbSMasahiro Yamada check_stdin(); 1090a9064fbSMasahiro Yamada /* fall through */ 1100a9064fbSMasahiro Yamada case oldaskconfig: 1110a9064fbSMasahiro Yamada fflush(stdout); 1120a9064fbSMasahiro Yamada xfgets(line, 128, stdin); 1130a9064fbSMasahiro Yamada if (!tty_stdio) 1140a9064fbSMasahiro Yamada printf("\n"); 1150a9064fbSMasahiro Yamada return 1; 1160a9064fbSMasahiro Yamada default: 1170a9064fbSMasahiro Yamada break; 1180a9064fbSMasahiro Yamada } 1190a9064fbSMasahiro Yamada 1200a9064fbSMasahiro Yamada switch (type) { 1210a9064fbSMasahiro Yamada case S_INT: 1220a9064fbSMasahiro Yamada case S_HEX: 1230a9064fbSMasahiro Yamada case S_STRING: 1240a9064fbSMasahiro Yamada printf("%s\n", def); 1250a9064fbSMasahiro Yamada return 1; 1260a9064fbSMasahiro Yamada default: 1270a9064fbSMasahiro Yamada ; 1280a9064fbSMasahiro Yamada } 1290a9064fbSMasahiro Yamada printf("%s", line); 1300a9064fbSMasahiro Yamada return 1; 1310a9064fbSMasahiro Yamada } 1320a9064fbSMasahiro Yamada 1330a9064fbSMasahiro Yamada static int conf_string(struct menu *menu) 1340a9064fbSMasahiro Yamada { 1350a9064fbSMasahiro Yamada struct symbol *sym = menu->sym; 1360a9064fbSMasahiro Yamada const char *def; 1370a9064fbSMasahiro Yamada 1380a9064fbSMasahiro Yamada while (1) { 1390a9064fbSMasahiro Yamada printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 1400a9064fbSMasahiro Yamada printf("(%s) ", sym->name); 1410a9064fbSMasahiro Yamada def = sym_get_string_value(sym); 1420a9064fbSMasahiro Yamada if (sym_get_string_value(sym)) 1430a9064fbSMasahiro Yamada printf("[%s] ", def); 1440a9064fbSMasahiro Yamada if (!conf_askvalue(sym, def)) 1450a9064fbSMasahiro Yamada return 0; 1460a9064fbSMasahiro Yamada switch (line[0]) { 1470a9064fbSMasahiro Yamada case '\n': 1480a9064fbSMasahiro Yamada break; 1490a9064fbSMasahiro Yamada case '?': 1500a9064fbSMasahiro Yamada /* print help */ 1510a9064fbSMasahiro Yamada if (line[1] == '\n') { 1520a9064fbSMasahiro Yamada print_help(menu); 1530a9064fbSMasahiro Yamada def = NULL; 1540a9064fbSMasahiro Yamada break; 1550a9064fbSMasahiro Yamada } 1560a9064fbSMasahiro Yamada /* fall through */ 1570a9064fbSMasahiro Yamada default: 1580a9064fbSMasahiro Yamada line[strlen(line)-1] = 0; 1590a9064fbSMasahiro Yamada def = line; 1600a9064fbSMasahiro Yamada } 1610a9064fbSMasahiro Yamada if (def && sym_set_string_value(sym, def)) 1620a9064fbSMasahiro Yamada return 0; 1630a9064fbSMasahiro Yamada } 1640a9064fbSMasahiro Yamada } 1650a9064fbSMasahiro Yamada 1660a9064fbSMasahiro Yamada static int conf_sym(struct menu *menu) 1670a9064fbSMasahiro Yamada { 1680a9064fbSMasahiro Yamada struct symbol *sym = menu->sym; 1690a9064fbSMasahiro Yamada tristate oldval, newval; 1700a9064fbSMasahiro Yamada 1710a9064fbSMasahiro Yamada while (1) { 1720a9064fbSMasahiro Yamada printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); 1730a9064fbSMasahiro Yamada if (sym->name) 1740a9064fbSMasahiro Yamada printf("(%s) ", sym->name); 1750a9064fbSMasahiro Yamada putchar('['); 1760a9064fbSMasahiro Yamada oldval = sym_get_tristate_value(sym); 1770a9064fbSMasahiro Yamada switch (oldval) { 1780a9064fbSMasahiro Yamada case no: 1790a9064fbSMasahiro Yamada putchar('N'); 1800a9064fbSMasahiro Yamada break; 1810a9064fbSMasahiro Yamada case mod: 1820a9064fbSMasahiro Yamada putchar('M'); 1830a9064fbSMasahiro Yamada break; 1840a9064fbSMasahiro Yamada case yes: 1850a9064fbSMasahiro Yamada putchar('Y'); 1860a9064fbSMasahiro Yamada break; 1870a9064fbSMasahiro Yamada } 1880a9064fbSMasahiro Yamada if (oldval != no && sym_tristate_within_range(sym, no)) 1890a9064fbSMasahiro Yamada printf("/n"); 1900a9064fbSMasahiro Yamada if (oldval != mod && sym_tristate_within_range(sym, mod)) 1910a9064fbSMasahiro Yamada printf("/m"); 1920a9064fbSMasahiro Yamada if (oldval != yes && sym_tristate_within_range(sym, yes)) 1930a9064fbSMasahiro Yamada printf("/y"); 1940a9064fbSMasahiro Yamada if (menu_has_help(menu)) 1950a9064fbSMasahiro Yamada printf("/?"); 1960a9064fbSMasahiro Yamada printf("] "); 1970a9064fbSMasahiro Yamada if (!conf_askvalue(sym, sym_get_string_value(sym))) 1980a9064fbSMasahiro Yamada return 0; 1990a9064fbSMasahiro Yamada strip(line); 2000a9064fbSMasahiro Yamada 2010a9064fbSMasahiro Yamada switch (line[0]) { 2020a9064fbSMasahiro Yamada case 'n': 2030a9064fbSMasahiro Yamada case 'N': 2040a9064fbSMasahiro Yamada newval = no; 2050a9064fbSMasahiro Yamada if (!line[1] || !strcmp(&line[1], "o")) 2060a9064fbSMasahiro Yamada break; 2070a9064fbSMasahiro Yamada continue; 2080a9064fbSMasahiro Yamada case 'm': 2090a9064fbSMasahiro Yamada case 'M': 2100a9064fbSMasahiro Yamada newval = mod; 2110a9064fbSMasahiro Yamada if (!line[1]) 2120a9064fbSMasahiro Yamada break; 2130a9064fbSMasahiro Yamada continue; 2140a9064fbSMasahiro Yamada case 'y': 2150a9064fbSMasahiro Yamada case 'Y': 2160a9064fbSMasahiro Yamada newval = yes; 2170a9064fbSMasahiro Yamada if (!line[1] || !strcmp(&line[1], "es")) 2180a9064fbSMasahiro Yamada break; 2190a9064fbSMasahiro Yamada continue; 2200a9064fbSMasahiro Yamada case 0: 2210a9064fbSMasahiro Yamada newval = oldval; 2220a9064fbSMasahiro Yamada break; 2230a9064fbSMasahiro Yamada case '?': 2240a9064fbSMasahiro Yamada goto help; 2250a9064fbSMasahiro Yamada default: 2260a9064fbSMasahiro Yamada continue; 2270a9064fbSMasahiro Yamada } 2280a9064fbSMasahiro Yamada if (sym_set_tristate_value(sym, newval)) 2290a9064fbSMasahiro Yamada return 0; 2300a9064fbSMasahiro Yamada help: 2310a9064fbSMasahiro Yamada print_help(menu); 2320a9064fbSMasahiro Yamada } 2330a9064fbSMasahiro Yamada } 2340a9064fbSMasahiro Yamada 2350a9064fbSMasahiro Yamada static int conf_choice(struct menu *menu) 2360a9064fbSMasahiro Yamada { 2370a9064fbSMasahiro Yamada struct symbol *sym, *def_sym; 2380a9064fbSMasahiro Yamada struct menu *child; 2390a9064fbSMasahiro Yamada bool is_new; 2400a9064fbSMasahiro Yamada 2410a9064fbSMasahiro Yamada sym = menu->sym; 2420a9064fbSMasahiro Yamada is_new = !sym_has_value(sym); 2430a9064fbSMasahiro Yamada if (sym_is_changable(sym)) { 2440a9064fbSMasahiro Yamada conf_sym(menu); 2450a9064fbSMasahiro Yamada sym_calc_value(sym); 2460a9064fbSMasahiro Yamada switch (sym_get_tristate_value(sym)) { 2470a9064fbSMasahiro Yamada case no: 2480a9064fbSMasahiro Yamada return 1; 2490a9064fbSMasahiro Yamada case mod: 2500a9064fbSMasahiro Yamada return 0; 2510a9064fbSMasahiro Yamada case yes: 2520a9064fbSMasahiro Yamada break; 2530a9064fbSMasahiro Yamada } 2540a9064fbSMasahiro Yamada } else { 2550a9064fbSMasahiro Yamada switch (sym_get_tristate_value(sym)) { 2560a9064fbSMasahiro Yamada case no: 2570a9064fbSMasahiro Yamada return 1; 2580a9064fbSMasahiro Yamada case mod: 2590a9064fbSMasahiro Yamada printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 2600a9064fbSMasahiro Yamada return 0; 2610a9064fbSMasahiro Yamada case yes: 2620a9064fbSMasahiro Yamada break; 2630a9064fbSMasahiro Yamada } 2640a9064fbSMasahiro Yamada } 2650a9064fbSMasahiro Yamada 2660a9064fbSMasahiro Yamada while (1) { 2670a9064fbSMasahiro Yamada int cnt, def; 2680a9064fbSMasahiro Yamada 2690a9064fbSMasahiro Yamada printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); 2700a9064fbSMasahiro Yamada def_sym = sym_get_choice_value(sym); 2710a9064fbSMasahiro Yamada cnt = def = 0; 2720a9064fbSMasahiro Yamada line[0] = 0; 2730a9064fbSMasahiro Yamada for (child = menu->list; child; child = child->next) { 2740a9064fbSMasahiro Yamada if (!menu_is_visible(child)) 2750a9064fbSMasahiro Yamada continue; 2760a9064fbSMasahiro Yamada if (!child->sym) { 2770a9064fbSMasahiro Yamada printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); 2780a9064fbSMasahiro Yamada continue; 2790a9064fbSMasahiro Yamada } 2800a9064fbSMasahiro Yamada cnt++; 2810a9064fbSMasahiro Yamada if (child->sym == def_sym) { 2820a9064fbSMasahiro Yamada def = cnt; 2830a9064fbSMasahiro Yamada printf("%*c", indent, '>'); 2840a9064fbSMasahiro Yamada } else 2850a9064fbSMasahiro Yamada printf("%*c", indent, ' '); 2860a9064fbSMasahiro Yamada printf(" %d. %s", cnt, _(menu_get_prompt(child))); 2870a9064fbSMasahiro Yamada if (child->sym->name) 2880a9064fbSMasahiro Yamada printf(" (%s)", child->sym->name); 2890a9064fbSMasahiro Yamada if (!sym_has_value(child->sym)) 2900a9064fbSMasahiro Yamada printf(_(" (NEW)")); 2910a9064fbSMasahiro Yamada printf("\n"); 2920a9064fbSMasahiro Yamada } 2930a9064fbSMasahiro Yamada printf(_("%*schoice"), indent - 1, ""); 2940a9064fbSMasahiro Yamada if (cnt == 1) { 2950a9064fbSMasahiro Yamada printf("[1]: 1\n"); 2960a9064fbSMasahiro Yamada goto conf_childs; 2970a9064fbSMasahiro Yamada } 2980a9064fbSMasahiro Yamada printf("[1-%d", cnt); 2990a9064fbSMasahiro Yamada if (menu_has_help(menu)) 3000a9064fbSMasahiro Yamada printf("?"); 3010a9064fbSMasahiro Yamada printf("]: "); 3020a9064fbSMasahiro Yamada switch (input_mode) { 3030a9064fbSMasahiro Yamada case oldconfig: 3040a9064fbSMasahiro Yamada case silentoldconfig: 3050a9064fbSMasahiro Yamada if (!is_new) { 3060a9064fbSMasahiro Yamada cnt = def; 3070a9064fbSMasahiro Yamada printf("%d\n", cnt); 3080a9064fbSMasahiro Yamada break; 3090a9064fbSMasahiro Yamada } 3100a9064fbSMasahiro Yamada check_stdin(); 3110a9064fbSMasahiro Yamada /* fall through */ 3120a9064fbSMasahiro Yamada case oldaskconfig: 3130a9064fbSMasahiro Yamada fflush(stdout); 3140a9064fbSMasahiro Yamada xfgets(line, 128, stdin); 3150a9064fbSMasahiro Yamada strip(line); 3160a9064fbSMasahiro Yamada if (line[0] == '?') { 3170a9064fbSMasahiro Yamada print_help(menu); 3180a9064fbSMasahiro Yamada continue; 3190a9064fbSMasahiro Yamada } 3200a9064fbSMasahiro Yamada if (!line[0]) 3210a9064fbSMasahiro Yamada cnt = def; 3220a9064fbSMasahiro Yamada else if (isdigit(line[0])) 3230a9064fbSMasahiro Yamada cnt = atoi(line); 3240a9064fbSMasahiro Yamada else 3250a9064fbSMasahiro Yamada continue; 3260a9064fbSMasahiro Yamada break; 3270a9064fbSMasahiro Yamada default: 3280a9064fbSMasahiro Yamada break; 3290a9064fbSMasahiro Yamada } 3300a9064fbSMasahiro Yamada 3310a9064fbSMasahiro Yamada conf_childs: 3320a9064fbSMasahiro Yamada for (child = menu->list; child; child = child->next) { 3330a9064fbSMasahiro Yamada if (!child->sym || !menu_is_visible(child)) 3340a9064fbSMasahiro Yamada continue; 3350a9064fbSMasahiro Yamada if (!--cnt) 3360a9064fbSMasahiro Yamada break; 3370a9064fbSMasahiro Yamada } 3380a9064fbSMasahiro Yamada if (!child) 3390a9064fbSMasahiro Yamada continue; 3400a9064fbSMasahiro Yamada if (line[0] && line[strlen(line) - 1] == '?') { 3410a9064fbSMasahiro Yamada print_help(child); 3420a9064fbSMasahiro Yamada continue; 3430a9064fbSMasahiro Yamada } 3440a9064fbSMasahiro Yamada sym_set_choice_value(sym, child->sym); 3450a9064fbSMasahiro Yamada for (child = child->list; child; child = child->next) { 3460a9064fbSMasahiro Yamada indent += 2; 3470a9064fbSMasahiro Yamada conf(child); 3480a9064fbSMasahiro Yamada indent -= 2; 3490a9064fbSMasahiro Yamada } 3500a9064fbSMasahiro Yamada return 1; 3510a9064fbSMasahiro Yamada } 3520a9064fbSMasahiro Yamada } 3530a9064fbSMasahiro Yamada 3540a9064fbSMasahiro Yamada static void conf(struct menu *menu) 3550a9064fbSMasahiro Yamada { 3560a9064fbSMasahiro Yamada struct symbol *sym; 3570a9064fbSMasahiro Yamada struct property *prop; 3580a9064fbSMasahiro Yamada struct menu *child; 3590a9064fbSMasahiro Yamada 3600a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 3610a9064fbSMasahiro Yamada return; 3620a9064fbSMasahiro Yamada 3630a9064fbSMasahiro Yamada sym = menu->sym; 3640a9064fbSMasahiro Yamada prop = menu->prompt; 3650a9064fbSMasahiro Yamada if (prop) { 3660a9064fbSMasahiro Yamada const char *prompt; 3670a9064fbSMasahiro Yamada 3680a9064fbSMasahiro Yamada switch (prop->type) { 3690a9064fbSMasahiro Yamada case P_MENU: 3700a9064fbSMasahiro Yamada if ((input_mode == silentoldconfig || 3710a9064fbSMasahiro Yamada input_mode == listnewconfig || 3720a9064fbSMasahiro Yamada input_mode == olddefconfig) && 3730a9064fbSMasahiro Yamada rootEntry != menu) { 3740a9064fbSMasahiro Yamada check_conf(menu); 3750a9064fbSMasahiro Yamada return; 3760a9064fbSMasahiro Yamada } 3770a9064fbSMasahiro Yamada /* fall through */ 3780a9064fbSMasahiro Yamada case P_COMMENT: 3790a9064fbSMasahiro Yamada prompt = menu_get_prompt(menu); 3800a9064fbSMasahiro Yamada if (prompt) 3810a9064fbSMasahiro Yamada printf("%*c\n%*c %s\n%*c\n", 3820a9064fbSMasahiro Yamada indent, '*', 3830a9064fbSMasahiro Yamada indent, '*', _(prompt), 3840a9064fbSMasahiro Yamada indent, '*'); 3850a9064fbSMasahiro Yamada default: 3860a9064fbSMasahiro Yamada ; 3870a9064fbSMasahiro Yamada } 3880a9064fbSMasahiro Yamada } 3890a9064fbSMasahiro Yamada 3900a9064fbSMasahiro Yamada if (!sym) 3910a9064fbSMasahiro Yamada goto conf_childs; 3920a9064fbSMasahiro Yamada 3930a9064fbSMasahiro Yamada if (sym_is_choice(sym)) { 3940a9064fbSMasahiro Yamada conf_choice(menu); 3950a9064fbSMasahiro Yamada if (sym->curr.tri != mod) 3960a9064fbSMasahiro Yamada return; 3970a9064fbSMasahiro Yamada goto conf_childs; 3980a9064fbSMasahiro Yamada } 3990a9064fbSMasahiro Yamada 4000a9064fbSMasahiro Yamada switch (sym->type) { 4010a9064fbSMasahiro Yamada case S_INT: 4020a9064fbSMasahiro Yamada case S_HEX: 4030a9064fbSMasahiro Yamada case S_STRING: 4040a9064fbSMasahiro Yamada conf_string(menu); 4050a9064fbSMasahiro Yamada break; 4060a9064fbSMasahiro Yamada default: 4070a9064fbSMasahiro Yamada conf_sym(menu); 4080a9064fbSMasahiro Yamada break; 4090a9064fbSMasahiro Yamada } 4100a9064fbSMasahiro Yamada 4110a9064fbSMasahiro Yamada conf_childs: 4120a9064fbSMasahiro Yamada if (sym) 4130a9064fbSMasahiro Yamada indent += 2; 4140a9064fbSMasahiro Yamada for (child = menu->list; child; child = child->next) 4150a9064fbSMasahiro Yamada conf(child); 4160a9064fbSMasahiro Yamada if (sym) 4170a9064fbSMasahiro Yamada indent -= 2; 4180a9064fbSMasahiro Yamada } 4190a9064fbSMasahiro Yamada 4200a9064fbSMasahiro Yamada static void check_conf(struct menu *menu) 4210a9064fbSMasahiro Yamada { 4220a9064fbSMasahiro Yamada struct symbol *sym; 4230a9064fbSMasahiro Yamada struct menu *child; 4240a9064fbSMasahiro Yamada 4250a9064fbSMasahiro Yamada if (!menu_is_visible(menu)) 4260a9064fbSMasahiro Yamada return; 4270a9064fbSMasahiro Yamada 4280a9064fbSMasahiro Yamada sym = menu->sym; 4290a9064fbSMasahiro Yamada if (sym && !sym_has_value(sym)) { 4300a9064fbSMasahiro Yamada if (sym_is_changable(sym) || 4310a9064fbSMasahiro Yamada (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { 4320a9064fbSMasahiro Yamada if (input_mode == listnewconfig) { 4330a9064fbSMasahiro Yamada if (sym->name && !sym_is_choice_value(sym)) { 4340a9064fbSMasahiro Yamada printf("%s%s\n", CONFIG_, sym->name); 4350a9064fbSMasahiro Yamada } 4360a9064fbSMasahiro Yamada } else if (input_mode != olddefconfig) { 4370a9064fbSMasahiro Yamada if (!conf_cnt++) 4380a9064fbSMasahiro Yamada printf(_("*\n* Restart config...\n*\n")); 4390a9064fbSMasahiro Yamada rootEntry = menu_get_parent_menu(menu); 4400a9064fbSMasahiro Yamada conf(rootEntry); 4410a9064fbSMasahiro Yamada } 4420a9064fbSMasahiro Yamada } 4430a9064fbSMasahiro Yamada } 4440a9064fbSMasahiro Yamada 4450a9064fbSMasahiro Yamada for (child = menu->list; child; child = child->next) 4460a9064fbSMasahiro Yamada check_conf(child); 4470a9064fbSMasahiro Yamada } 4480a9064fbSMasahiro Yamada 4490a9064fbSMasahiro Yamada static struct option long_opts[] = { 4500a9064fbSMasahiro Yamada {"oldaskconfig", no_argument, NULL, oldaskconfig}, 4510a9064fbSMasahiro Yamada {"oldconfig", no_argument, NULL, oldconfig}, 4520a9064fbSMasahiro Yamada {"silentoldconfig", no_argument, NULL, silentoldconfig}, 4530a9064fbSMasahiro Yamada {"defconfig", optional_argument, NULL, defconfig}, 4540a9064fbSMasahiro Yamada {"savedefconfig", required_argument, NULL, savedefconfig}, 4550a9064fbSMasahiro Yamada {"allnoconfig", no_argument, NULL, allnoconfig}, 4560a9064fbSMasahiro Yamada {"allyesconfig", no_argument, NULL, allyesconfig}, 4570a9064fbSMasahiro Yamada {"allmodconfig", no_argument, NULL, allmodconfig}, 4580a9064fbSMasahiro Yamada {"alldefconfig", no_argument, NULL, alldefconfig}, 4590a9064fbSMasahiro Yamada {"randconfig", no_argument, NULL, randconfig}, 4600a9064fbSMasahiro Yamada {"listnewconfig", no_argument, NULL, listnewconfig}, 4610a9064fbSMasahiro Yamada {"olddefconfig", no_argument, NULL, olddefconfig}, 4620a9064fbSMasahiro Yamada /* 4630a9064fbSMasahiro Yamada * oldnoconfig is an alias of olddefconfig, because people already 4640a9064fbSMasahiro Yamada * are dependent on its behavior(sets new symbols to their default 4650a9064fbSMasahiro Yamada * value but not 'n') with the counter-intuitive name. 4660a9064fbSMasahiro Yamada */ 4670a9064fbSMasahiro Yamada {"oldnoconfig", no_argument, NULL, olddefconfig}, 4680a9064fbSMasahiro Yamada {NULL, 0, NULL, 0} 4690a9064fbSMasahiro Yamada }; 4700a9064fbSMasahiro Yamada 4710a9064fbSMasahiro Yamada static void conf_usage(const char *progname) 4720a9064fbSMasahiro Yamada { 4730a9064fbSMasahiro Yamada 474*9b5f0b1dSMasahiro Yamada printf("Usage: %s [-s] [option] <kconfig-file>\n", progname); 4750a9064fbSMasahiro Yamada printf("[option] is _one_ of the following:\n"); 4760a9064fbSMasahiro Yamada printf(" --listnewconfig List new options\n"); 4770a9064fbSMasahiro Yamada printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); 4780a9064fbSMasahiro Yamada printf(" --oldconfig Update a configuration using a provided .config as base\n"); 4790a9064fbSMasahiro Yamada printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); 4800a9064fbSMasahiro Yamada printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n"); 4810a9064fbSMasahiro Yamada printf(" --oldnoconfig An alias of olddefconfig\n"); 4820a9064fbSMasahiro Yamada printf(" --defconfig <file> New config with default defined in <file>\n"); 4830a9064fbSMasahiro Yamada printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); 4840a9064fbSMasahiro Yamada printf(" --allnoconfig New config where all options are answered with no\n"); 4850a9064fbSMasahiro Yamada printf(" --allyesconfig New config where all options are answered with yes\n"); 4860a9064fbSMasahiro Yamada printf(" --allmodconfig New config where all options are answered with mod\n"); 4870a9064fbSMasahiro Yamada printf(" --alldefconfig New config with all symbols set to default\n"); 4880a9064fbSMasahiro Yamada printf(" --randconfig New config with random answer to all options\n"); 4890a9064fbSMasahiro Yamada } 4900a9064fbSMasahiro Yamada 4910a9064fbSMasahiro Yamada int main(int ac, char **av) 4920a9064fbSMasahiro Yamada { 4930a9064fbSMasahiro Yamada const char *progname = av[0]; 4940a9064fbSMasahiro Yamada int opt; 4950a9064fbSMasahiro Yamada const char *name, *defconfig_file = NULL /* gcc uninit */; 4960a9064fbSMasahiro Yamada struct stat tmpstat; 4970a9064fbSMasahiro Yamada 4980a9064fbSMasahiro Yamada setlocale(LC_ALL, ""); 4990a9064fbSMasahiro Yamada bindtextdomain(PACKAGE, LOCALEDIR); 5000a9064fbSMasahiro Yamada textdomain(PACKAGE); 5010a9064fbSMasahiro Yamada 5020a9064fbSMasahiro Yamada tty_stdio = isatty(0) && isatty(1) && isatty(2); 5030a9064fbSMasahiro Yamada 504*9b5f0b1dSMasahiro Yamada while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) { 505*9b5f0b1dSMasahiro Yamada if (opt == 's') { 506*9b5f0b1dSMasahiro Yamada conf_set_message_callback(NULL); 507*9b5f0b1dSMasahiro Yamada continue; 508*9b5f0b1dSMasahiro Yamada } 5090a9064fbSMasahiro Yamada input_mode = (enum input_mode)opt; 5100a9064fbSMasahiro Yamada switch (opt) { 5110a9064fbSMasahiro Yamada case silentoldconfig: 5120a9064fbSMasahiro Yamada sync_kconfig = 1; 5130a9064fbSMasahiro Yamada break; 5140a9064fbSMasahiro Yamada case defconfig: 5150a9064fbSMasahiro Yamada case savedefconfig: 5160a9064fbSMasahiro Yamada defconfig_file = optarg; 5170a9064fbSMasahiro Yamada break; 5180a9064fbSMasahiro Yamada case randconfig: 5190a9064fbSMasahiro Yamada { 5200a9064fbSMasahiro Yamada struct timeval now; 5210a9064fbSMasahiro Yamada unsigned int seed; 5220a9064fbSMasahiro Yamada char *seed_env; 5230a9064fbSMasahiro Yamada 5240a9064fbSMasahiro Yamada /* 5250a9064fbSMasahiro Yamada * Use microseconds derived seed, 5260a9064fbSMasahiro Yamada * compensate for systems where it may be zero 5270a9064fbSMasahiro Yamada */ 5280a9064fbSMasahiro Yamada gettimeofday(&now, NULL); 5290a9064fbSMasahiro Yamada seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); 5300a9064fbSMasahiro Yamada 5310a9064fbSMasahiro Yamada seed_env = getenv("KCONFIG_SEED"); 5320a9064fbSMasahiro Yamada if( seed_env && *seed_env ) { 5330a9064fbSMasahiro Yamada char *endp; 5340a9064fbSMasahiro Yamada int tmp = (int)strtol(seed_env, &endp, 0); 5350a9064fbSMasahiro Yamada if (*endp == '\0') { 5360a9064fbSMasahiro Yamada seed = tmp; 5370a9064fbSMasahiro Yamada } 5380a9064fbSMasahiro Yamada } 5390a9064fbSMasahiro Yamada fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed ); 5400a9064fbSMasahiro Yamada srand(seed); 5410a9064fbSMasahiro Yamada break; 5420a9064fbSMasahiro Yamada } 5430a9064fbSMasahiro Yamada case oldaskconfig: 5440a9064fbSMasahiro Yamada case oldconfig: 5450a9064fbSMasahiro Yamada case allnoconfig: 5460a9064fbSMasahiro Yamada case allyesconfig: 5470a9064fbSMasahiro Yamada case allmodconfig: 5480a9064fbSMasahiro Yamada case alldefconfig: 5490a9064fbSMasahiro Yamada case listnewconfig: 5500a9064fbSMasahiro Yamada case olddefconfig: 5510a9064fbSMasahiro Yamada break; 5520a9064fbSMasahiro Yamada case '?': 5530a9064fbSMasahiro Yamada conf_usage(progname); 5540a9064fbSMasahiro Yamada exit(1); 5550a9064fbSMasahiro Yamada break; 5560a9064fbSMasahiro Yamada } 5570a9064fbSMasahiro Yamada } 5580a9064fbSMasahiro Yamada if (ac == optind) { 5590a9064fbSMasahiro Yamada printf(_("%s: Kconfig file missing\n"), av[0]); 5600a9064fbSMasahiro Yamada conf_usage(progname); 5610a9064fbSMasahiro Yamada exit(1); 5620a9064fbSMasahiro Yamada } 5630a9064fbSMasahiro Yamada name = av[optind]; 5640a9064fbSMasahiro Yamada conf_parse(name); 5650a9064fbSMasahiro Yamada //zconfdump(stdout); 5660a9064fbSMasahiro Yamada if (sync_kconfig) { 5670a9064fbSMasahiro Yamada name = conf_get_configname(); 5680a9064fbSMasahiro Yamada if (stat(name, &tmpstat)) { 5690a9064fbSMasahiro Yamada fprintf(stderr, _("***\n" 5700a9064fbSMasahiro Yamada "*** Configuration file \"%s\" not found!\n" 5710a9064fbSMasahiro Yamada "***\n" 5720a9064fbSMasahiro Yamada "*** Please run some configurator (e.g. \"make oldconfig\" or\n" 5730a9064fbSMasahiro Yamada "*** \"make menuconfig\" or \"make xconfig\").\n" 5740a9064fbSMasahiro Yamada "***\n"), name); 5750a9064fbSMasahiro Yamada exit(1); 5760a9064fbSMasahiro Yamada } 5770a9064fbSMasahiro Yamada } 5780a9064fbSMasahiro Yamada 5790a9064fbSMasahiro Yamada switch (input_mode) { 5800a9064fbSMasahiro Yamada case defconfig: 5810a9064fbSMasahiro Yamada if (!defconfig_file) 5820a9064fbSMasahiro Yamada defconfig_file = conf_get_default_confname(); 5830a9064fbSMasahiro Yamada if (conf_read(defconfig_file)) { 5840a9064fbSMasahiro Yamada printf(_("***\n" 5850a9064fbSMasahiro Yamada "*** Can't find default configuration \"%s\"!\n" 5860a9064fbSMasahiro Yamada "***\n"), defconfig_file); 5870a9064fbSMasahiro Yamada exit(1); 5880a9064fbSMasahiro Yamada } 5890a9064fbSMasahiro Yamada break; 5900a9064fbSMasahiro Yamada case savedefconfig: 5910a9064fbSMasahiro Yamada case silentoldconfig: 5920a9064fbSMasahiro Yamada case oldaskconfig: 5930a9064fbSMasahiro Yamada case oldconfig: 5940a9064fbSMasahiro Yamada case listnewconfig: 5950a9064fbSMasahiro Yamada case olddefconfig: 5960a9064fbSMasahiro Yamada conf_read(NULL); 5970a9064fbSMasahiro Yamada break; 5980a9064fbSMasahiro Yamada case allnoconfig: 5990a9064fbSMasahiro Yamada case allyesconfig: 6000a9064fbSMasahiro Yamada case allmodconfig: 6010a9064fbSMasahiro Yamada case alldefconfig: 6020a9064fbSMasahiro Yamada case randconfig: 6030a9064fbSMasahiro Yamada name = getenv("KCONFIG_ALLCONFIG"); 6040a9064fbSMasahiro Yamada if (!name) 6050a9064fbSMasahiro Yamada break; 6060a9064fbSMasahiro Yamada if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { 6070a9064fbSMasahiro Yamada if (conf_read_simple(name, S_DEF_USER)) { 6080a9064fbSMasahiro Yamada fprintf(stderr, 6090a9064fbSMasahiro Yamada _("*** Can't read seed configuration \"%s\"!\n"), 6100a9064fbSMasahiro Yamada name); 6110a9064fbSMasahiro Yamada exit(1); 6120a9064fbSMasahiro Yamada } 6130a9064fbSMasahiro Yamada break; 6140a9064fbSMasahiro Yamada } 6150a9064fbSMasahiro Yamada switch (input_mode) { 6160a9064fbSMasahiro Yamada case allnoconfig: name = "allno.config"; break; 6170a9064fbSMasahiro Yamada case allyesconfig: name = "allyes.config"; break; 6180a9064fbSMasahiro Yamada case allmodconfig: name = "allmod.config"; break; 6190a9064fbSMasahiro Yamada case alldefconfig: name = "alldef.config"; break; 6200a9064fbSMasahiro Yamada case randconfig: name = "allrandom.config"; break; 6210a9064fbSMasahiro Yamada default: break; 6220a9064fbSMasahiro Yamada } 6230a9064fbSMasahiro Yamada if (conf_read_simple(name, S_DEF_USER) && 6240a9064fbSMasahiro Yamada conf_read_simple("all.config", S_DEF_USER)) { 6250a9064fbSMasahiro Yamada fprintf(stderr, 6260a9064fbSMasahiro Yamada _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), 6270a9064fbSMasahiro Yamada name); 6280a9064fbSMasahiro Yamada exit(1); 6290a9064fbSMasahiro Yamada } 6300a9064fbSMasahiro Yamada break; 6310a9064fbSMasahiro Yamada default: 6320a9064fbSMasahiro Yamada break; 6330a9064fbSMasahiro Yamada } 6340a9064fbSMasahiro Yamada 6350a9064fbSMasahiro Yamada if (sync_kconfig) { 6360a9064fbSMasahiro Yamada if (conf_get_changed()) { 6370a9064fbSMasahiro Yamada name = getenv("KCONFIG_NOSILENTUPDATE"); 6380a9064fbSMasahiro Yamada if (name && *name) { 6390a9064fbSMasahiro Yamada fprintf(stderr, 6400a9064fbSMasahiro Yamada _("\n*** The configuration requires explicit update.\n\n")); 6410a9064fbSMasahiro Yamada return 1; 6420a9064fbSMasahiro Yamada } 6430a9064fbSMasahiro Yamada } 6440a9064fbSMasahiro Yamada valid_stdin = tty_stdio; 6450a9064fbSMasahiro Yamada } 6460a9064fbSMasahiro Yamada 6470a9064fbSMasahiro Yamada switch (input_mode) { 6480a9064fbSMasahiro Yamada case allnoconfig: 6490a9064fbSMasahiro Yamada conf_set_all_new_symbols(def_no); 6500a9064fbSMasahiro Yamada break; 6510a9064fbSMasahiro Yamada case allyesconfig: 6520a9064fbSMasahiro Yamada conf_set_all_new_symbols(def_yes); 6530a9064fbSMasahiro Yamada break; 6540a9064fbSMasahiro Yamada case allmodconfig: 6550a9064fbSMasahiro Yamada conf_set_all_new_symbols(def_mod); 6560a9064fbSMasahiro Yamada break; 6570a9064fbSMasahiro Yamada case alldefconfig: 6580a9064fbSMasahiro Yamada conf_set_all_new_symbols(def_default); 6590a9064fbSMasahiro Yamada break; 6600a9064fbSMasahiro Yamada case randconfig: 6610a9064fbSMasahiro Yamada /* Really nothing to do in this loop */ 6620a9064fbSMasahiro Yamada while (conf_set_all_new_symbols(def_random)) ; 6630a9064fbSMasahiro Yamada break; 6640a9064fbSMasahiro Yamada case defconfig: 6650a9064fbSMasahiro Yamada conf_set_all_new_symbols(def_default); 6660a9064fbSMasahiro Yamada break; 6670a9064fbSMasahiro Yamada case savedefconfig: 6680a9064fbSMasahiro Yamada break; 6690a9064fbSMasahiro Yamada case oldaskconfig: 6700a9064fbSMasahiro Yamada rootEntry = &rootmenu; 6710a9064fbSMasahiro Yamada conf(&rootmenu); 6720a9064fbSMasahiro Yamada input_mode = silentoldconfig; 6730a9064fbSMasahiro Yamada /* fall through */ 6740a9064fbSMasahiro Yamada case oldconfig: 6750a9064fbSMasahiro Yamada case listnewconfig: 6760a9064fbSMasahiro Yamada case olddefconfig: 6770a9064fbSMasahiro Yamada case silentoldconfig: 6780a9064fbSMasahiro Yamada /* Update until a loop caused no more changes */ 6790a9064fbSMasahiro Yamada do { 6800a9064fbSMasahiro Yamada conf_cnt = 0; 6810a9064fbSMasahiro Yamada check_conf(&rootmenu); 6820a9064fbSMasahiro Yamada } while (conf_cnt && 6830a9064fbSMasahiro Yamada (input_mode != listnewconfig && 6840a9064fbSMasahiro Yamada input_mode != olddefconfig)); 6850a9064fbSMasahiro Yamada break; 6860a9064fbSMasahiro Yamada } 6870a9064fbSMasahiro Yamada 6880a9064fbSMasahiro Yamada if (sync_kconfig) { 6890a9064fbSMasahiro Yamada /* silentoldconfig is used during the build so we shall update autoconf. 6900a9064fbSMasahiro Yamada * All other commands are only used to generate a config. 6910a9064fbSMasahiro Yamada */ 6920a9064fbSMasahiro Yamada if (conf_get_changed() && conf_write(NULL)) { 6930a9064fbSMasahiro Yamada fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 6940a9064fbSMasahiro Yamada exit(1); 6950a9064fbSMasahiro Yamada } 6960a9064fbSMasahiro Yamada if (conf_write_autoconf()) { 6970a9064fbSMasahiro Yamada fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); 6980a9064fbSMasahiro Yamada return 1; 6990a9064fbSMasahiro Yamada } 7000a9064fbSMasahiro Yamada } else if (input_mode == savedefconfig) { 7010a9064fbSMasahiro Yamada if (conf_write_defconfig(defconfig_file)) { 7020a9064fbSMasahiro Yamada fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), 7030a9064fbSMasahiro Yamada defconfig_file); 7040a9064fbSMasahiro Yamada return 1; 7050a9064fbSMasahiro Yamada } 7060a9064fbSMasahiro Yamada } else if (input_mode != listnewconfig) { 7070a9064fbSMasahiro Yamada if (conf_write(NULL)) { 7080a9064fbSMasahiro Yamada fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); 7090a9064fbSMasahiro Yamada exit(1); 7100a9064fbSMasahiro Yamada } 7110a9064fbSMasahiro Yamada } 7120a9064fbSMasahiro Yamada return 0; 7130a9064fbSMasahiro Yamada } 7140a9064fbSMasahiro Yamada 7150a9064fbSMasahiro Yamada /* 7160a9064fbSMasahiro Yamada * Helper function to facilitate fgets() by Jean Sacren. 7170a9064fbSMasahiro Yamada */ 7180a9064fbSMasahiro Yamada void xfgets(char *str, int size, FILE *in) 7190a9064fbSMasahiro Yamada { 7200a9064fbSMasahiro Yamada if (fgets(str, size, in) == NULL) 7210a9064fbSMasahiro Yamada fprintf(stderr, "\nError in reading or end of file.\n"); 7220a9064fbSMasahiro Yamada } 723