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