1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
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>
23 #include "lxdialog/dialog.h"
25 static const char mconf_readme
[] =
26 "OpenWrt config is based on Kernel kconfig\n"
27 "so ipkg packages are referred here as modules.\n"
31 "This interface lets you select features and parameters for the build.\n"
32 "Features can either be built-in, modularized, or ignored. Parameters\n"
33 "must be entered in as decimal or hexadecimal numbers or text.\n"
35 "Menu items beginning with following braces represent features that\n"
36 " [ ] can be built in or removed\n"
37 " < > can be built in, modularized or removed\n"
38 " { } can be built in or modularized (selected by other feature)\n"
39 " - - are selected by other feature,\n"
40 "while *, M or whitespace inside braces means to build in, build as\n"
41 "a module or to exclude the feature respectively.\n"
43 "To change any of these features, highlight it with the cursor\n"
44 "keys and press <Y> to build it in, <M> to make it a module or\n"
45 "<N> to remove it. You may also press the <Space Bar> to cycle\n"
46 "through the available options (i.e. Y->N->M->Y).\n"
48 "Some additional keyboard hints:\n"
52 "o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n"
53 " wish to change or the submenu you wish to select and press <Enter>.\n"
54 " Submenus are designated by \"--->\", empty ones by \"----\".\n"
56 " Shortcut: Press the option's highlighted letter (hotkey).\n"
57 " Pressing a hotkey more than once will sequence\n"
58 " through all visible items which use that hotkey.\n"
60 " You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
61 " unseen options into view.\n"
63 "o To exit a menu use the cursor keys to highlight the <Exit> button\n"
64 " and press <ENTER>.\n"
66 " Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
67 " using those letters. You may press a single <ESC>, but\n"
68 " there is a delayed response which you may find annoying.\n"
70 " Also, the <TAB> and cursor keys will cycle between <Select>,\n"
71 " <Exit>, <Help>, <Save>, and <Load>.\n"
73 "o To get help with an item, use the cursor keys to highlight <Help>\n"
74 " and press <ENTER>.\n"
76 " Shortcut: Press <H> or <?>.\n"
78 "o To toggle the display of hidden options, press <Z>.\n"
81 "Radiolists (Choice lists)\n"
83 "o Use the cursor keys to select the option you wish to set and press\n"
84 " <S> or the <SPACE BAR>.\n"
86 " Shortcut: Press the first letter of the option you wish to set then\n"
87 " press <S> or <SPACE BAR>.\n"
89 "o To see available help for the item, use the cursor keys to highlight\n"
90 " <Help> and Press <ENTER>.\n"
92 " Shortcut: Press <H> or <?>.\n"
94 " Also, the <TAB> and cursor keys will cycle between <Select> and\n"
100 "o Enter the requested information and press <ENTER>\n"
101 " If you are entering hexadecimal values, it is not necessary to\n"
102 " add the '0x' prefix to the entry.\n"
104 "o For help, use the <TAB> or cursor keys to highlight the help option\n"
105 " and press <ENTER>. You can try <TAB><H> as well.\n"
108 "Text Box (Help Window)\n"
110 "o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
111 " keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
112 " those who are familiar with less and lynx.\n"
114 "o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
117 "Alternate Configuration Files\n"
118 "-----------------------------\n"
119 "Menuconfig supports the use of alternate configuration files for\n"
120 "those who, for various reasons, find it necessary to switch\n"
121 "between different configurations.\n"
123 "The <Save> button will let you save the current configuration to\n"
124 "a file of your choosing. Use the <Load> button to load a previously\n"
125 "saved alternate configuration.\n"
127 "Even if you don't use alternate configuration files, but you find\n"
128 "during a Menuconfig session that you have completely messed up your\n"
129 "settings, you may use the <Load> button to restore your previously\n"
130 "saved settings from \".config\" without restarting Menuconfig.\n"
132 "Other information\n"
133 "-----------------\n"
134 "If you use Menuconfig in an XTERM window, make sure you have your\n"
135 "$TERM variable set to point to an xterm definition which supports\n"
136 "color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
137 "not display correctly in an RXVT window because rxvt displays only one\n"
138 "intensity of color, bright.\n"
140 "Menuconfig will display larger menus on screens or xterms which are\n"
141 "set to display more than the standard 25 row by 80 column geometry.\n"
142 "In order for this to work, the \"stty size\" command must be able to\n"
143 "display the screen's current row and column geometry. I STRONGLY\n"
144 "RECOMMEND that you make sure you do NOT have the shell variables\n"
145 "LINES and COLUMNS exported into your environment. Some distributions\n"
146 "export those variables via /etc/profile. Some ncurses programs can\n"
147 "become confused when those variables (LINES & COLUMNS) don't reflect\n"
148 "the true screen size.\n"
150 "Optional personality available\n"
151 "------------------------------\n"
152 "If you prefer to have all of the options listed in a single menu,\n"
153 "rather than the default multimenu hierarchy, run the menuconfig with\n"
154 "MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
156 "make MENUCONFIG_MODE=single_menu menuconfig\n"
158 "<Enter> will then unroll the appropriate category, or enfold it if it\n"
159 "is already unrolled.\n"
161 "Note that this mode can eventually be a little more CPU expensive\n"
162 "(especially with a larger number of unrolled categories) than the\n"
165 "Different color themes available\n"
166 "--------------------------------\n"
167 "It is possible to select different color themes using the variable\n"
168 "MENUCONFIG_COLOR. To select a theme use:\n"
170 "make MENUCONFIG_COLOR=<theme> menuconfig\n"
172 "Available themes are\n"
173 " mono => selects colors suitable for monochrome displays\n"
174 " blackbg => selects a color scheme with black background\n"
175 " classic => theme with blue background. The classic look\n"
176 " bluetitle => an LCD friendly version of classic. (default)\n"
178 menu_instructions
[] =
179 "Arrow keys navigate the menu. "
180 "<Enter> selects submenus ---> (or empty submenus ----). "
181 "Highlighted letters are hotkeys. "
182 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
183 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
184 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
185 radiolist_instructions
[] =
186 "Use the arrow keys to navigate this window or "
187 "press the hotkey of the item you wish to select "
188 "followed by the <SPACE BAR>. "
189 "Press <?> for additional information about this option.",
190 inputbox_instructions_int
[] =
191 "Please enter a decimal value. "
192 "Fractions will not be accepted. "
193 "Use the <TAB> key to move from the input field to the buttons below it.",
194 inputbox_instructions_hex
[] =
195 "Please enter a hexadecimal value. "
196 "Use the <TAB> key to move from the input field to the buttons below it.",
197 inputbox_instructions_string
[] =
198 "Please enter a string value. "
199 "Use the <TAB> key to move from the input field to the buttons below it.",
201 "This feature depends on another which has been configured as a module.\n"
202 "As a result, this feature will be built as a module.",
204 "Enter the name of the configuration file you wish to load. "
205 "Accept the name shown to restore the configuration you "
206 "last retrieved. Leave blank to abort.",
209 "For various reasons, one may wish to keep several different\n"
210 "configurations available on a single machine.\n"
212 "If you have saved a previous configuration in a file other than the\n"
213 "default one, entering its name here will allow you to modify that\n"
216 "If you are uncertain, then you have probably never used alternate\n"
217 "configuration files. You should therefore leave this blank to abort.\n",
219 "Enter a filename to which this configuration should be saved "
220 "as an alternate. Leave blank to abort.",
223 "For various reasons, one may wish to keep different configurations\n"
224 "available on a single machine.\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"
230 "If you are uncertain what all this means then you should probably\n"
231 "leave this blank.\n",
234 "Search for symbols and display their relations.\n"
235 "Regular expressions are allowed.\n"
236 "Example: search for \"^FOO\"\n"
238 "-----------------------------------------------------------------\n"
241 "Prompt: Foo bus is used to drive the bar HW\n"
243 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
244 " -> PCI support (PCI [=y])\n"
245 "(1) -> PCI access mode (<choice> [=y])\n"
246 " Defined at drivers/pci/Kconfig:47\n"
247 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
248 " Selects: LIBCRC32\n"
249 " Selected by: BAR [=n]\n"
250 "-----------------------------------------------------------------\n"
251 "o The line 'Type:' shows the type of the configuration option for\n"
252 " this symbol (bool, tristate, string, ...)\n"
253 "o The line 'Prompt:' shows the text used in the menu structure for\n"
255 "o The 'Defined at' line tells at what file / line number the symbol\n"
257 "o The 'Depends on:' line tells what symbols need to be defined for\n"
258 " this symbol to be visible in the menu (selectable)\n"
259 "o The 'Location:' lines tells where in the menu structure this symbol\n"
261 " A location followed by a [=y] indicates that this is a\n"
262 " selectable menu item - and the current value is displayed inside\n"
264 " Press the key in the (#) prefix to jump directly to that\n"
265 " location. You will be returned to the current search results\n"
266 " after exiting this new menu.\n"
267 "o The 'Selects:' line tells what symbols will be automatically\n"
268 " selected if this symbol is selected (y or m)\n"
269 "o The 'Selected by' line tells what symbol has selected this symbol\n"
271 "Only relevant lines are shown.\n"
274 "Examples: USB => find all symbols containing USB\n"
275 " ^USB => find all symbols starting with USB\n"
276 " USB$ => find all symbols ending with USB\n"
280 static struct menu
*current_menu
;
281 static int child_count
;
282 static int single_menu_mode
;
283 static int show_all_options
;
284 static int save_and_exit
;
287 static void conf(struct menu
*menu
, struct menu
*active_menu
);
288 static void conf_choice(struct menu
*menu
);
289 static void conf_string(struct menu
*menu
);
290 static void conf_load(void);
291 static void conf_save(void);
292 static int show_textbox_ext(const char *title
, char *text
, int r
, int c
,
293 int *keys
, int *vscroll
, int *hscroll
,
294 update_text_fn update_text
, void *data
);
295 static void show_textbox(const char *title
, const char *text
, int r
, int c
);
296 static void show_helptext(const char *title
, const char *text
);
297 static void show_help(struct menu
*menu
);
299 static char filename
[PATH_MAX
+1];
300 static void set_config_filename(const char *config_filename
)
302 static char menu_backtitle
[PATH_MAX
+128];
305 size
= snprintf(menu_backtitle
, sizeof(menu_backtitle
),
306 "%s - %s", config_filename
, rootmenu
.prompt
->text
);
307 if (size
>= sizeof(menu_backtitle
))
308 menu_backtitle
[sizeof(menu_backtitle
)-1] = '\0';
309 set_dialog_backtitle(menu_backtitle
);
311 size
= snprintf(filename
, sizeof(filename
), "%s", config_filename
);
312 if (size
>= sizeof(filename
))
313 filename
[sizeof(filename
)-1] = '\0';
316 struct subtitle_part
{
317 struct list_head entries
;
320 static LIST_HEAD(trail
);
322 static struct subtitle_list
*subtitles
;
323 static void set_subtitle(void)
325 struct subtitle_part
*sp
;
326 struct subtitle_list
*pos
, *tmp
;
328 for (pos
= subtitles
; pos
!= NULL
; pos
= tmp
) {
334 list_for_each_entry(sp
, &trail
, entries
) {
337 pos
->next
= xcalloc(1, sizeof(*pos
));
340 subtitles
= pos
= xcalloc(1, sizeof(*pos
));
342 pos
->text
= sp
->text
;
346 set_dialog_subtitles(subtitles
);
349 static void reset_subtitle(void)
351 struct subtitle_list
*pos
, *tmp
;
353 for (pos
= subtitles
; pos
!= NULL
; pos
= tmp
) {
358 set_dialog_subtitles(subtitles
);
362 struct list_head
*head
;
363 struct menu
**targets
;
367 static void update_text(char *buf
, size_t start
, size_t end
, void *_data
)
369 struct search_data
*data
= _data
;
370 struct jump_key
*pos
;
373 list_for_each_entry(pos
, data
->head
, entries
) {
374 if (pos
->offset
>= start
&& pos
->offset
< end
) {
378 int key
= '0' + (pos
->index
% JUMP_NB
) + 1;
380 sprintf(header
, "(%c)", key
);
382 data
->targets
[k
] = pos
->target
;
385 sprintf(header
, " ");
388 memcpy(buf
+ pos
->offset
, header
, sizeof(header
) - 1);
394 static void search_conf(void)
396 struct symbol
**sym_arr
;
400 int dres
, vscroll
= 0, hscroll
= 0;
403 struct subtitle_part stpart
;
406 str_printf( &title
, "Enter (sub)string or regexp to search for "
407 "(with or without \"%s\")", CONFIG_
);
411 dres
= dialog_inputbox("Search Configuration Parameter",
418 show_helptext("Search Configuration", search_help
);
425 /* strip the prefix if necessary */
426 dialog_input
= dialog_input_result
;
427 if (strncasecmp(dialog_input_result
, CONFIG_
, strlen(CONFIG_
)) == 0)
428 dialog_input
+= strlen(CONFIG_
);
431 str_printf(&sttext
, "Search (%s)", dialog_input_result
);
432 stpart
.text
= str_get(&sttext
);
433 list_add_tail(&stpart
.entries
, &trail
);
435 sym_arr
= sym_re_search(dialog_input
);
438 struct menu
*targets
[JUMP_NB
];
439 int keys
[JUMP_NB
+ 1], i
;
440 struct search_data data
= {
445 struct jump_key
*pos
, *tmp
;
447 res
= get_relations_str(sym_arr
, &head
);
449 dres
= show_textbox_ext("Search Results", (char *)
450 str_get(&res
), 0, 0, keys
, &vscroll
,
451 &hscroll
, &update_text
, (void *)
454 for (i
= 0; i
< JUMP_NB
&& keys
[i
]; i
++)
455 if (dres
== keys
[i
]) {
456 conf(targets
[i
]->parent
, targets
[i
]);
460 list_for_each_entry_safe(pos
, tmp
, &head
, entries
)
465 list_del(trail
.prev
);
469 static void build_conf(struct menu
*menu
)
472 struct property
*prop
;
474 int type
, tmp
, doint
= 2;
480 * note: menu_is_visible() has side effect that it will
481 * recalc the value of the symbol.
483 visible
= menu_is_visible(menu
);
484 if (show_all_options
&& !menu_has_prompt(menu
))
486 else if (!show_all_options
&& !visible
)
492 if (prop
&& menu
!= current_menu
) {
493 const char *prompt
= menu_get_prompt(menu
);
494 switch (prop
->type
) {
497 if (single_menu_mode
) {
499 menu
->data
? "-->" : "++>",
500 indent
+ 1, ' ', prompt
);
502 item_make(" %*c%s %s",
503 indent
+ 1, ' ', prompt
,
504 menu_is_empty(menu
) ? "----" : "--->");
507 if (single_menu_mode
&& menu
->data
)
513 item_make(" %*c*** %s ***", indent
+ 1, ' ', prompt
);
521 item_make("---%*c%s", indent
+ 1, ' ', prompt
);
531 type
= sym_get_type(sym
);
532 if (sym_is_choice(sym
)) {
533 struct symbol
*def_sym
= sym_get_choice_value(sym
);
534 struct menu
*def_menu
= NULL
;
537 for (child
= menu
->list
; child
; child
= child
->next
) {
538 if (menu_is_visible(child
) && child
->sym
== def_sym
)
542 val
= sym_get_tristate_value(sym
);
543 if (sym_is_changeable(sym
)) {
546 item_make("[%c]", val
== no
? ' ' : '*');
550 case yes
: ch
= '*'; break;
551 case mod
: ch
= 'M'; break;
552 default: ch
= ' '; break;
554 item_make("<%c>", ch
);
561 item_set_tag(def_menu
? 't' : ':');
565 item_add_str("%*c%s", indent
+ 1, ' ', menu_get_prompt(menu
));
568 item_add_str(" (%s)", menu_get_prompt(def_menu
));
569 item_add_str(" --->");
570 if (def_menu
->list
) {
572 build_conf(def_menu
);
579 if (menu
== current_menu
) {
580 item_make("---%*c%s", indent
+ 1, ' ', menu_get_prompt(menu
));
586 val
= sym_get_tristate_value(sym
);
587 if (sym_is_choice_value(sym
) && val
== yes
) {
594 if (sym_is_changeable(sym
))
595 item_make("[%c]", val
== no
? ' ' : '*');
597 item_make("-%c-", val
== no
? ' ' : '*');
603 case yes
: ch
= '*'; break;
604 case mod
: ch
= 'M'; break;
605 default: ch
= ' '; break;
607 if (sym_is_changeable(sym
)) {
608 if (sym
->rev_dep
.tri
== mod
)
609 item_make("{%c}", ch
);
611 item_make("<%c>", ch
);
613 item_make("-%c-", ch
);
618 tmp
= 2 + strlen(sym_get_string_value(sym
)); /* () = 2 */
619 item_make("(%s)", sym_get_string_value(sym
));
620 tmp
= indent
- tmp
+ 4;
623 item_add_str("%*c%s%s", tmp
, ' ', menu_get_prompt(menu
),
624 (sym_has_value(sym
) || !sym_is_changeable(sym
)) ?
631 item_add_str("%*c%s%s", indent
+ 1, ' ', menu_get_prompt(menu
),
632 (sym_has_value(sym
) || !sym_is_changeable(sym
)) ?
634 if (menu
->prompt
->type
== P_MENU
) {
635 item_add_str(" %s", menu_is_empty(menu
) ? "----" : "--->");
642 for (child
= menu
->list
; child
; child
= child
->next
)
647 static void conf(struct menu
*menu
, struct menu
*active_menu
)
649 struct menu
*submenu
;
650 const char *prompt
= menu_get_prompt(menu
);
651 struct subtitle_part stpart
;
656 if (menu
!= &rootmenu
)
657 stpart
.text
= menu_get_prompt(menu
);
660 list_add_tail(&stpart
.entries
, &trail
);
670 res
= dialog_menu(prompt
? prompt
: "Main Menu",
672 active_menu
, &s_scroll
);
673 if (res
== 1 || res
== KEY_ESC
|| res
== -ERRDISPLAYTOOSMALL
)
675 if (item_count() != 0) {
676 if (!item_activate_selected())
681 submenu
= item_data();
682 active_menu
= item_data();
690 switch (item_tag()) {
692 if (single_menu_mode
)
693 submenu
->data
= (void *) (long) !submenu
->data
;
698 if (sym_is_choice(sym
) && sym_get_tristate_value(sym
) == yes
)
699 conf_choice(submenu
);
700 else if (submenu
->prompt
->type
== P_MENU
)
704 conf_string(submenu
);
713 show_helptext("README", mconf_readme
);
725 if (item_is_tag('t')) {
726 if (sym_set_tristate_value(sym
, yes
))
728 if (sym_set_tristate_value(sym
, mod
))
729 show_textbox(NULL
, setmod_text
, 6, 74);
733 if (item_is_tag('t'))
734 sym_set_tristate_value(sym
, no
);
737 if (item_is_tag('t'))
738 sym_set_tristate_value(sym
, mod
);
741 if (item_is_tag('t'))
742 sym_toggle_tristate_value(sym
);
743 else if (item_is_tag('m'))
750 show_all_options
= !show_all_options
;
755 list_del(trail
.prev
);
758 static int show_textbox_ext(const char *title
, char *text
, int r
, int c
, int
759 *keys
, int *vscroll
, int *hscroll
, update_text_fn
760 update_text
, void *data
)
763 return dialog_textbox(title
, text
, r
, c
, keys
, vscroll
, hscroll
,
767 static void show_textbox(const char *title
, const char *text
, int r
, int c
)
769 show_textbox_ext(title
, (char *) text
, r
, c
, (int []) {0}, NULL
, NULL
,
773 static void show_helptext(const char *title
, const char *text
)
775 show_textbox(title
, text
, 0, 0);
778 static void conf_message_callback(const char *s
)
784 show_textbox(NULL
, s
, 6, 60);
788 static void show_help(struct menu
*menu
)
790 struct gstr help
= str_new();
792 help
.max_width
= getmaxx(stdscr
) - 10;
793 menu_get_ext_help(menu
, &help
);
795 show_helptext(menu_get_prompt(menu
), str_get(&help
));
799 static void conf_choice(struct menu
*menu
)
801 const char *prompt
= menu_get_prompt(menu
);
803 struct symbol
*active
;
804 struct property
*prop
;
806 active
= sym_get_choice_value(menu
->sym
);
813 for (child
= menu
->list
; child
; child
= child
->next
) {
814 if (!menu_is_visible(child
))
817 item_make("%s", menu_get_prompt(child
));
819 item_make("*** %s ***", menu_get_prompt(child
));
822 item_set_data(child
);
823 if (child
->sym
== active
)
824 item_set_selected(1);
825 if (child
->sym
== sym_get_choice_value(menu
->sym
))
829 res
= dialog_checklist(prompt
? prompt
: "Main Menu",
830 radiolist_instructions
,
833 CHECKLIST_HEIGTH_MIN
);
834 selected
= item_activate_selected();
842 if (sym_get_tristate_value(child
->sym
) != yes
) {
843 for_all_properties(menu
->sym
, prop
, P_RESET
) {
844 if (expr_calc_value(prop
->visible
.expr
) == no
)
847 conf_reset(S_DEF_USER
);
851 sym_set_tristate_value(child
->sym
, yes
);
864 case -ERRDISPLAYTOOSMALL
:
870 static void conf_string(struct menu
*menu
)
872 const char *prompt
= menu_get_prompt(menu
);
878 switch (sym_get_type(menu
->sym
)) {
880 heading
= inputbox_instructions_int
;
883 heading
= inputbox_instructions_hex
;
886 heading
= inputbox_instructions_string
;
889 heading
= "Internal mconf error!";
892 res
= dialog_inputbox(prompt
? prompt
: "Main Menu",
894 sym_get_string_value(menu
->sym
));
897 if (sym_set_string_value(menu
->sym
, dialog_input_result
))
899 show_textbox(NULL
, "You have made an invalid entry.", 5, 43);
910 static void conf_load(void)
916 res
= dialog_inputbox(NULL
, load_config_text
,
920 if (!dialog_input_result
[0])
922 if (!conf_read(dialog_input_result
)) {
923 set_config_filename(dialog_input_result
);
924 sym_set_change_count(1);
927 show_textbox(NULL
, "File does not exist!", 5, 38);
930 show_helptext("Load Alternate Configuration", load_config_help
);
938 static void conf_save(void)
943 res
= dialog_inputbox(NULL
, save_config_text
,
947 if (!dialog_input_result
[0])
949 if (!conf_write(dialog_input_result
)) {
950 set_config_filename(dialog_input_result
);
953 show_textbox(NULL
, "Can't create file!", 5, 60);
956 show_helptext("Save Alternate Configuration", save_config_help
);
964 static int handle_exit(void)
971 if (conf_get_changed())
972 res
= dialog_yesno(NULL
,
973 "Do you wish to save your new configuration?\n"
974 "(Press <ESC><ESC> to continue kernel configuration.)",
979 end_dialog(saved_x
, saved_y
);
983 if (conf_write(filename
)) {
984 fprintf(stderr
, "\n\n"
985 "Error while writing of the configuration.\n"
986 "Your configuration changes were NOT saved."
990 conf_write_autoconf(0);
995 "*** End of the configuration.\n"
996 "*** Execute 'make' to start the build or try 'make help'."
1002 fprintf(stderr
, "\n\n"
1003 "Your configuration changes were NOT saved."
1012 static void sig_handler(int signo
)
1014 exit(handle_exit());
1017 int main(int ac
, char **av
)
1022 signal(SIGINT
, sig_handler
);
1024 if (ac
> 1 && strcmp(av
[1], "-s") == 0) {
1026 /* Silence conf_read() until the real callback is set up */
1027 conf_set_message_callback(NULL
);
1033 mode
= getenv("MENUCONFIG_MODE");
1035 if (!strcasecmp(mode
, "single_menu"))
1036 single_menu_mode
= 1;
1039 if (init_dialog(NULL
)) {
1040 fprintf(stderr
, "Your display is too small to run Menuconfig!\n");
1041 fprintf(stderr
, "It must be at least 19 lines by 80 columns.\n");
1045 set_config_filename(conf_get_configname());
1046 conf_set_message_callback(conf_message_callback
);
1048 conf(&rootmenu
, NULL
);
1049 res
= handle_exit();
1050 } while (res
== KEY_ESC
);