blob: ed22b13f846092fdb9a6843f80ce15b90b1ca293 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07007 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
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>
Jean-Christophe Dubois442ff702005-06-25 14:55:43 -070023#include <locale.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#define LKC_DIRECT_LINK
26#include "lkc.h"
27
28static char menu_backtitle[128];
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070029static const char mconf_readme[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -070030"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"
Sam Ravnborg45897212006-07-24 22:04:04 +0200162"default mode.\n"
163"\n"
164"Different color themes available\n"
165"--------------------------------\n"
166"It is possible to select different color themes using the variable\n"
167"MENUCONFIG_COLOR. To select a theme use:\n"
168"\n"
169"make MENUCONFIG_COLOR=<theme> menuconfig\n"
170"\n"
171"Available themes are\n"
172" mono => selects colors suitable for monochrome displays\n"
173" blackbg => selects a color scheme with black background\n"
174" classic => theme with blue background. The classic look. (default)\n"
175"\n"),
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700176menu_instructions[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 "Arrow keys navigate the menu. "
178 "<Enter> selects submenus --->. "
179 "Highlighted letters are hotkeys. "
180 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
181 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700182 "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
183radiolist_instructions[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 "Use the arrow keys to navigate this window or "
185 "press the hotkey of the item you wish to select "
186 "followed by the <SPACE BAR>. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700187 "Press <?> for additional information about this option."),
188inputbox_instructions_int[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 "Please enter a decimal value. "
190 "Fractions will not be accepted. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700191 "Use the <TAB> key to move from the input field to the buttons below it."),
192inputbox_instructions_hex[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 "Please enter a hexadecimal value. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700194 "Use the <TAB> key to move from the input field to the buttons below it."),
195inputbox_instructions_string[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 "Please enter a string value. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700197 "Use the <TAB> key to move from the input field to the buttons below it."),
198setmod_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 "This feature depends on another which has been configured as a module.\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700200 "As a result, this feature will be built as a module."),
201nohelp_text[] = N_(
202 "There is no help available for this kernel option.\n"),
203load_config_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 "Enter the name of the configuration file you wish to load. "
205 "Accept the name shown to restore the configuration you "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700206 "last retrieved. Leave blank to abort."),
207load_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 "\n"
209 "For various reasons, one may wish to keep several different kernel\n"
210 "configurations available on a single machine.\n"
211 "\n"
212 "If you have saved a previous configuration in a file other than the\n"
213 "kernel's default, entering the name of the file here will allow you\n"
214 "to modify that configuration.\n"
215 "\n"
216 "If you are uncertain, then you have probably never used alternate\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700217 "configuration files. You should therefor leave this blank to abort.\n"),
218save_config_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 "Enter a filename to which this configuration should be saved "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700220 "as an alternate. Leave blank to abort."),
221save_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 "\n"
223 "For various reasons, one may wish to keep different kernel\n"
224 "configurations available on a single machine.\n"
225 "\n"
226 "Entering a file name here will allow you to later retrieve, modify\n"
227 "and use the current configuration as an alternate to whatever\n"
228 "configuration options you have selected at that time.\n"
229 "\n"
230 "If you are uncertain what all this means then you should probably\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700231 "leave this blank.\n"),
232search_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 "\n"
234 "Search for CONFIG_ symbols and display their relations.\n"
Randy Dunlap503af332005-10-30 15:02:15 -0800235 "Regular expressions are allowed.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 "Example: search for \"^FOO\"\n"
237 "Result:\n"
238 "-----------------------------------------------------------------\n"
239 "Symbol: FOO [=m]\n"
240 "Prompt: Foo bus is used to drive the bar HW\n"
241 "Defined at drivers/pci/Kconfig:47\n"
242 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
243 "Location:\n"
244 " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
245 " -> PCI support (PCI [=y])\n"
246 " -> PCI access mode (<choice> [=y])\n"
247 "Selects: LIBCRC32\n"
248 "Selected by: BAR\n"
249 "-----------------------------------------------------------------\n"
250 "o The line 'Prompt:' shows the text used in the menu structure for\n"
251 " this CONFIG_ symbol\n"
252 "o The 'Defined at' line tell at what file / line number the symbol\n"
253 " is defined\n"
254 "o The 'Depends on:' line tell what symbols needs to be defined for\n"
255 " this symbol to be visible in the menu (selectable)\n"
256 "o The 'Location:' lines tell where in the menu structure this symbol\n"
257 " is located\n"
258 " A location followed by a [=y] indicate that this is a selectable\n"
259 " menu item - and current value is displayed inside brackets.\n"
260 "o The 'Selects:' line tell what symbol will be automatically\n"
261 " selected if this symbol is selected (y or m)\n"
262 "o The 'Selected by' line tell what symbol has selected this symbol\n"
263 "\n"
264 "Only relevant lines are shown.\n"
265 "\n\n"
266 "Search examples:\n"
267 "Examples: USB => find all CONFIG_ symbols containing USB\n"
268 " ^USB => find all CONFIG_ symbols starting with USB\n"
269 " USB$ => find all CONFIG_ symbols ending with USB\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700270 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
J.A. Magallon48b9d032005-06-25 14:59:22 -0700272static char buf[4096], *bufptr = buf;
273static char input_buf[4096];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274static char filename[PATH_MAX+1] = ".config";
275static char *args[1024], **argptr = args;
276static int indent;
277static struct termios ios_org;
278static int rows = 0, cols = 0;
279static struct menu *current_menu;
280static int child_count;
281static int do_resize;
282static int single_menu_mode;
283
284static void conf(struct menu *menu);
285static void conf_choice(struct menu *menu);
286static void conf_string(struct menu *menu);
287static void conf_load(void);
288static void conf_save(void);
289static void show_textbox(const char *title, const char *text, int r, int c);
290static void show_helptext(const char *title, const char *text);
291static void show_help(struct menu *menu);
292static void show_file(const char *filename, const char *title, int r, int c);
293
294static void cprint_init(void);
295static int cprint1(const char *fmt, ...);
296static void cprint_done(void);
297static int cprint(const char *fmt, ...);
298
299static void init_wsize(void)
300{
301 struct winsize ws;
302 char *env;
303
304 if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
305 rows = ws.ws_row;
306 cols = ws.ws_col;
307 }
308
309 if (!rows) {
310 env = getenv("LINES");
311 if (env)
312 rows = atoi(env);
313 if (!rows)
314 rows = 24;
315 }
316 if (!cols) {
317 env = getenv("COLUMNS");
318 if (env)
319 cols = atoi(env);
320 if (!cols)
321 cols = 80;
322 }
323
324 if (rows < 19 || cols < 80) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700325 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
326 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 exit(1);
328 }
329
330 rows -= 4;
331 cols -= 5;
332}
333
334static void cprint_init(void)
335{
336 bufptr = buf;
337 argptr = args;
338 memset(args, 0, sizeof(args));
339 indent = 0;
340 child_count = 0;
Sam Ravnborg6f6046c2005-12-16 21:35:19 +0100341 cprint("./scripts/kconfig/lxdialog/lxdialog");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 cprint("--backtitle");
343 cprint(menu_backtitle);
344}
345
346static int cprint1(const char *fmt, ...)
347{
348 va_list ap;
349 int res;
350
351 if (!*argptr)
352 *argptr = bufptr;
353 va_start(ap, fmt);
354 res = vsprintf(bufptr, fmt, ap);
355 va_end(ap);
356 bufptr += res;
357
358 return res;
359}
360
361static void cprint_done(void)
362{
363 *bufptr++ = 0;
364 argptr++;
365}
366
367static int cprint(const char *fmt, ...)
368{
369 va_list ap;
370 int res;
371
372 *argptr++ = bufptr;
373 va_start(ap, fmt);
374 res = vsprintf(bufptr, fmt, ap);
375 va_end(ap);
376 bufptr += res;
377 *bufptr++ = 0;
378
379 return res;
380}
381
382static void get_prompt_str(struct gstr *r, struct property *prop)
383{
384 int i, j;
385 struct menu *submenu[8], *menu;
386
387 str_printf(r, "Prompt: %s\n", prop->text);
388 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
389 prop->menu->lineno);
390 if (!expr_is_yes(prop->visible.expr)) {
391 str_append(r, " Depends on: ");
392 expr_gstr_print(prop->visible.expr, r);
393 str_append(r, "\n");
394 }
395 menu = prop->menu->parent;
396 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
397 submenu[i++] = menu;
398 if (i > 0) {
399 str_printf(r, " Location:\n");
400 for (j = 4; --i >= 0; j += 2) {
401 menu = submenu[i];
402 str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
403 if (menu->sym) {
404 str_printf(r, " (%s [=%s])", menu->sym->name ?
405 menu->sym->name : "<choice>",
406 sym_get_string_value(menu->sym));
407 }
408 str_append(r, "\n");
409 }
410 }
411}
412
413static void get_symbol_str(struct gstr *r, struct symbol *sym)
414{
415 bool hit;
416 struct property *prop;
417
418 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
419 sym_get_string_value(sym));
420 for_all_prompts(sym, prop)
421 get_prompt_str(r, prop);
422 hit = false;
423 for_all_properties(sym, prop, P_SELECT) {
424 if (!hit) {
425 str_append(r, " Selects: ");
426 hit = true;
427 } else
428 str_printf(r, " && ");
429 expr_gstr_print(prop->expr, r);
430 }
431 if (hit)
432 str_append(r, "\n");
433 if (sym->rev_dep.expr) {
434 str_append(r, " Selected by: ");
435 expr_gstr_print(sym->rev_dep.expr, r);
436 str_append(r, "\n");
437 }
438 str_append(r, "\n\n");
439}
440
441static struct gstr get_relations_str(struct symbol **sym_arr)
442{
443 struct symbol *sym;
444 struct gstr res = str_new();
445 int i;
446
447 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
448 get_symbol_str(&res, sym);
449 if (!i)
450 str_append(&res, "No matches found.\n");
451 return res;
452}
453
454pid_t pid;
455
456static void winch_handler(int sig)
457{
458 if (!do_resize) {
459 kill(pid, SIGINT);
460 do_resize = 1;
461 }
462}
463
464static int exec_conf(void)
465{
466 int pipefd[2], stat, size;
467 struct sigaction sa;
468 sigset_t sset, osset;
469
470 sigemptyset(&sset);
471 sigaddset(&sset, SIGINT);
472 sigprocmask(SIG_BLOCK, &sset, &osset);
473
474 signal(SIGINT, SIG_DFL);
475
476 sa.sa_handler = winch_handler;
477 sigemptyset(&sa.sa_mask);
478 sa.sa_flags = SA_RESTART;
479 sigaction(SIGWINCH, &sa, NULL);
480
481 *argptr++ = NULL;
482
483 pipe(pipefd);
484 pid = fork();
485 if (pid == 0) {
486 sigprocmask(SIG_SETMASK, &osset, NULL);
487 dup2(pipefd[1], 2);
488 close(pipefd[0]);
489 close(pipefd[1]);
490 execv(args[0], args);
491 _exit(EXIT_FAILURE);
492 }
493
494 close(pipefd[1]);
495 bufptr = input_buf;
496 while (1) {
497 size = input_buf + sizeof(input_buf) - bufptr;
498 size = read(pipefd[0], bufptr, size);
499 if (size <= 0) {
500 if (size < 0) {
501 if (errno == EINTR || errno == EAGAIN)
502 continue;
503 perror("read");
504 }
505 break;
506 }
507 bufptr += size;
508 }
509 *bufptr++ = 0;
510 close(pipefd[0]);
511 waitpid(pid, &stat, 0);
512
513 if (do_resize) {
514 init_wsize();
515 do_resize = 0;
516 sigprocmask(SIG_SETMASK, &osset, NULL);
517 return -1;
518 }
519 if (WIFSIGNALED(stat)) {
520 printf("\finterrupted(%d)\n", WTERMSIG(stat));
521 exit(1);
522 }
523#if 0
524 printf("\fexit state: %d\nexit data: '%s'\n", WEXITSTATUS(stat), input_buf);
525 sleep(1);
526#endif
527 sigpending(&sset);
528 if (sigismember(&sset, SIGINT)) {
529 printf("\finterrupted\n");
530 exit(1);
531 }
532 sigprocmask(SIG_SETMASK, &osset, NULL);
533
534 return WEXITSTATUS(stat);
535}
536
537static void search_conf(void)
538{
539 struct symbol **sym_arr;
540 int stat;
541 struct gstr res;
542
543again:
544 cprint_init();
545 cprint("--title");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700546 cprint(_("Search Configuration Parameter"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 cprint("--inputbox");
Randy Dunlap503af332005-10-30 15:02:15 -0800548 cprint(_("Enter CONFIG_ (sub)string to search for (omit CONFIG_)"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 cprint("10");
550 cprint("75");
551 cprint("");
552 stat = exec_conf();
553 if (stat < 0)
554 goto again;
555 switch (stat) {
556 case 0:
557 break;
558 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700559 show_helptext(_("Search Configuration"), search_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 goto again;
561 default:
562 return;
563 }
564
565 sym_arr = sym_re_search(input_buf);
566 res = get_relations_str(sym_arr);
567 free(sym_arr);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700568 show_textbox(_("Search Results"), str_get(&res), 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 str_free(&res);
570}
571
572static void build_conf(struct menu *menu)
573{
574 struct symbol *sym;
575 struct property *prop;
576 struct menu *child;
577 int type, tmp, doint = 2;
578 tristate val;
579 char ch;
580
581 if (!menu_is_visible(menu))
582 return;
583
584 sym = menu->sym;
585 prop = menu->prompt;
586 if (!sym) {
587 if (prop && menu != current_menu) {
588 const char *prompt = menu_get_prompt(menu);
589 switch (prop->type) {
590 case P_MENU:
591 child_count++;
592 cprint("m%p", menu);
593
594 if (single_menu_mode) {
595 cprint1("%s%*c%s",
596 menu->data ? "-->" : "++>",
597 indent + 1, ' ', prompt);
598 } else
599 cprint1(" %*c%s --->", indent + 1, ' ', prompt);
600
601 cprint_done();
602 if (single_menu_mode && menu->data)
603 goto conf_childs;
604 return;
605 default:
606 if (prompt) {
607 child_count++;
608 cprint(":%p", menu);
609 cprint("---%*c%s", indent + 1, ' ', prompt);
610 }
611 }
612 } else
613 doint = 0;
614 goto conf_childs;
615 }
616
617 type = sym_get_type(sym);
618 if (sym_is_choice(sym)) {
619 struct symbol *def_sym = sym_get_choice_value(sym);
620 struct menu *def_menu = NULL;
621
622 child_count++;
623 for (child = menu->list; child; child = child->next) {
624 if (menu_is_visible(child) && child->sym == def_sym)
625 def_menu = child;
626 }
627
628 val = sym_get_tristate_value(sym);
629 if (sym_is_changable(sym)) {
630 cprint("t%p", menu);
631 switch (type) {
632 case S_BOOLEAN:
633 cprint1("[%c]", val == no ? ' ' : '*');
634 break;
635 case S_TRISTATE:
636 switch (val) {
637 case yes: ch = '*'; break;
638 case mod: ch = 'M'; break;
639 default: ch = ' '; break;
640 }
641 cprint1("<%c>", ch);
642 break;
643 }
644 } else {
645 cprint("%c%p", def_menu ? 't' : ':', menu);
646 cprint1(" ");
647 }
648
649 cprint1("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
650 if (val == yes) {
651 if (def_menu) {
652 cprint1(" (%s)", menu_get_prompt(def_menu));
653 cprint1(" --->");
654 cprint_done();
655 if (def_menu->list) {
656 indent += 2;
657 build_conf(def_menu);
658 indent -= 2;
659 }
660 } else
661 cprint_done();
662 return;
663 }
664 cprint_done();
665 } else {
666 if (menu == current_menu) {
667 cprint(":%p", menu);
668 cprint("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
669 goto conf_childs;
670 }
671 child_count++;
672 val = sym_get_tristate_value(sym);
673 if (sym_is_choice_value(sym) && val == yes) {
674 cprint(":%p", menu);
675 cprint1(" ");
676 } else {
677 switch (type) {
678 case S_BOOLEAN:
679 cprint("t%p", menu);
680 if (sym_is_changable(sym))
681 cprint1("[%c]", val == no ? ' ' : '*');
682 else
683 cprint1("---");
684 break;
685 case S_TRISTATE:
686 cprint("t%p", menu);
687 switch (val) {
688 case yes: ch = '*'; break;
689 case mod: ch = 'M'; break;
690 default: ch = ' '; break;
691 }
692 if (sym_is_changable(sym))
693 cprint1("<%c>", ch);
694 else
695 cprint1("---");
696 break;
697 default:
698 cprint("s%p", menu);
699 tmp = cprint1("(%s)", sym_get_string_value(sym));
700 tmp = indent - tmp + 4;
701 if (tmp < 0)
702 tmp = 0;
703 cprint1("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
704 (sym_has_value(sym) || !sym_is_changable(sym)) ?
705 "" : " (NEW)");
706 cprint_done();
707 goto conf_childs;
708 }
709 }
710 cprint1("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
711 (sym_has_value(sym) || !sym_is_changable(sym)) ?
712 "" : " (NEW)");
713 if (menu->prompt->type == P_MENU) {
714 cprint1(" --->");
715 cprint_done();
716 return;
717 }
718 cprint_done();
719 }
720
721conf_childs:
722 indent += doint;
723 for (child = menu->list; child; child = child->next)
724 build_conf(child);
725 indent -= doint;
726}
727
728static void conf(struct menu *menu)
729{
730 struct menu *submenu;
731 const char *prompt = menu_get_prompt(menu);
732 struct symbol *sym;
733 char active_entry[40];
734 int stat, type, i;
735
736 unlink("lxdialog.scrltmp");
737 active_entry[0] = 0;
738 while (1) {
739 cprint_init();
740 cprint("--title");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700741 cprint("%s", prompt ? prompt : _("Main Menu"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 cprint("--menu");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700743 cprint(_(menu_instructions));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 cprint("%d", rows);
745 cprint("%d", cols);
746 cprint("%d", rows - 10);
747 cprint("%s", active_entry);
748 current_menu = menu;
749 build_conf(menu);
750 if (!child_count)
751 break;
752 if (menu == &rootmenu) {
753 cprint(":");
754 cprint("--- ");
755 cprint("L");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700756 cprint(_(" Load an Alternate Configuration File"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 cprint("S");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700758 cprint(_(" Save Configuration to an Alternate File"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760 stat = exec_conf();
761 if (stat < 0)
762 continue;
763
764 if (stat == 1 || stat == 255)
765 break;
766
767 type = input_buf[0];
768 if (!type)
769 continue;
770
771 for (i = 0; input_buf[i] && !isspace(input_buf[i]); i++)
772 ;
773 if (i >= sizeof(active_entry))
774 i = sizeof(active_entry) - 1;
775 input_buf[i] = 0;
776 strcpy(active_entry, input_buf);
777
778 sym = NULL;
779 submenu = NULL;
780 if (sscanf(input_buf + 1, "%p", &submenu) == 1)
781 sym = submenu->sym;
782
783 switch (stat) {
784 case 0:
785 switch (type) {
786 case 'm':
787 if (single_menu_mode)
788 submenu->data = (void *) (long) !submenu->data;
789 else
790 conf(submenu);
791 break;
792 case 't':
793 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
794 conf_choice(submenu);
795 else if (submenu->prompt->type == P_MENU)
796 conf(submenu);
797 break;
798 case 's':
799 conf_string(submenu);
800 break;
801 case 'L':
802 conf_load();
803 break;
804 case 'S':
805 conf_save();
806 break;
807 }
808 break;
809 case 2:
810 if (sym)
811 show_help(submenu);
812 else
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700813 show_helptext("README", _(mconf_readme));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 break;
815 case 3:
816 if (type == 't') {
817 if (sym_set_tristate_value(sym, yes))
818 break;
819 if (sym_set_tristate_value(sym, mod))
820 show_textbox(NULL, setmod_text, 6, 74);
821 }
822 break;
823 case 4:
824 if (type == 't')
825 sym_set_tristate_value(sym, no);
826 break;
827 case 5:
828 if (type == 't')
829 sym_set_tristate_value(sym, mod);
830 break;
831 case 6:
832 if (type == 't')
833 sym_toggle_tristate_value(sym);
834 else if (type == 'm')
835 conf(submenu);
836 break;
837 case 7:
838 search_conf();
839 break;
840 }
841 }
842}
843
844static void show_textbox(const char *title, const char *text, int r, int c)
845{
846 int fd;
847
848 fd = creat(".help.tmp", 0777);
849 write(fd, text, strlen(text));
850 close(fd);
851 show_file(".help.tmp", title, r, c);
852 unlink(".help.tmp");
853}
854
855static void show_helptext(const char *title, const char *text)
856{
857 show_textbox(title, text, 0, 0);
858}
859
860static void show_help(struct menu *menu)
861{
862 struct gstr help = str_new();
863 struct symbol *sym = menu->sym;
864
865 if (sym->help)
866 {
867 if (sym->name) {
868 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700869 str_append(&help, _(sym->help));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 str_append(&help, "\n");
871 }
872 } else {
873 str_append(&help, nohelp_text);
874 }
875 get_symbol_str(&help, sym);
876 show_helptext(menu_get_prompt(menu), str_get(&help));
877 str_free(&help);
878}
879
880static void show_file(const char *filename, const char *title, int r, int c)
881{
882 do {
883 cprint_init();
884 if (title) {
885 cprint("--title");
886 cprint("%s", title);
887 }
888 cprint("--textbox");
889 cprint("%s", filename);
890 cprint("%d", r ? r : rows);
891 cprint("%d", c ? c : cols);
892 } while (exec_conf() < 0);
893}
894
895static void conf_choice(struct menu *menu)
896{
897 const char *prompt = menu_get_prompt(menu);
898 struct menu *child;
899 struct symbol *active;
900 int stat;
901
902 active = sym_get_choice_value(menu->sym);
903 while (1) {
904 cprint_init();
905 cprint("--title");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700906 cprint("%s", prompt ? prompt : _("Main Menu"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 cprint("--radiolist");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700908 cprint(_(radiolist_instructions));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 cprint("15");
910 cprint("70");
911 cprint("6");
912
913 current_menu = menu;
914 for (child = menu->list; child; child = child->next) {
915 if (!menu_is_visible(child))
916 continue;
917 cprint("%p", child);
918 cprint("%s", menu_get_prompt(child));
919 if (child->sym == sym_get_choice_value(menu->sym))
920 cprint("ON");
921 else if (child->sym == active)
922 cprint("SELECTED");
923 else
924 cprint("OFF");
925 }
926
927 stat = exec_conf();
928 switch (stat) {
929 case 0:
930 if (sscanf(input_buf, "%p", &child) != 1)
931 break;
932 sym_set_tristate_value(child->sym, yes);
933 return;
934 case 1:
935 if (sscanf(input_buf, "%p", &child) == 1) {
936 show_help(child);
937 active = child->sym;
938 } else
939 show_help(menu);
940 break;
941 case 255:
942 return;
943 }
944 }
945}
946
947static void conf_string(struct menu *menu)
948{
949 const char *prompt = menu_get_prompt(menu);
950 int stat;
951
952 while (1) {
953 cprint_init();
954 cprint("--title");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700955 cprint("%s", prompt ? prompt : _("Main Menu"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 cprint("--inputbox");
957 switch (sym_get_type(menu->sym)) {
958 case S_INT:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700959 cprint(_(inputbox_instructions_int));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 break;
961 case S_HEX:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700962 cprint(_(inputbox_instructions_hex));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 break;
964 case S_STRING:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700965 cprint(_(inputbox_instructions_string));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 break;
967 default:
968 /* panic? */;
969 }
970 cprint("10");
971 cprint("75");
972 cprint("%s", sym_get_string_value(menu->sym));
973 stat = exec_conf();
974 switch (stat) {
975 case 0:
976 if (sym_set_string_value(menu->sym, input_buf))
977 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700978 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 break;
980 case 1:
981 show_help(menu);
982 break;
983 case 255:
984 return;
985 }
986 }
987}
988
989static void conf_load(void)
990{
991 int stat;
992
993 while (1) {
994 cprint_init();
995 cprint("--inputbox");
996 cprint(load_config_text);
997 cprint("11");
998 cprint("55");
999 cprint("%s", filename);
1000 stat = exec_conf();
1001 switch(stat) {
1002 case 0:
1003 if (!input_buf[0])
1004 return;
1005 if (!conf_read(input_buf))
1006 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001007 show_textbox(NULL, _("File does not exist!"), 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 break;
1009 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001010 show_helptext(_("Load Alternate Configuration"), load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 break;
1012 case 255:
1013 return;
1014 }
1015 }
1016}
1017
1018static void conf_save(void)
1019{
1020 int stat;
1021
1022 while (1) {
1023 cprint_init();
1024 cprint("--inputbox");
1025 cprint(save_config_text);
1026 cprint("11");
1027 cprint("55");
1028 cprint("%s", filename);
1029 stat = exec_conf();
1030 switch(stat) {
1031 case 0:
1032 if (!input_buf[0])
1033 return;
1034 if (!conf_write(input_buf))
1035 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001036 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 break;
1038 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001039 show_helptext(_("Save Alternate Configuration"), save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 break;
1041 case 255:
1042 return;
1043 }
1044 }
1045}
1046
1047static void conf_cleanup(void)
1048{
1049 tcsetattr(1, TCSAFLUSH, &ios_org);
1050 unlink(".help.tmp");
1051 unlink("lxdialog.scrltmp");
1052}
1053
1054int main(int ac, char **av)
1055{
1056 struct symbol *sym;
1057 char *mode;
1058 int stat;
1059
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001060 setlocale(LC_ALL, "");
1061 bindtextdomain(PACKAGE, LOCALEDIR);
1062 textdomain(PACKAGE);
1063
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 conf_parse(av[1]);
1065 conf_read(NULL);
1066
Sam Ravnborg2244cbd2006-01-16 12:12:12 +01001067 sym = sym_lookup("KERNELVERSION", 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 sym_calc_value(sym);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001069 sprintf(menu_backtitle, _("Linux Kernel v%s Configuration"),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 sym_get_string_value(sym));
1071
1072 mode = getenv("MENUCONFIG_MODE");
1073 if (mode) {
1074 if (!strcasecmp(mode, "single_menu"))
1075 single_menu_mode = 1;
1076 }
1077
1078 tcgetattr(1, &ios_org);
1079 atexit(conf_cleanup);
1080 init_wsize();
1081 conf(&rootmenu);
1082
1083 do {
1084 cprint_init();
1085 cprint("--yesno");
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001086 cprint(_("Do you wish to save your new kernel configuration?"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 cprint("5");
1088 cprint("60");
1089 stat = exec_conf();
1090 } while (stat < 0);
1091
1092 if (stat == 0) {
1093 if (conf_write(NULL)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001094 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 "Error during writing of the kernel configuration.\n"
1096 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001097 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 return 1;
1099 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001100 printf(_("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 "*** End of Linux kernel configuration.\n"
1102 "*** Execute 'make' to build the kernel or try 'make help'."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001103 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 } else {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001105 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07001107 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 }
1109
1110 return 0;
1111}