root/trunk/freewrt/tools/config/conf.c

Revision 3205, 10.9 kB (checked in by austriancoder, 5 years ago)

This commit is a solution for the following problem:

Our snapshotbuilder - I will send a mail around in the next days for more
informations - will do the following tasks to generate a build:
* make distclean
* make allmodconfig
* changes target platform and other stuff in generated .config
* make oldconfig
* make

make oldconfig needs userinteraction and the user needs only to press
ENTER a few times (remeber: we changed some config values in step 3).
As we want to run our builds without userinteraction, we need something.
Now this commit introduces a new make target: snapshotupdate
It is equal to oldconfig, but uses data from stdin. So we can call e.g.
printf "\n" | make snapshotupdate (no user interaction)
instead of make oldconfig (with user interaction).

If somebody is not happy with this solution, commit a _working_ replacement,
which has the same functionality.

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