usbmodeswitch: Updated to v.1.2.6 from shibby's branch.
[tomato.git] / release / src / router / config / conf.c
blob62779625bb0484e42f231d13f437bebf513e8f46
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 <string.h>
9 #include <unistd.h>
10 #include <time.h>
11 #include <sys/stat.h>
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
16 static void conf(struct menu *menu);
17 static void check_conf(struct menu *menu);
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;
30 static int indent = 1;
31 static int valid_stdin = 1;
32 static int conf_cnt;
33 static char line[128];
34 static struct menu *rootEntry;
36 static char nohelp_text[] = "Sorry, no help available for this option yet.\n";
39 static void printo(const char *o)
41 static int sep = 0;
43 if (!sep) {
44 putchar('(');
45 sep = 1;
46 } else if (o) {
47 putchar(',');
48 putchar(' ');
50 if (!o) {
51 putchar(')');
52 putchar(' ');
53 sep = 0;
54 } else
55 printf("%s", o);
58 static void strip(char *str)
60 char *p = str;
61 int l;
63 while ((isspace((int)*p)))
64 p++;
65 l = strlen(p);
66 if (p != str)
67 memmove(str, p, l + 1);
68 if (!l)
69 return;
70 p = str + l - 1;
71 while ((isspace((int)*p)))
72 *p-- = 0;
75 static void conf_askvalue(struct symbol *sym, const char *def)
77 enum symbol_type type = sym_get_type(sym);
78 tristate val;
80 if (!sym_has_value(sym))
81 printf("(NEW) ");
83 line[0] = '\n';
84 line[1] = 0;
86 switch (input_mode) {
87 case ask_new:
88 case ask_silent:
89 if (sym_has_value(sym)) {
90 printf("%s\n", def);
91 return;
93 if (!valid_stdin && input_mode == ask_silent) {
94 printf("aborted!\n\n");
95 printf("Console input/output is redirected. ");
96 printf("Run 'make oldconfig' to update configuration.\n\n");
97 exit(1);
99 case ask_all:
100 fflush(stdout);
101 fgets(line, 128, stdin);
102 return;
103 case set_default:
104 printf("%s\n", def);
105 return;
106 default:
107 break;
110 switch (type) {
111 case S_INT:
112 case S_HEX:
113 case S_STRING:
114 printf("%s\n", def);
115 return;
116 default:
119 switch (input_mode) {
120 case set_yes:
121 if (sym_tristate_within_range(sym, yes)) {
122 line[0] = 'y';
123 line[1] = '\n';
124 line[2] = 0;
125 break;
127 case set_mod:
128 if (type == S_TRISTATE) {
129 if (sym_tristate_within_range(sym, mod)) {
130 line[0] = 'm';
131 line[1] = '\n';
132 line[2] = 0;
133 break;
135 } else {
136 if (sym_tristate_within_range(sym, yes)) {
137 line[0] = 'y';
138 line[1] = '\n';
139 line[2] = 0;
140 break;
143 case set_no:
144 if (sym_tristate_within_range(sym, no)) {
145 line[0] = 'n';
146 line[1] = '\n';
147 line[2] = 0;
148 break;
150 case set_random:
151 do {
152 val = (tristate)(random() % 3);
153 } while (!sym_tristate_within_range(sym, val));
154 switch (val) {
155 case no: line[0] = 'n'; break;
156 case mod: line[0] = 'm'; break;
157 case yes: line[0] = 'y'; break;
159 line[1] = '\n';
160 line[2] = 0;
161 break;
162 default:
163 break;
165 printf("%s", line);
168 int conf_string(struct menu *menu)
170 struct symbol *sym = menu->sym;
171 const char *def, *help;
173 while (1) {
174 printf("%*s%s ", indent - 1, "", menu->prompt->text);
175 printf("(%s) ", sym->name);
176 def = sym_get_string_value(sym);
177 if (sym_get_string_value(sym))
178 printf("[%s] ", def);
179 conf_askvalue(sym, def);
180 switch (line[0]) {
181 case '\n':
182 break;
183 case '?':
184 /* print help */
185 if (line[1] == 0) {
186 help = nohelp_text;
187 if (menu->sym->help)
188 help = menu->sym->help;
189 printf("\n%s\n", menu->sym->help);
190 def = NULL;
191 break;
193 default:
194 line[strlen(line)-1] = 0;
195 def = line;
197 if (def && sym_set_string_value(sym, def))
198 return 0;
202 static int conf_sym(struct menu *menu)
204 struct symbol *sym = menu->sym;
205 int type;
206 tristate oldval, newval;
207 const char *help;
209 while (1) {
210 printf("%*s%s ", indent - 1, "", menu->prompt->text);
211 if (sym->name)
212 printf("(%s) ", sym->name);
213 type = sym_get_type(sym);
214 putchar('[');
215 oldval = sym_get_tristate_value(sym);
216 switch (oldval) {
217 case no:
218 putchar('N');
219 break;
220 case mod:
221 putchar('M');
222 break;
223 case yes:
224 putchar('Y');
225 break;
227 if (oldval != no && sym_tristate_within_range(sym, no))
228 printf("/n");
229 if (oldval != mod && sym_tristate_within_range(sym, mod))
230 printf("/m");
231 if (oldval != yes && sym_tristate_within_range(sym, yes))
232 printf("/y");
233 if (sym->help)
234 printf("/?");
235 printf("] ");
236 conf_askvalue(sym, sym_get_string_value(sym));
237 strip(line);
239 switch (line[0]) {
240 case 'n':
241 case 'N':
242 newval = no;
243 if (!line[1] || !strcmp(&line[1], "o"))
244 break;
245 continue;
246 case 'm':
247 case 'M':
248 newval = mod;
249 if (!line[1])
250 break;
251 continue;
252 case 'y':
253 case 'Y':
254 newval = yes;
255 if (!line[1] || !strcmp(&line[1], "es"))
256 break;
257 continue;
258 case 0:
259 newval = oldval;
260 break;
261 case '?':
262 goto help;
263 default:
264 continue;
266 if (sym_set_tristate_value(sym, newval))
267 return 0;
268 help:
269 help = nohelp_text;
270 if (sym->help)
271 help = sym->help;
272 printf("\n%s\n", help);
276 static int conf_choice(struct menu *menu)
278 struct symbol *sym, *def_sym;
279 struct menu *cmenu, *def_menu;
280 const char *help;
281 int type, len;
282 bool is_new;
284 sym = menu->sym;
285 type = sym_get_type(sym);
286 is_new = !sym_has_value(sym);
287 if (sym_is_changable(sym)) {
288 conf_sym(menu);
289 sym_calc_value(sym);
290 switch (sym_get_tristate_value(sym)) {
291 case no:
292 return 1;
293 case mod:
294 return 0;
295 case yes:
296 break;
298 } else {
299 sym->def = sym->curr;
300 if (S_TRI(sym->curr) == mod) {
301 printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
302 return 0;
306 while (1) {
307 printf("%*s%s ", indent - 1, "", menu_get_prompt(menu));
308 def_sym = sym_get_choice_value(sym);
309 def_menu = NULL;
310 for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
311 if (!menu_is_visible(cmenu))
312 continue;
313 printo(menu_get_prompt(cmenu));
314 if (cmenu->sym == def_sym)
315 def_menu = cmenu;
317 printo(NULL);
318 if (def_menu)
319 printf("[%s] ", menu_get_prompt(def_menu));
320 else {
321 printf("\n");
322 return 1;
324 switch (input_mode) {
325 case ask_new:
326 case ask_silent:
327 case ask_all:
328 conf_askvalue(sym, menu_get_prompt(def_menu));
329 strip(line);
330 break;
331 default:
332 line[0] = 0;
333 printf("\n");
335 if (line[0] == '?' && !line[1]) {
336 help = nohelp_text;
337 if (menu->sym->help)
338 help = menu->sym->help;
339 printf("\n%s\n", help);
340 continue;
342 if (line[0]) {
343 len = strlen(line);
344 line[len] = 0;
346 def_menu = NULL;
347 for (cmenu = menu->list; cmenu; cmenu = cmenu->next) {
348 if (!cmenu->sym || !menu_is_visible(cmenu))
349 continue;
350 if (!strncasecmp(line, menu_get_prompt(cmenu), len)) {
351 def_menu = cmenu;
352 break;
356 if (def_menu) {
357 sym_set_choice_value(sym, def_menu->sym);
358 if (def_menu->list) {
359 indent += 2;
360 conf(def_menu->list);
361 indent -= 2;
363 return 1;
368 static void conf(struct menu *menu)
370 struct symbol *sym;
371 struct property *prop;
372 struct menu *child;
374 if (!menu_is_visible(menu))
375 return;
377 sym = menu->sym;
378 prop = menu->prompt;
379 if (prop) {
380 const char *prompt;
382 switch (prop->type) {
383 case P_MENU:
384 if (input_mode == ask_silent && rootEntry != menu) {
385 check_conf(menu);
386 return;
388 case P_COMMENT:
389 prompt = menu_get_prompt(menu);
390 if (prompt)
391 printf("%*c\n%*c %s\n%*c\n",
392 indent, '*',
393 indent, '*', prompt,
394 indent, '*');
395 default:
400 if (!sym)
401 goto conf_childs;
403 if (sym_is_choice(sym)) {
404 conf_choice(menu);
405 if (S_TRI(sym->curr) != mod)
406 return;
407 goto conf_childs;
410 switch (sym->type) {
411 case S_INT:
412 case S_HEX:
413 case S_STRING:
414 conf_string(menu);
415 break;
416 default:
417 conf_sym(menu);
418 break;
421 conf_childs:
422 if (sym)
423 indent += 2;
424 for (child = menu->list; child; child = child->next)
425 conf(child);
426 if (sym)
427 indent -= 2;
430 static void check_conf(struct menu *menu)
432 struct symbol *sym;
433 struct menu *child;
435 if (!menu_is_visible(menu))
436 return;
438 sym = menu->sym;
439 if (!sym)
440 goto conf_childs;
442 if (sym_is_choice(sym)) {
443 if (!sym_has_value(sym)) {
444 if (!conf_cnt++)
445 printf("*\n* Restart config...\n*\n");
446 rootEntry = menu_get_parent_menu(menu);
447 conf(rootEntry);
449 if (sym_get_tristate_value(sym) != mod)
450 return;
451 goto conf_childs;
454 if (!sym_has_value(sym)) {
455 if (!conf_cnt++)
456 printf("*\n* Restart config...\n*\n");
457 rootEntry = menu_get_parent_menu(menu);
458 conf(rootEntry);
461 conf_childs:
462 for (child = menu->list; child; child = child->next)
463 check_conf(child);
466 int main(int ac, char **av)
468 const char *name;
469 struct stat tmpstat;
471 if (ac > 1 && av[1][0] == '-') {
472 switch (av[1][1]) {
473 case 'o':
474 input_mode = ask_new;
475 break;
476 case 's':
477 input_mode = ask_silent;
478 valid_stdin = isatty(0) && isatty(1) && isatty(2);
479 break;
480 case 'd':
481 input_mode = set_default;
482 break;
483 case 'n':
484 input_mode = set_no;
485 break;
486 case 'm':
487 input_mode = set_mod;
488 break;
489 case 'y':
490 input_mode = set_yes;
491 break;
492 case 'r':
493 input_mode = set_random;
494 srandom(time(NULL));
495 break;
496 case 'h':
497 case '?':
498 printf("%s [-o|-s] config\n", av[0]);
499 exit(0);
501 name = av[2];
502 } else
503 name = av[1];
504 conf_parse(name);
505 //zconfdump(stdout);
506 switch (input_mode) {
507 case set_default:
508 name = conf_get_default_confname();
509 if (conf_read(name)) {
510 printf("***\n"
511 "*** Can't find default configuration \"%s\"!\n"
512 "***\n", name);
513 exit(1);
515 break;
516 case ask_silent:
517 if (stat(".config", &tmpstat)) {
518 printf("***\n"
519 "*** You have not yet configured!\n"
520 "***\n"
521 "*** Please run some configurator (e.g. \"make oldconfig\"\n"
522 "*** or \"make menuconfig\").\n"
523 "***\n");
524 exit(1);
526 case ask_all:
527 case ask_new:
528 conf_read(NULL);
529 break;
530 default:
531 break;
534 if (input_mode != ask_silent) {
535 rootEntry = &rootmenu;
536 conf(&rootmenu);
537 if (input_mode == ask_all) {
538 input_mode = ask_silent;
539 valid_stdin = 1;
542 do {
543 conf_cnt = 0;
544 check_conf(&rootmenu);
545 } while (conf_cnt);
546 conf_write(NULL);
547 return 0;