inotify: fix race
[linux-2.6.22.y-op.git] / scripts / kconfig / conf.c
blob45550d2b6ef54024be58e6bb85c9fa15c13e6197
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <time.h>
12 #include <sys/stat.h>
14 #define LKC_DIRECT_LINK
15 #include "lkc.h"
17 static void conf(struct menu *menu);
18 static void check_conf(struct menu *menu);
20 enum {
21 ask_all,
22 ask_new,
23 ask_silent,
24 set_default,
25 set_yes,
26 set_mod,
27 set_no,
28 set_random
29 } input_mode = ask_all;
30 char *defconfig_file;
32 static int indent = 1;
33 static int valid_stdin = 1;
34 static int conf_cnt;
35 static char line[128];
36 static struct menu *rootEntry;
38 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
40 static void strip(char *str)
42 char *p = str;
43 int l;
45 while ((isspace(*p)))
46 p++;
47 l = strlen(p);
48 if (p != str)
49 memmove(str, p, l + 1);
50 if (!l)
51 return;
52 p = str + l - 1;
53 while ((isspace(*p)))
54 *p-- = 0;
57 static void check_stdin(void)
59 if (!valid_stdin && input_mode == ask_silent) {
60 printf(_("aborted!\n\n"));
61 printf(_("Console input/output is redirected. "));
62 printf(_("Run 'make oldconfig' to update configuration.\n\n"));
63 exit(1);
67 static int conf_askvalue(struct symbol *sym, const char *def)
69 enum symbol_type type = sym_get_type(sym);
70 tristate val;
72 if (!sym_has_value(sym))
73 printf("(NEW) ");
75 line[0] = '\n';
76 line[1] = 0;
78 if (!sym_is_changable(sym)) {
79 printf("%s\n", def);
80 line[0] = '\n';
81 line[1] = 0;
82 return 0;
85 switch (input_mode) {
86 case set_no:
87 case set_mod:
88 case set_yes:
89 case set_random:
90 if (sym_has_value(sym)) {
91 printf("%s\n", def);
92 return 0;
94 break;
95 case ask_new:
96 case ask_silent:
97 if (sym_has_value(sym)) {
98 printf("%s\n", def);
99 return 0;
101 check_stdin();
102 case ask_all:
103 fflush(stdout);
104 fgets(line, 128, stdin);
105 return 1;
106 case set_default:
107 printf("%s\n", def);
108 return 1;
109 default:
110 break;
113 switch (type) {
114 case S_INT:
115 case S_HEX:
116 case S_STRING:
117 printf("%s\n", def);
118 return 1;
119 default:
122 switch (input_mode) {
123 case set_yes:
124 if (sym_tristate_within_range(sym, yes)) {
125 line[0] = 'y';
126 line[1] = '\n';
127 line[2] = 0;
128 break;
130 case set_mod:
131 if (type == S_TRISTATE) {
132 if (sym_tristate_within_range(sym, mod)) {
133 line[0] = 'm';
134 line[1] = '\n';
135 line[2] = 0;
136 break;
138 } else {
139 if (sym_tristate_within_range(sym, yes)) {
140 line[0] = 'y';
141 line[1] = '\n';
142 line[2] = 0;
143 break;
146 case set_no:
147 if (sym_tristate_within_range(sym, no)) {
148 line[0] = 'n';
149 line[1] = '\n';
150 line[2] = 0;
151 break;
153 case set_random:
154 do {
155 val = (tristate)(random() % 3);
156 } while (!sym_tristate_within_range(sym, val));
157 switch (val) {
158 case no: line[0] = 'n'; break;
159 case mod: line[0] = 'm'; break;
160 case yes: line[0] = 'y'; break;
162 line[1] = '\n';
163 line[2] = 0;
164 break;
165 default:
166 break;
168 printf("%s", line);
169 return 1;
172 int conf_string(struct menu *menu)
174 struct symbol *sym = menu->sym;
175 const char *def, *help;
177 while (1) {
178 printf("%*s%s ", indent - 1, "", menu->prompt->text);
179 printf("(%s) ", sym->name);
180 def = sym_get_string_value(sym);
181 if (sym_get_string_value(sym))
182 printf("[%s] ", def);
183 if (!conf_askvalue(sym, def))
184 return 0;
185 switch (line[0]) {
186 case '\n':
187 break;
188 case '?':
189 /* print help */
190 if (line[1] == '\n') {
191 help = nohelp_text;
192 if (menu->sym->help)
193 help = menu->sym->help;
194 printf("\n%s\n", menu->sym->help);
195 def = NULL;
196 break;
198 default:
199 line[strlen(line)-1] = 0;
200 def = line;
202 if (def && sym_set_string_value(sym, def))
203 return 0;
207 static int conf_sym(struct menu *menu)
209 struct symbol *sym = menu->sym;
210 int type;
211 tristate oldval, newval;
212 const char *help;
214 while (1) {
215 printf("%*s%s ", indent - 1, "", menu->prompt->text);
216 if (sym->name)
217 printf("(%s) ", sym->name);
218 type = sym_get_type(sym);
219 putchar('[');
220 oldval = sym_get_tristate_value(sym);
221 switch (oldval) {
222 case no:
223 putchar('N');
224 break;
225 case mod:
226 putchar('M');
227 break;
228 case yes:
229 putchar('Y');
230 break;
232 if (oldval != no && sym_tristate_within_range(sym, no))
233 printf("/n");
234 if (oldval != mod && sym_tristate_within_range(sym, mod))
235 printf("/m");
236 if (oldval != yes && sym_tristate_within_range(sym, yes))
237 printf("/y");
238 if (sym->help)
239 printf("/?");
240 printf("] ");
241 if (!conf_askvalue(sym, sym_get_string_value(sym)))
242 return 0;
243 strip(line);
245 switch (line[0]) {
246 case 'n':
247 case 'N':
248 newval = no;
249 if (!line[1] || !strcmp(&line[1], "o"))
250 break;
251 continue;
252 case 'm':
253 case 'M':
254 newval = mod;
255 if (!line[1])
256 break;
257 continue;
258 case 'y':
259 case 'Y':
260 newval = yes;
261 if (!line[1] || !strcmp(&line[1], "es"))
262 break;
263 continue;
264 case 0:
265 newval = oldval;
266 break;
267 case '?':
268 goto help;
269 default:
270 continue;
272 if (sym_set_tristate_value(sym, newval))
273 return 0;
274 help:
275 help = nohelp_text;
276 if (sym->help)
277 help = sym->help;
278 printf("\n%s\n", help);
282 static int conf_choice(struct menu *menu)
284 struct symbol *sym, *def_sym;
285 struct menu *child;
286 int type;
287 bool is_new;
289 sym = menu->sym;
290 type = sym_get_type(sym);
291 is_new = !sym_has_value(sym);
292 if (sym_is_changable(sym)) {
293 conf_sym(menu);
294 sym_calc_value(sym);
295 switch (sym_get_tristate_value(sym)) {
296 case no:
297 return 1;
298 case mod:
299 return 0;
300 case yes:
301 break;
303 } else {
304 switch (sym_get_tristate_value(sym)) {
305 case no:
306 return 1;
307 case mod:
308 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
309 return 0;
310 case yes:
311 break;
315 while (1) {
316 int cnt, def;
318 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
319 def_sym = sym_get_choice_value(sym);
320 cnt = def = 0;
321 line[0] = 0;
322 for (child = menu->list; child; child = child->next) {
323 if (!menu_is_visible(child))
324 continue;
325 if (!child->sym) {
326 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
327 continue;
329 cnt++;
330 if (child->sym == def_sym) {
331 def = cnt;
332 printf("%*c", indent, '>');
333 } else
334 printf("%*c", indent, ' ');
335 printf(" %d. %s", cnt, menu_get_prompt(child));
336 if (child->sym->name)
337 printf(" (%s)", child->sym->name);
338 if (!sym_has_value(child->sym))
339 printf(" (NEW)");
340 printf("\n");
342 printf("%*schoice", indent - 1, "");
343 if (cnt == 1) {
344 printf("[1]: 1\n");
345 goto conf_childs;
347 printf("[1-%d", cnt);
348 if (sym->help)
349 printf("?");
350 printf("]: ");
351 switch (input_mode) {
352 case ask_new:
353 case ask_silent:
354 if (!is_new) {
355 cnt = def;
356 printf("%d\n", cnt);
357 break;
359 check_stdin();
360 case ask_all:
361 fflush(stdout);
362 fgets(line, 128, stdin);
363 strip(line);
364 if (line[0] == '?') {
365 printf("\n%s\n", menu->sym->help ?
366 menu->sym->help : nohelp_text);
367 continue;
369 if (!line[0])
370 cnt = def;
371 else if (isdigit(line[0]))
372 cnt = atoi(line);
373 else
374 continue;
375 break;
376 case set_random:
377 def = (random() % cnt) + 1;
378 case set_default:
379 case set_yes:
380 case set_mod:
381 case set_no:
382 cnt = def;
383 printf("%d\n", cnt);
384 break;
387 conf_childs:
388 for (child = menu->list; child; child = child->next) {
389 if (!child->sym || !menu_is_visible(child))
390 continue;
391 if (!--cnt)
392 break;
394 if (!child)
395 continue;
396 if (line[strlen(line) - 1] == '?') {
397 printf("\n%s\n", child->sym->help ?
398 child->sym->help : nohelp_text);
399 continue;
401 sym_set_choice_value(sym, child->sym);
402 if (child->list) {
403 indent += 2;
404 conf(child->list);
405 indent -= 2;
407 return 1;
411 static void conf(struct menu *menu)
413 struct symbol *sym;
414 struct property *prop;
415 struct menu *child;
417 if (!menu_is_visible(menu))
418 return;
420 sym = menu->sym;
421 prop = menu->prompt;
422 if (prop) {
423 const char *prompt;
425 switch (prop->type) {
426 case P_MENU:
427 if (input_mode == ask_silent && rootEntry != menu) {
428 check_conf(menu);
429 return;
431 case P_COMMENT:
432 prompt = menu_get_prompt(menu);
433 if (prompt)
434 printf("%*c\n%*c %s\n%*c\n",
435 indent, '*',
436 indent, '*', prompt,
437 indent, '*');
438 default:
443 if (!sym)
444 goto conf_childs;
446 if (sym_is_choice(sym)) {
447 conf_choice(menu);
448 if (sym->curr.tri != mod)
449 return;
450 goto conf_childs;
453 switch (sym->type) {
454 case S_INT:
455 case S_HEX:
456 case S_STRING:
457 conf_string(menu);
458 break;
459 default:
460 conf_sym(menu);
461 break;
464 conf_childs:
465 if (sym)
466 indent += 2;
467 for (child = menu->list; child; child = child->next)
468 conf(child);
469 if (sym)
470 indent -= 2;
473 static void check_conf(struct menu *menu)
475 struct symbol *sym;
476 struct menu *child;
478 if (!menu_is_visible(menu))
479 return;
481 sym = menu->sym;
482 if (sym && !sym_has_value(sym)) {
483 if (sym_is_changable(sym) ||
484 (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
485 if (!conf_cnt++)
486 printf(_("*\n* Restart config...\n*\n"));
487 rootEntry = menu_get_parent_menu(menu);
488 conf(rootEntry);
492 for (child = menu->list; child; child = child->next)
493 check_conf(child);
496 int main(int ac, char **av)
498 int i = 1;
499 const char *name;
500 struct stat tmpstat;
502 if (ac > i && av[i][0] == '-') {
503 switch (av[i++][1]) {
504 case 'o':
505 input_mode = ask_new;
506 break;
507 case 's':
508 input_mode = ask_silent;
509 valid_stdin = isatty(0) && isatty(1) && isatty(2);
510 break;
511 case 'd':
512 input_mode = set_default;
513 break;
514 case 'D':
515 input_mode = set_default;
516 defconfig_file = av[i++];
517 if (!defconfig_file) {
518 printf(_("%s: No default config file specified\n"),
519 av[0]);
520 exit(1);
522 break;
523 case 'n':
524 input_mode = set_no;
525 break;
526 case 'm':
527 input_mode = set_mod;
528 break;
529 case 'y':
530 input_mode = set_yes;
531 break;
532 case 'r':
533 input_mode = set_random;
534 srandom(time(NULL));
535 break;
536 case 'h':
537 case '?':
538 fprintf(stderr, "See README for usage info\n");
539 exit(0);
542 name = av[i];
543 if (!name) {
544 printf(_("%s: Kconfig file missing\n"), av[0]);
545 exit(1);
547 conf_parse(name);
548 //zconfdump(stdout);
549 switch (input_mode) {
550 case set_default:
551 if (!defconfig_file)
552 defconfig_file = conf_get_default_confname();
553 if (conf_read(defconfig_file)) {
554 printf("***\n"
555 "*** Can't find default configuration \"%s\"!\n"
556 "***\n", defconfig_file);
557 exit(1);
559 break;
560 case ask_silent:
561 if (stat(".config", &tmpstat)) {
562 printf(_("***\n"
563 "*** You have not yet configured your kernel!\n"
564 "*** (missing kernel .config file)\n"
565 "***\n"
566 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
567 "*** \"make menuconfig\" or \"make xconfig\").\n"
568 "***\n"));
569 exit(1);
571 case ask_all:
572 case ask_new:
573 conf_read(NULL);
574 break;
575 case set_no:
576 case set_mod:
577 case set_yes:
578 case set_random:
579 name = getenv("KCONFIG_ALLCONFIG");
580 if (name && !stat(name, &tmpstat)) {
581 conf_read_simple(name, S_DEF_USER);
582 break;
584 switch (input_mode) {
585 case set_no: name = "allno.config"; break;
586 case set_mod: name = "allmod.config"; break;
587 case set_yes: name = "allyes.config"; break;
588 case set_random: name = "allrandom.config"; break;
589 default: break;
591 if (!stat(name, &tmpstat))
592 conf_read_simple(name, S_DEF_USER);
593 else if (!stat("all.config", &tmpstat))
594 conf_read_simple("all.config", S_DEF_USER);
595 break;
596 default:
597 break;
600 if (input_mode != ask_silent) {
601 rootEntry = &rootmenu;
602 conf(&rootmenu);
603 if (input_mode == ask_all) {
604 input_mode = ask_silent;
605 valid_stdin = 1;
607 } else if (conf_get_changed()) {
608 name = getenv("KCONFIG_NOSILENTUPDATE");
609 if (name && *name) {
610 fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
611 return 1;
613 } else
614 goto skip_check;
616 do {
617 conf_cnt = 0;
618 check_conf(&rootmenu);
619 } while (conf_cnt);
620 if (conf_write(NULL)) {
621 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
622 return 1;
624 skip_check:
625 if (input_mode == ask_silent && conf_write_autoconf()) {
626 fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
627 return 1;
630 return 0;