Linux-2.6.12-rc2
[deliverable/linux.git] / scripts / kconfig / mconf.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 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
7 */
8
9 #include <sys/ioctl.h>
10 #include <sys/wait.h>
11 #include <ctype.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <limits.h>
15 #include <signal.h>
16 #include <stdarg.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <termios.h>
20 #include <unistd.h>
21
22 #define LKC_DIRECT_LINK
23 #include "lkc.h"
24
25 static char menu_backtitle[128];
26 static const char mconf_readme[] =
27 "Overview\n"
28 "--------\n"
29 "Some kernel features may be built directly into the kernel.\n"
30 "Some may be made into loadable runtime modules. Some features\n"
31 "may be completely removed altogether. There are also certain\n"
32 "kernel parameters which are not really features, but must be\n"
33 "entered in as decimal or hexadecimal numbers or possibly text.\n"
34 "\n"
35 "Menu items beginning with [*], <M> or [ ] represent features\n"
36 "configured to be built in, modularized or removed respectively.\n"
37 "Pointed brackets <> represent module capable features.\n"
38 "\n"
39 "To change any of these features, highlight it with the cursor\n"
40 "keys and press <Y> to build it in, <M> to make it a module or\n"
41 "<N> to removed it. You may also press the <Space Bar> to cycle\n"
42 "through the available options (ie. Y->N->M->Y).\n"
43 "\n"
44 "Some additional keyboard hints:\n"
45 "\n"
46 "Menus\n"
47 "----------\n"
48 "o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
49 " you wish to change or submenu wish to select and press <Enter>.\n"
50 " Submenus are designated by \"--->\".\n"
51 "\n"
52 " Shortcut: Press the option's highlighted letter (hotkey).\n"
53 " Pressing a hotkey more than once will sequence\n"
54 " through all visible items which use that hotkey.\n"
55 "\n"
56 " You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
57 " unseen options into view.\n"
58 "\n"
59 "o To exit a menu use the cursor keys to highlight the <Exit> button\n"
60 " and press <ENTER>.\n"
61 "\n"
62 " Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
63 " using those letters. You may press a single <ESC>, but\n"
64 " there is a delayed response which you may find annoying.\n"
65 "\n"
66 " Also, the <TAB> and cursor keys will cycle between <Select>,\n"
67 " <Exit> and <Help>\n"
68 "\n"
69 "o To get help with an item, use the cursor keys to highlight <Help>\n"
70 " and Press <ENTER>.\n"
71 "\n"
72 " Shortcut: Press <H> or <?>.\n"
73 "\n"
74 "\n"
75 "Radiolists (Choice lists)\n"
76 "-----------\n"
77 "o Use the cursor keys to select the option you wish to set and press\n"
78 " <S> or the <SPACE BAR>.\n"
79 "\n"
80 " Shortcut: Press the first letter of the option you wish to set then\n"
81 " press <S> or <SPACE BAR>.\n"
82 "\n"
83 "o To see available help for the item, use the cursor keys to highlight\n"
84 " <Help> and Press <ENTER>.\n"
85 "\n"
86 " Shortcut: Press <H> or <?>.\n"
87 "\n"
88 " Also, the <TAB> and cursor keys will cycle between <Select> and\n"
89 " <Help>\n"
90 "\n"
91 "\n"
92 "Data Entry\n"
93 "-----------\n"
94 "o Enter the requested information and press <ENTER>\n"
95 " If you are entering hexadecimal values, it is not necessary to\n"
96 " add the '0x' prefix to the entry.\n"
97 "\n"
98 "o For help, use the <TAB> or cursor keys to highlight the help option\n"
99 " and press <ENTER>. You can try <TAB><H> as well.\n"
100 "\n"
101 "\n"
102 "Text Box (Help Window)\n"
103 "--------\n"
104 "o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
105 " keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
106 " who are familiar with less and lynx.\n"
107 "\n"
108 "o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
109 "\n"
110 "\n"
111 "Alternate Configuration Files\n"
112 "-----------------------------\n"
113 "Menuconfig supports the use of alternate configuration files for\n"
114 "those who, for various reasons, find it necessary to switch\n"
115 "between different kernel configurations.\n"
116 "\n"
117 "At the end of the main menu you will find two options. One is\n"
118 "for saving the current configuration to a file of your choosing.\n"
119 "The other option is for loading a previously saved alternate\n"
120 "configuration.\n"
121 "\n"
122 "Even if you don't use alternate configuration files, but you\n"
123 "find during a Menuconfig session that you have completely messed\n"
124 "up your settings, you may use the \"Load Alternate...\" option to\n"
125 "restore your previously saved settings from \".config\" without\n"
126 "restarting Menuconfig.\n"
127 "\n"
128 "Other information\n"
129 "-----------------\n"
130 "If you use Menuconfig in an XTERM window make sure you have your\n"
131 "$TERM variable set to point to a xterm definition which supports color.\n"
132 "Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
133 "display correctly in a RXVT window because rxvt displays only one\n"
134 "intensity of color, bright.\n"
135 "\n"
136 "Menuconfig will display larger menus on screens or xterms which are\n"
137 "set to display more than the standard 25 row by 80 column geometry.\n"
138 "In order for this to work, the \"stty size\" command must be able to\n"
139 "display the screen's current row and column geometry. I STRONGLY\n"
140 "RECOMMEND that you make sure you do NOT have the shell variables\n"
141 "LINES and COLUMNS exported into your environment. Some distributions\n"
142 "export those variables via /etc/profile. Some ncurses programs can\n"
143 "become confused when those variables (LINES & COLUMNS) don't reflect\n"
144 "the true screen size.\n"
145 "\n"
146 "Optional personality available\n"
147 "------------------------------\n"
148 "If you prefer to have all of the kernel options listed in a single\n"
149 "menu, rather than the default multimenu hierarchy, run the menuconfig\n"
150 "with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
151 "\n"
152 "make MENUCONFIG_MODE=single_menu menuconfig\n"
153 "\n"
154 "<Enter> will then unroll the appropriate category, or enfold it if it\n"
155 "is already unrolled.\n"
156 "\n"
157 "Note that this mode can eventually be a little more CPU expensive\n"
158 "(especially with a larger number of unrolled categories) than the\n"
159 "default mode.\n",
160 menu_instructions[] =
161 "Arrow keys navigate the menu. "
162 "<Enter> selects submenus --->. "
163 "Highlighted letters are hotkeys. "
164 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
165 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
166 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
167 radiolist_instructions[] =
168 "Use the arrow keys to navigate this window or "
169 "press the hotkey of the item you wish to select "
170 "followed by the <SPACE BAR>. "
171 "Press <?> for additional information about this option.",
172 inputbox_instructions_int[] =
173 "Please enter a decimal value. "
174 "Fractions will not be accepted. "
175 "Use the <TAB> key to move from the input field to the buttons below it.",
176 inputbox_instructions_hex[] =
177 "Please enter a hexadecimal value. "
178 "Use the <TAB> key to move from the input field to the buttons below it.",
179 inputbox_instructions_string[] =
180 "Please enter a string value. "
181 "Use the <TAB> key to move from the input field to the buttons below it.",
182 setmod_text[] =
183 "This feature depends on another which has been configured as a module.\n"
184 "As a result, this feature will be built as a module.",
185 nohelp_text[] =
186 "There is no help available for this kernel option.\n",
187 load_config_text[] =
188 "Enter the name of the configuration file you wish to load. "
189 "Accept the name shown to restore the configuration you "
190 "last retrieved. Leave blank to abort.",
191 load_config_help[] =
192 "\n"
193 "For various reasons, one may wish to keep several different kernel\n"
194 "configurations available on a single machine.\n"
195 "\n"
196 "If you have saved a previous configuration in a file other than the\n"
197 "kernel's default, entering the name of the file here will allow you\n"
198 "to modify that configuration.\n"
199 "\n"
200 "If you are uncertain, then you have probably never used alternate\n"
201 "configuration files. You should therefor leave this blank to abort.\n",
202 save_config_text[] =
203 "Enter a filename to which this configuration should be saved "
204 "as an alternate. Leave blank to abort.",
205 save_config_help[] =
206 "\n"
207 "For various reasons, one may wish to keep different kernel\n"
208 "configurations available on a single machine.\n"
209 "\n"
210 "Entering a file name here will allow you to later retrieve, modify\n"
211 "and use the current configuration as an alternate to whatever\n"
212 "configuration options you have selected at that time.\n"
213 "\n"
214 "If you are uncertain what all this means then you should probably\n"
215 "leave this blank.\n",
216 search_help[] =
217 "\n"
218 "Search for CONFIG_ symbols and display their relations.\n"
219 "Example: search for \"^FOO\"\n"
220 "Result:\n"
221 "-----------------------------------------------------------------\n"
222 "Symbol: FOO [=m]\n"
223 "Prompt: Foo bus is used to drive the bar HW\n"
224 "Defined at drivers/pci/Kconfig:47\n"
225 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
226 "Location:\n"
227 " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
228 " -> PCI support (PCI [=y])\n"
229 " -> PCI access mode (<choice> [=y])\n"
230 "Selects: LIBCRC32\n"
231 "Selected by: BAR\n"
232 "-----------------------------------------------------------------\n"
233 "o The line 'Prompt:' shows the text used in the menu structure for\n"
234 " this CONFIG_ symbol\n"
235 "o The 'Defined at' line tell at what file / line number the symbol\n"
236 " is defined\n"
237 "o The 'Depends on:' line tell what symbols needs to be defined for\n"
238 " this symbol to be visible in the menu (selectable)\n"
239 "o The 'Location:' lines tell where in the menu structure this symbol\n"
240 " is located\n"
241 " A location followed by a [=y] indicate that this is a selectable\n"
242 " menu item - and current value is displayed inside brackets.\n"
243 "o The 'Selects:' line tell what symbol will be automatically\n"
244 " selected if this symbol is selected (y or m)\n"
245 "o The 'Selected by' line tell what symbol has selected this symbol\n"
246 "\n"
247 "Only relevant lines are shown.\n"
248 "\n\n"
249 "Search examples:\n"
250 "Examples: USB => find all CONFIG_ symbols containing USB\n"
251 " ^USB => find all CONFIG_ symbols starting with USB\n"
252 " USB$ => find all CONFIG_ symbols ending with USB\n"
253 "\n";
254
255 static signed char buf[4096], *bufptr = buf;
256 static signed char input_buf[4096];
257 static char filename[PATH_MAX+1] = ".config";
258 static char *args[1024], **argptr = args;
259 static int indent;
260 static struct termios ios_org;
261 static int rows = 0, cols = 0;
262 static struct menu *current_menu;
263 static int child_count;
264 static int do_resize;
265 static int single_menu_mode;
266
267 static void conf(struct menu *menu);
268 static void conf_choice(struct menu *menu);
269 static void conf_string(struct menu *menu);
270 static void conf_load(void);
271 static void conf_save(void);
272 static void show_textbox(const char *title, const char *text, int r, int c);
273 static void show_helptext(const char *title, const char *text);
274 static void show_help(struct menu *menu);
275 static void show_file(const char *filename, const char *title, int r, int c);
276
277 static void cprint_init(void);
278 static int cprint1(const char *fmt, ...);
279 static void cprint_done(void);
280 static int cprint(const char *fmt, ...);
281
282 static void init_wsize(void)
283 {
284 struct winsize ws;
285 char *env;
286
287 if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
288 rows = ws.ws_row;
289 cols = ws.ws_col;
290 }
291
292 if (!rows) {
293 env = getenv("LINES");
294 if (env)
295 rows = atoi(env);
296 if (!rows)
297 rows = 24;
298 }
299 if (!cols) {
300 env = getenv("COLUMNS");
301 if (env)
302 cols = atoi(env);
303 if (!cols)
304 cols = 80;
305 }
306
307 if (rows < 19 || cols < 80) {
308 fprintf(stderr, "Your display is too small to run Menuconfig!\n");
309 fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
310 exit(1);
311 }
312
313 rows -= 4;
314 cols -= 5;
315 }
316
317 static void cprint_init(void)
318 {
319 bufptr = buf;
320 argptr = args;
321 memset(args, 0, sizeof(args));
322 indent = 0;
323 child_count = 0;
324 cprint("./scripts/lxdialog/lxdialog");
325 cprint("--backtitle");
326 cprint(menu_backtitle);
327 }
328
329 static int cprint1(const char *fmt, ...)
330 {
331 va_list ap;
332 int res;
333
334 if (!*argptr)
335 *argptr = bufptr;
336 va_start(ap, fmt);
337 res = vsprintf(bufptr, fmt, ap);
338 va_end(ap);
339 bufptr += res;
340
341 return res;
342 }
343
344 static void cprint_done(void)
345 {
346 *bufptr++ = 0;
347 argptr++;
348 }
349
350 static int cprint(const char *fmt, ...)
351 {
352 va_list ap;
353 int res;
354
355 *argptr++ = bufptr;
356 va_start(ap, fmt);
357 res = vsprintf(bufptr, fmt, ap);
358 va_end(ap);
359 bufptr += res;
360 *bufptr++ = 0;
361
362 return res;
363 }
364
365 static void get_prompt_str(struct gstr *r, struct property *prop)
366 {
367 int i, j;
368 struct menu *submenu[8], *menu;
369
370 str_printf(r, "Prompt: %s\n", prop->text);
371 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
372 prop->menu->lineno);
373 if (!expr_is_yes(prop->visible.expr)) {
374 str_append(r, " Depends on: ");
375 expr_gstr_print(prop->visible.expr, r);
376 str_append(r, "\n");
377 }
378 menu = prop->menu->parent;
379 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
380 submenu[i++] = menu;
381 if (i > 0) {
382 str_printf(r, " Location:\n");
383 for (j = 4; --i >= 0; j += 2) {
384 menu = submenu[i];
385 str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
386 if (menu->sym) {
387 str_printf(r, " (%s [=%s])", menu->sym->name ?
388 menu->sym->name : "<choice>",
389 sym_get_string_value(menu->sym));
390 }
391 str_append(r, "\n");
392 }
393 }
394 }
395
396 static void get_symbol_str(struct gstr *r, struct symbol *sym)
397 {
398 bool hit;
399 struct property *prop;
400
401 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
402 sym_get_string_value(sym));
403 for_all_prompts(sym, prop)
404 get_prompt_str(r, prop);
405 hit = false;
406 for_all_properties(sym, prop, P_SELECT) {
407 if (!hit) {
408 str_append(r, " Selects: ");
409 hit = true;
410 } else
411 str_printf(r, " && ");
412 expr_gstr_print(prop->expr, r);
413 }
414 if (hit)
415 str_append(r, "\n");
416 if (sym->rev_dep.expr) {
417 str_append(r, " Selected by: ");
418 expr_gstr_print(sym->rev_dep.expr, r);
419 str_append(r, "\n");
420 }
421 str_append(r, "\n\n");
422 }
423
424 static struct gstr get_relations_str(struct symbol **sym_arr)
425 {
426 struct symbol *sym;
427 struct gstr res = str_new();
428 int i;
429
430 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
431 get_symbol_str(&res, sym);
432 if (!i)
433 str_append(&res, "No matches found.\n");
434 return res;
435 }
436
437 pid_t pid;
438
439 static void winch_handler(int sig)
440 {
441 if (!do_resize) {
442 kill(pid, SIGINT);
443 do_resize = 1;
444 }
445 }
446
447 static int exec_conf(void)
448 {
449 int pipefd[2], stat, size;
450 struct sigaction sa;
451 sigset_t sset, osset;
452
453 sigemptyset(&sset);
454 sigaddset(&sset, SIGINT);
455 sigprocmask(SIG_BLOCK, &sset, &osset);
456
457 signal(SIGINT, SIG_DFL);
458
459 sa.sa_handler = winch_handler;
460 sigemptyset(&sa.sa_mask);
461 sa.sa_flags = SA_RESTART;
462 sigaction(SIGWINCH, &sa, NULL);
463
464 *argptr++ = NULL;
465
466 pipe(pipefd);
467 pid = fork();
468 if (pid == 0) {
469 sigprocmask(SIG_SETMASK, &osset, NULL);
470 dup2(pipefd[1], 2);
471 close(pipefd[0]);
472 close(pipefd[1]);
473 execv(args[0], args);
474 _exit(EXIT_FAILURE);
475 }
476
477 close(pipefd[1]);
478 bufptr = input_buf;
479 while (1) {
480 size = input_buf + sizeof(input_buf) - bufptr;
481 size = read(pipefd[0], bufptr, size);
482 if (size <= 0) {
483 if (size < 0) {
484 if (errno == EINTR || errno == EAGAIN)
485 continue;
486 perror("read");
487 }
488 break;
489 }
490 bufptr += size;
491 }
492 *bufptr++ = 0;
493 close(pipefd[0]);
494 waitpid(pid, &stat, 0);
495
496 if (do_resize) {
497 init_wsize();
498 do_resize = 0;
499 sigprocmask(SIG_SETMASK, &osset, NULL);
500 return -1;
501 }
502 if (WIFSIGNALED(stat)) {
503 printf("\finterrupted(%d)\n", WTERMSIG(stat));
504 exit(1);
505 }
506 #if 0
507 printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
508 sleep(1);
509 #endif
510 sigpending(&sset);
511 if (sigismember(&sset, SIGINT)) {
512 printf("\finterrupted\n");
513 exit(1);
514 }
515 sigprocmask(SIG_SETMASK, &osset, NULL);
516
517 return WEXITSTATUS(stat);
518 }
519
520 static void search_conf(void)
521 {
522 struct symbol **sym_arr;
523 int stat;
524 struct gstr res;
525
526 again:
527 cprint_init();
528 cprint("--title");
529 cprint("Search Configuration Parameter");
530 cprint("--inputbox");
531 cprint("Enter Keyword");
532 cprint("10");
533 cprint("75");
534 cprint("");
535 stat = exec_conf();
536 if (stat < 0)
537 goto again;
538 switch (stat) {
539 case 0:
540 break;
541 case 1:
542 show_helptext("Search Configuration", search_help);
543 goto again;
544 default:
545 return;
546 }
547
548 sym_arr = sym_re_search(input_buf);
549 res = get_relations_str(sym_arr);
550 free(sym_arr);
551 show_textbox("Search Results", str_get(&res), 0, 0);
552 str_free(&res);
553 }
554
555 static void build_conf(struct menu *menu)
556 {
557 struct symbol *sym;
558 struct property *prop;
559 struct menu *child;
560 int type, tmp, doint = 2;
561 tristate val;
562 char ch;
563
564 if (!menu_is_visible(menu))
565 return;
566
567 sym = menu->sym;
568 prop = menu->prompt;
569 if (!sym) {
570 if (prop && menu != current_menu) {
571 const char *prompt = menu_get_prompt(menu);
572 switch (prop->type) {
573 case P_MENU:
574 child_count++;
575 cprint("m%p", menu);
576
577 if (single_menu_mode) {
578 cprint1("%s%*c%s",
579 menu->data ? "-->" : "++>",
580 indent + 1, ' ', prompt);
581 } else
582 cprint1(" %*c%s --->", indent + 1, ' ', prompt);
583
584 cprint_done();
585 if (single_menu_mode && menu->data)
586 goto conf_childs;
587 return;
588 default:
589 if (prompt) {
590 child_count++;
591 cprint(":%p", menu);
592 cprint("---%*c%s", indent + 1, ' ', prompt);
593 }
594 }
595 } else
596 doint = 0;
597 goto conf_childs;
598 }
599
600 type = sym_get_type(sym);
601 if (sym_is_choice(sym)) {
602 struct symbol *def_sym = sym_get_choice_value(sym);
603 struct menu *def_menu = NULL;
604
605 child_count++;
606 for (child = menu->list; child; child = child->next) {
607 if (menu_is_visible(child) && child->sym == def_sym)
608 def_menu = child;
609 }
610
611 val = sym_get_tristate_value(sym);
612 if (sym_is_changable(sym)) {
613 cprint("t%p", menu);
614 switch (type) {
615 case S_BOOLEAN:
616 cprint1("[%c]", val == no ? ' ' : '*');
617 break;
618 case S_TRISTATE:
619 switch (val) {
620 case yes: ch = '*'; break;
621 case mod: ch = 'M'; break;
622 default: ch = ' '; break;
623 }
624 cprint1("<%c>", ch);
625 break;
626 }
627 } else {
628 cprint("%c%p", def_menu ? 't' : ':', menu);
629 cprint1(" ");
630 }
631
632 cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
633 if (val == yes) {
634 if (def_menu) {
635 cprint1(" (%s)", menu_get_prompt(def_menu));
636 cprint1(" --->");
637 cprint_done();
638 if (def_menu->list) {
639 indent += 2;
640 build_conf(def_menu);
641 indent -= 2;
642 }
643 } else
644 cprint_done();
645 return;
646 }
647 cprint_done();
648 } else {
649 if (menu == current_menu) {
650 cprint(":%p", menu);
651 cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
652 goto conf_childs;
653 }
654 child_count++;
655 val = sym_get_tristate_value(sym);
656 if (sym_is_choice_value(sym) && val == yes) {
657 cprint(":%p", menu);
658 cprint1(" ");
659 } else {
660 switch (type) {
661 case S_BOOLEAN:
662 cprint("t%p", menu);
663 if (sym_is_changable(sym))
664 cprint1("[%c]", val == no ? ' ' : '*');
665 else
666 cprint1("---");
667 break;
668 case S_TRISTATE:
669 cprint("t%p", menu);
670 switch (val) {
671 case yes: ch = '*'; break;
672 case mod: ch = 'M'; break;
673 default: ch = ' '; break;
674 }
675 if (sym_is_changable(sym))
676 cprint1("<%c>", ch);
677 else
678 cprint1("---");
679 break;
680 default:
681 cprint("s%p", menu);
682 tmp = cprint1("(%s)", sym_get_string_value(sym));
683 tmp = indent - tmp + 4;
684 if (tmp < 0)
685 tmp = 0;
686 cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
687 (sym_has_value(sym) || !sym_is_changable(sym)) ?
688 "" : " (NEW)");
689 cprint_done();
690 goto conf_childs;
691 }
692 }
693 cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
694 (sym_has_value(sym) || !sym_is_changable(sym)) ?
695 "" : " (NEW)");
696 if (menu->prompt->type == P_MENU) {
697 cprint1(" --->");
698 cprint_done();
699 return;
700 }
701 cprint_done();
702 }
703
704 conf_childs:
705 indent += doint;
706 for (child = menu->list; child; child = child->next)
707 build_conf(child);
708 indent -= doint;
709 }
710
711 static void conf(struct menu *menu)
712 {
713 struct menu *submenu;
714 const char *prompt = menu_get_prompt(menu);
715 struct symbol *sym;
716 char active_entry[40];
717 int stat, type, i;
718
719 unlink("lxdialog.scrltmp");
720 active_entry[0] = 0;
721 while (1) {
722 cprint_init();
723 cprint("--title");
724 cprint("%s", prompt ? prompt : "Main Menu");
725 cprint("--menu");
726 cprint(menu_instructions);
727 cprint("%d", rows);
728 cprint("%d", cols);
729 cprint("%d", rows - 10);
730 cprint("%s", active_entry);
731 current_menu = menu;
732 build_conf(menu);
733 if (!child_count)
734 break;
735 if (menu == &rootmenu) {
736 cprint(":");
737 cprint("--- ");
738 cprint("L");
739 cprint(" Load an Alternate Configuration File");
740 cprint("S");
741 cprint(" Save Configuration to an Alternate File");
742 }
743 stat = exec_conf();
744 if (stat < 0)
745 continue;
746
747 if (stat == 1 || stat == 255)
748 break;
749
750 type = input_buf[0];
751 if (!type)
752 continue;
753
754 for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
755 ;
756 if (i >= sizeof(active_entry))
757 i = sizeof(active_entry) - 1;
758 input_buf[i] = 0;
759 strcpy(active_entry, input_buf);
760
761 sym = NULL;
762 submenu = NULL;
763 if (sscanf(input_buf + 1, "%p", &submenu) == 1)
764 sym = submenu->sym;
765
766 switch (stat) {
767 case 0:
768 switch (type) {
769 case 'm':
770 if (single_menu_mode)
771 submenu->data = (void *) (long) !submenu->data;
772 else
773 conf(submenu);
774 break;
775 case 't':
776 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
777 conf_choice(submenu);
778 else if (submenu->prompt->type == P_MENU)
779 conf(submenu);
780 break;
781 case 's':
782 conf_string(submenu);
783 break;
784 case 'L':
785 conf_load();
786 break;
787 case 'S':
788 conf_save();
789 break;
790 }
791 break;
792 case 2:
793 if (sym)
794 show_help(submenu);
795 else
796 show_helptext("README", mconf_readme);
797 break;
798 case 3:
799 if (type == 't') {
800 if (sym_set_tristate_value(sym, yes))
801 break;
802 if (sym_set_tristate_value(sym, mod))
803 show_textbox(NULL, setmod_text, 6, 74);
804 }
805 break;
806 case 4:
807 if (type == 't')
808 sym_set_tristate_value(sym, no);
809 break;
810 case 5:
811 if (type == 't')
812 sym_set_tristate_value(sym, mod);
813 break;
814 case 6:
815 if (type == 't')
816 sym_toggle_tristate_value(sym);
817 else if (type == 'm')
818 conf(submenu);
819 break;
820 case 7:
821 search_conf();
822 break;
823 }
824 }
825 }
826
827 static void show_textbox(const char *title, const char *text, int r, int c)
828 {
829 int fd;
830
831 fd = creat(".help.tmp", 0777);
832 write(fd, text, strlen(text));
833 close(fd);
834 show_file(".help.tmp", title, r, c);
835 unlink(".help.tmp");
836 }
837
838 static void show_helptext(const char *title, const char *text)
839 {
840 show_textbox(title, text, 0, 0);
841 }
842
843 static void show_help(struct menu *menu)
844 {
845 struct gstr help = str_new();
846 struct symbol *sym = menu->sym;
847
848 if (sym->help)
849 {
850 if (sym->name) {
851 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
852 str_append(&help, sym->help);
853 str_append(&help, "\n");
854 }
855 } else {
856 str_append(&help, nohelp_text);
857 }
858 get_symbol_str(&help, sym);
859 show_helptext(menu_get_prompt(menu), str_get(&help));
860 str_free(&help);
861 }
862
863 static void show_file(const char *filename, const char *title, int r, int c)
864 {
865 do {
866 cprint_init();
867 if (title) {
868 cprint("--title");
869 cprint("%s", title);
870 }
871 cprint("--textbox");
872 cprint("%s", filename);
873 cprint("%d", r ? r : rows);
874 cprint("%d", c ? c : cols);
875 } while (exec_conf() < 0);
876 }
877
878 static void conf_choice(struct menu *menu)
879 {
880 const char *prompt = menu_get_prompt(menu);
881 struct menu *child;
882 struct symbol *active;
883 int stat;
884
885 active = sym_get_choice_value(menu->sym);
886 while (1) {
887 cprint_init();
888 cprint("--title");
889 cprint("%s", prompt ? prompt : "Main Menu");
890 cprint("--radiolist");
891 cprint(radiolist_instructions);
892 cprint("15");
893 cprint("70");
894 cprint("6");
895
896 current_menu = menu;
897 for (child = menu->list; child; child = child->next) {
898 if (!menu_is_visible(child))
899 continue;
900 cprint("%p", child);
901 cprint("%s", menu_get_prompt(child));
902 if (child->sym == sym_get_choice_value(menu->sym))
903 cprint("ON");
904 else if (child->sym == active)
905 cprint("SELECTED");
906 else
907 cprint("OFF");
908 }
909
910 stat = exec_conf();
911 switch (stat) {
912 case 0:
913 if (sscanf(input_buf, "%p", &child) != 1)
914 break;
915 sym_set_tristate_value(child->sym, yes);
916 return;
917 case 1:
918 if (sscanf(input_buf, "%p", &child) == 1) {
919 show_help(child);
920 active = child->sym;
921 } else
922 show_help(menu);
923 break;
924 case 255:
925 return;
926 }
927 }
928 }
929
930 static void conf_string(struct menu *menu)
931 {
932 const char *prompt = menu_get_prompt(menu);
933 int stat;
934
935 while (1) {
936 cprint_init();
937 cprint("--title");
938 cprint("%s", prompt ? prompt : "Main Menu");
939 cprint("--inputbox");
940 switch (sym_get_type(menu->sym)) {
941 case S_INT:
942 cprint(inputbox_instructions_int);
943 break;
944 case S_HEX:
945 cprint(inputbox_instructions_hex);
946 break;
947 case S_STRING:
948 cprint(inputbox_instructions_string);
949 break;
950 default:
951 /* panic? */;
952 }
953 cprint("10");
954 cprint("75");
955 cprint("%s", sym_get_string_value(menu->sym));
956 stat = exec_conf();
957 switch (stat) {
958 case 0:
959 if (sym_set_string_value(menu->sym, input_buf))
960 return;
961 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
962 break;
963 case 1:
964 show_help(menu);
965 break;
966 case 255:
967 return;
968 }
969 }
970 }
971
972 static void conf_load(void)
973 {
974 int stat;
975
976 while (1) {
977 cprint_init();
978 cprint("--inputbox");
979 cprint(load_config_text);
980 cprint("11");
981 cprint("55");
982 cprint("%s", filename);
983 stat = exec_conf();
984 switch(stat) {
985 case 0:
986 if (!input_buf[0])
987 return;
988 if (!conf_read(input_buf))
989 return;
990 show_textbox(NULL, "File does not exist!", 5, 38);
991 break;
992 case 1:
993 show_helptext("Load Alternate Configuration", load_config_help);
994 break;
995 case 255:
996 return;
997 }
998 }
999 }
1000
1001 static void conf_save(void)
1002 {
1003 int stat;
1004
1005 while (1) {
1006 cprint_init();
1007 cprint("--inputbox");
1008 cprint(save_config_text);
1009 cprint("11");
1010 cprint("55");
1011 cprint("%s", filename);
1012 stat = exec_conf();
1013 switch(stat) {
1014 case 0:
1015 if (!input_buf[0])
1016 return;
1017 if (!conf_write(input_buf))
1018 return;
1019 show_textbox(NULL, "Can't create file! Probably a nonexistent directory.", 5, 60);
1020 break;
1021 case 1:
1022 show_helptext("Save Alternate Configuration", save_config_help);
1023 break;
1024 case 255:
1025 return;
1026 }
1027 }
1028 }
1029
1030 static void conf_cleanup(void)
1031 {
1032 tcsetattr(1, TCSAFLUSH, &ios_org);
1033 unlink(".help.tmp");
1034 unlink("lxdialog.scrltmp");
1035 }
1036
1037 int main(int ac, char **av)
1038 {
1039 struct symbol *sym;
1040 char *mode;
1041 int stat;
1042
1043 conf_parse(av[1]);
1044 conf_read(NULL);
1045
1046 sym = sym_lookup("KERNELRELEASE", 0);
1047 sym_calc_value(sym);
1048 sprintf(menu_backtitle, "Linux Kernel v%s Configuration",
1049 sym_get_string_value(sym));
1050
1051 mode = getenv("MENUCONFIG_MODE");
1052 if (mode) {
1053 if (!strcasecmp(mode, "single_menu"))
1054 single_menu_mode = 1;
1055 }
1056
1057 tcgetattr(1, &ios_org);
1058 atexit(conf_cleanup);
1059 init_wsize();
1060 conf(&rootmenu);
1061
1062 do {
1063 cprint_init();
1064 cprint("--yesno");
1065 cprint("Do you wish to save your new kernel configuration?");
1066 cprint("5");
1067 cprint("60");
1068 stat = exec_conf();
1069 } while (stat < 0);
1070
1071 if (stat == 0) {
1072 if (conf_write(NULL)) {
1073 fprintf(stderr, "\n\n"
1074 "Error during writing of the kernel configuration.\n"
1075 "Your kernel configuration changes were NOT saved."
1076 "\n\n");
1077 return 1;
1078 }
1079 printf("\n\n"
1080 "*** End of Linux kernel configuration.\n"
1081 "*** Execute 'make' to build the kernel or try 'make help'."
1082 "\n\n");
1083 } else {
1084 fprintf(stderr, "\n\n"
1085 "Your kernel configuration changes were NOT saved."
1086 "\n\n");
1087 }
1088
1089 return 0;
1090 }
This page took 0.05542 seconds and 6 git commands to generate.