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