enabled when DEVELOPER=1
[openwrt.git] / openwrt / package / config / conf.c
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <time.h>
11 #include <sys/stat.h>
12
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
15
16 static void conf(struct menu *menu);
17 static void check_conf(struct menu *menu);
18
19 enum {
20 ask_all,
21 ask_new,
22 ask_silent,
23 set_default,
24 set_yes,
25 set_mod,
26 set_no,
27 set_random
28 } input_mode = ask_all;
29 char *defconfig_file;
30
31 static int indent = 1;
32 static int valid_stdin = 1;
33 static int conf_cnt;
34 static char line[128];
35 static struct menu *rootEntry;
36
37 static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
38
39 static void strip(char *str)
40 {
41 char *p = str;
42 int l;
43
44 while ((isspace(*p)))
45 p++;
46 l = strlen(p);
47 if (p != str)
48 memmove(str, p, l + 1);
49 if (!l)
50 return;
51 p = str + l - 1;
52 while ((isspace(*p)))
53 *p-- = 0;
54 }
55
56 static void check_stdin(void)
57 {
58 if (!valid_stdin && input_mode == ask_silent) {
59 printf("aborted!\n\n");
60 printf("Console input/output is redirected. ");
61 printf("Run 'make oldconfig' to update configuration.\n\n");
62 exit(1);
63 }
64 }
65
66 static void conf_askvalue(struct symbol *sym, const char *def)
67 {
68 enum symbol_type type = sym_get_type(sym);
69 tristate val;
70
71 if (!sym_has_value(sym))
72 printf("(NEW) ");
73
74 line[0] = '\n';
75 line[1] = 0;
76
77 if (!sym_is_changable(sym)) {
78 printf("%s\n", def);
79 line[0] = '\n';
80 line[1] = 0;
81 return;
82 }
83
84 switch (input_mode) {
85 case ask_new:
86 case ask_silent:
87 if (sym_has_value(sym)) {
88 printf("%s\n", def);
89 return;
90 }
91 check_stdin();
92 case ask_all:
93 fflush(stdout);
94 fgets(line, 128, stdin);
95 return;
96 case set_default:
97 printf("%s\n", def);
98 return;
99 default:
100 break;
101 }
102
103 switch (type) {
104 case S_INT:
105 case S_HEX:
106 case S_STRING:
107 printf("%s\n", def);
108 return;
109 default:
110 ;
111 }
112 switch (input_mode) {
113 case set_yes:
114 if (sym_tristate_within_range(sym, yes)) {
115 line[0] = 'y';
116 line[1] = '\n';
117 line[2] = 0;
118 break;
119 }
120 case set_mod:
121 if (type == S_TRISTATE) {
122 if (sym_tristate_within_range(sym, mod)) {
123 line[0] = 'm';
124 line[1] = '\n';
125 line[2] = 0;
126 break;
127 }
128 } else {
129 if (sym_tristate_within_range(sym, yes)) {
130 line[0] = 'y';
131 line[1] = '\n';
132 line[2] = 0;
133 break;
134 }
135 }
136 case set_no:
137 if (sym_tristate_within_range(sym, no)) {
138 line[0] = 'n';
139 line[1] = '\n';
140 line[2] = 0;
141 break;
142 }
143 case set_random:
144 do {
145 val = (tristate)(random() % 3);
146 } while (!sym_tristate_within_range(sym, val));
147 switch (val) {
148 case no: line[0] = 'n'; break;
149 case mod: line[0] = 'm'; break;
150 case yes: line[0] = 'y'; break;
151 }
152 line[1] = '\n';
153 line[2] = 0;
154 break;
155 default:
156 break;
157 }
158 printf("%s", line);
159 }
160
161 int conf_string(struct menu *menu)
162 {
163 struct symbol *sym = menu->sym;
164 const char *def, *help;
165
166 while (1) {
167 printf("%*s%s ", indent - 1, "", menu->prompt->text);
168 printf("(%s) ", sym->name);
169 def = sym_get_string_value(sym);
170 if (sym_get_string_value(sym))
171 printf("[%s] ", def);
172 conf_askvalue(sym, def);
173 switch (line[0]) {
174 case '\n':
175 break;
176 case '?':
177 /* print help */
178 if (line[1] == '\n') {
179 help = nohelp_text;
180 if (menu->sym->help)
181 help = menu->sym->help;
182 printf("\n%s\n", menu->sym->help);
183 def = NULL;
184 break;
185 }
186 default:
187 line[strlen(line)-1] = 0;
188 def = line;
189 }
190 if (def && sym_set_string_value(sym, def))
191 return 0;
192 }
193 }
194
195 static int conf_sym(struct menu *menu)
196 {
197 struct symbol *sym = menu->sym;
198 int type;
199 tristate oldval, newval;
200 const char *help;
201
202 while (1) {
203 printf("%*s%s ", indent - 1, "", menu->prompt->text);
204 if (sym->name)
205 printf("(%s) ", sym->name);
206 type = sym_get_type(sym);
207 putchar('[');
208 oldval = sym_get_tristate_value(sym);
209 switch (oldval) {
210 case no:
211 putchar('N');
212 break;
213 case mod:
214 putchar('M');
215 break;
216 case yes:
217 putchar('Y');
218 break;
219 }
220 if (oldval != no && sym_tristate_within_range(sym, no))
221 printf("/n");
222 if (oldval != mod && sym_tristate_within_range(sym, mod))
223 printf("/m");
224 if (oldval != yes && sym_tristate_within_range(sym, yes))
225 printf("/y");
226 if (sym->help)
227 printf("/?");
228 printf("] ");
229 conf_askvalue(sym, sym_get_string_value(sym));
230 strip(line);
231
232 switch (line[0]) {
233 case 'n':
234 case 'N':
235 newval = no;
236 if (!line[1] || !strcmp(&line[1], "o"))
237 break;
238 continue;
239 case 'm':
240 case 'M':
241 newval = mod;
242 if (!line[1])
243 break;
244 continue;
245 case 'y':
246 case 'Y':
247 newval = yes;
248 if (!line[1] || !strcmp(&line[1], "es"))
249 break;
250 continue;
251 case 0:
252 newval = oldval;
253 break;
254 case '?':
255 goto help;
256 default:
257 continue;
258 }
259 if (sym_set_tristate_value(sym, newval))
260 return 0;
261 help:
262 help = nohelp_text;
263 if (sym->help)
264 help = sym->help;
265 printf("\n%s\n", help);
266 }
267 }
268
269 static int conf_choice(struct menu *menu)
270 {
271 struct symbol *sym, *def_sym;
272 struct menu *child;
273 int type;
274 bool is_new;
275
276 sym = menu->sym;
277 type = sym_get_type(sym);
278 is_new = !sym_has_value(sym);
279 if (sym_is_changable(sym)) {
280 conf_sym(menu);
281 sym_calc_value(sym);
282 switch (sym_get_tristate_value(sym)) {
283 case no:
284 return 1;
285 case mod:
286 return 0;
287 case yes:
288 break;
289 }
290 } else {
291 switch (sym_get_tristate_value(sym)) {
292 case no:
293 return 1;
294 case mod:
295 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
296 return 0;
297 case yes:
298 break;
299 }
300 }
301
302 while (1) {
303 int cnt, def;
304
305 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
306 def_sym = sym_get_choice_value(sym);
307 cnt = def = 0;
308 line[0] = '0';
309 line[1] = 0;
310 for (child = menu->list; child; child = child->next) {
311 if (!menu_is_visible(child))
312 continue;
313 if (!child->sym) {
314 printf("%*c %s\n", indent, '*', menu_get_prompt(child));
315 continue;
316 }
317 cnt++;
318 if (child->sym == def_sym) {
319 def = cnt;
320 printf("%*c", indent, '>');
321 } else
322 printf("%*c", indent, ' ');
323 printf(" %d. %s", cnt, menu_get_prompt(child));
324 if (child->sym->name)
325 printf(" (%s)", child->sym->name);
326 if (!sym_has_value(child->sym))
327 printf(" (NEW)");
328 printf("\n");
329 }
330 printf("%*schoice", indent - 1, "");
331 if (cnt == 1) {
332 printf("[1]: 1\n");
333 goto conf_childs;
334 }
335 printf("[1-%d", cnt);
336 if (sym->help)
337 printf("?");
338 printf("]: ");
339 switch (input_mode) {
340 case ask_new:
341 case ask_silent:
342 if (!is_new) {
343 cnt = def;
344 printf("%d\n", cnt);
345 break;
346 }
347 check_stdin();
348 case ask_all:
349 fflush(stdout);
350 fgets(line, 128, stdin);
351 strip(line);
352 if (line[0] == '?') {
353 printf("\n%s\n", menu->sym->help ?
354 menu->sym->help : nohelp_text);
355 continue;
356 }
357 if (!line[0])
358 cnt = def;
359 else if (isdigit(line[0]))
360 cnt = atoi(line);
361 else
362 continue;
363 break;
364 case set_random:
365 def = (random() % cnt) + 1;
366 case set_default:
367 case set_yes:
368 case set_mod:
369 case set_no:
370 cnt = def;
371 printf("%d\n", cnt);
372 break;
373 }
374
375 conf_childs:
376 for (child = menu->list; child; child = child->next) {
377 if (!child->sym || !menu_is_visible(child))
378 continue;
379 if (!--cnt)
380 break;
381 }
382 if (!child)
383 continue;
384 if (line[strlen(line) - 1] == '?') {
385 printf("\n%s\n", child->sym->help ?
386 child->sym->help : nohelp_text);
387 continue;
388 }
389 sym_set_choice_value(sym, child->sym);
390 if (child->list) {
391 indent += 2;
392 conf(child->list);
393 indent -= 2;
394 }
395 return 1;
396 }
397 }
398
399 static void conf(struct menu *menu)
400 {
401 struct symbol *sym;
402 struct property *prop;
403 struct menu *child;
404
405 if (!menu_is_visible(menu))
406 return;
407
408 sym = menu->sym;
409 prop = menu->prompt;
410 if (prop) {
411 const char *prompt;
412
413 switch (prop->type) {
414 case P_MENU:
415 if (input_mode == ask_silent && rootEntry != menu) {
416 check_conf(menu);
417 return;
418 }
419 case P_COMMENT:
420 prompt = menu_get_prompt(menu);
421 if (prompt)
422 printf("%*c\n%*c %s\n%*c\n",
423 indent, '*',
424 indent, '*', prompt,
425 indent, '*');
426 default:
427 ;
428 }
429 }
430
431 if (!sym)
432 goto conf_childs;
433
434 if (sym_is_choice(sym)) {
435 conf_choice(menu);
436 if (sym->curr.tri != mod)
437 return;
438 goto conf_childs;
439 }
440
441 switch (sym->type) {
442 case S_INT:
443 case S_HEX:
444 case S_STRING:
445 conf_string(menu);
446 break;
447 default:
448 conf_sym(menu);
449 break;
450 }
451
452 conf_childs:
453 if (sym)
454 indent += 2;
455 for (child = menu->list; child; child = child->next)
456 conf(child);
457 if (sym)
458 indent -= 2;
459 }
460
461 static void check_conf(struct menu *menu)
462 {
463 struct symbol *sym;
464 struct menu *child;
465
466 if (!menu_is_visible(menu))
467 return;
468
469 sym = menu->sym;
470 if (sym) {
471 if (sym_is_changable(sym) && !sym_has_value(sym)) {
472 if (!conf_cnt++)
473 printf("*\n* Restart config...\n*\n");
474 rootEntry = menu_get_parent_menu(menu);
475 conf(rootEntry);
476 }
477 if (sym_is_choice(sym) && sym_get_tristate_value(sym) != mod)
478 return;
479 }
480
481 for (child = menu->list; child; child = child->next)
482 check_conf(child);
483 }
484
485 int main(int ac, char **av)
486 {
487 int i = 1;
488 const char *name;
489 struct stat tmpstat;
490
491 if (ac > i && av[i][0] == '-') {
492 switch (av[i++][1]) {
493 case 'o':
494 input_mode = ask_new;
495 break;
496 case 's':
497 input_mode = ask_silent;
498 valid_stdin = isatty(0) && isatty(1) && isatty(2);
499 break;
500 case 'd':
501 input_mode = set_default;
502 break;
503 case 'D':
504 input_mode = set_default;
505 defconfig_file = av[i++];
506 if (!defconfig_file) {
507 printf("%s: No default config file specified\n",
508 av[0]);
509 exit(1);
510 }
511 break;
512 case 'n':
513 input_mode = set_no;
514 break;
515 case 'm':
516 input_mode = set_mod;
517 break;
518 case 'y':
519 input_mode = set_yes;
520 break;
521 case 'r':
522 input_mode = set_random;
523 srandom(time(NULL));
524 break;
525 case 'h':
526 case '?':
527 printf("%s [-o|-s] config\n", av[0]);
528 exit(0);
529 }
530 }
531 name = av[i];
532 if (!name) {
533 printf("%s: configuration file missing\n", av[0]);
534 }
535 conf_parse(name);
536 //zconfdump(stdout);
537 switch (input_mode) {
538 case set_default:
539 if (!defconfig_file)
540 defconfig_file = conf_get_default_confname();
541 if (conf_read(defconfig_file)) {
542 printf("***\n"
543 "*** Can't find default configuration \"%s\"!\n"
544 "***\n", defconfig_file);
545 exit(1);
546 }
547 break;
548 case ask_silent:
549 if (stat(".config", &tmpstat)) {
550 printf("***\n"
551 "*** You have not yet configured Buildroot!\n"
552 "***\n"
553 "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
554 "*** \"make menuconfig\" or \"make config\").\n"
555 "***\n");
556 exit(1);
557 }
558 case ask_all:
559 case ask_new:
560 conf_read(NULL);
561 break;
562 default:
563 break;
564 }
565
566 if (input_mode != ask_silent) {
567 rootEntry = &rootmenu;
568 conf(&rootmenu);
569 if (input_mode == ask_all) {
570 input_mode = ask_silent;
571 valid_stdin = 1;
572 }
573 }
574 do {
575 conf_cnt = 0;
576 check_conf(&rootmenu);
577 } while (conf_cnt);
578 if (conf_write(NULL)) {
579 fprintf(stderr, "\n*** Error during writing of the Buildroot configuration.\n\n");
580 return 1;
581 }
582 return 0;
583 }
This page took 0.069978 seconds and 5 git commands to generate.