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