Home | History | Annotate | Line # | Download | only in sysinst
menus.mi revision 1.27
      1 /*	$NetBSD: menus.mi,v 1.27 2022/07/22 16:51:14 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by David Laight.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Menu system definitions -- machine and language independent
     34  *
     35  * Some menus may be called directly in the code rather than via the
     36  * menu system.
     37  *
     38  *  This file must be first in the sed command line.
     39  *
     40  */
     41 
     42 {
     43 #include <stdio.h>
     44 #include <time.h>
     45 #include <curses.h>
     46 #include "defs.h"
     47 #include "md.h"
     48 #include "msg_defs.h"
     49 #include "menu_defs.h"
     50 
     51 static menudesc menu_def[];
     52 
     53 static void
     54 expand_option_text(menudesc *menu, void *arg, int sel)
     55 {
     56 	arg_replace *ar = arg;
     57 	struct menu_ent *opt = &menu->opts[sel];
     58 
     59 	if (menu->opts[sel].opt_exp_name)
     60 		return;	/* has already been expanded */
     61 
     62 	opt->opt_exp_name =
     63 	    str_arg_subst(MSG_XLAT(opt->opt_name), ar->argc, ar->argv);
     64 }
     65 
     66 void
     67 expand_all_option_texts(menudesc *menu, void *arg)
     68 {
     69 	arg_replace *ar = arg;
     70 	const char *title;
     71 	int i;
     72 
     73 	if (menu->title != NULL && menu->exp_title == NULL) {
     74 		title = MSG_XLAT(menu->title);
     75 		if (needs_expanding(title, ar->argc)) {
     76 			menu->exp_title = str_arg_subst(title,
     77 			    ar->argc, ar->argv);
     78 		}
     79 	}
     80 	for (i = 0; i < menu->numopts; i++) {
     81 		const char *t = MSG_XLAT(menu->opts[i].opt_name);
     82 
     83 		if (t == NULL) continue;
     84 
     85 		if (needs_expanding(t, ar->argc))
     86 			expand_option_text(menu, arg, i);
     87 	}
     88 }
     89 
     90 /*
     91  * Re-create the menu window with heigh/width updated to current state.
     92  */
     93 void
     94 resize_menu_height(menudesc *m)
     95 {
     96 
     97 	if (m->mw == NULL)
     98 		return;
     99 
    100 	wclear(m->mw);
    101 	if (m->sv_mw) {
    102 		overwrite(m->sv_mw, m->mw);
    103 		delwin(m->sv_mw);
    104 		m->sv_mw = NULL;
    105 	}
    106 	wnoutrefresh(m->mw);
    107 	delwin(m->mw);
    108 	m->mw = NULL;
    109 }
    110 
    111 static void
    112 src_legend(menudesc *menu, const char *legend, const char *text)
    113 {
    114         wprintw(menu->mw, "%-35s %.50s", MSG_XLAT(legend), MSG_XLAT(text));
    115 }
    116 
    117 static void
    118 src_prompt(const char *prompt, char *buf, size_t size)
    119 {
    120 	msg_prompt_win(prompt, -1, 12, 0, 0, buf, buf, size);
    121 }
    122 
    123 static void
    124 remove_sub_menu(int menuID)
    125 {
    126 
    127 	for (size_t i = 0; i < DYN_MENU_START; i++) {
    128 		for (int j = 0; j < menu_def[i].numopts; j++) {
    129 			if ((menu_def[i].opts[j].opt_flags & OPT_SUB)
    130 			    && menu_def[i].opts[j].opt_menu == menuID) {
    131 
    132 				for (int k = j + 1; k < menu_def[i].numopts;
    133 				    k++) {
    134 					menu_def[i].opts[k-1] =
    135 					    menu_def[i].opts[k];
    136 				}
    137 				menu_def[i].numopts--;
    138 				return;
    139 
    140 			}
    141 		}
    142 	}
    143 }
    144 
    145 #ifndef NO_PARTMAN
    146 static void
    147 remove_menu_option(int menuID, const char *option)
    148 {
    149 
    150 	for (int j = 0; j < menu_def[menuID].numopts; j++) {
    151 		if (menu_def[menuID].opts[j].opt_name == option) {
    152 			for (int k = j + 1; k < menu_def[menuID].numopts;
    153 			    k++) {
    154 				menu_def[menuID].opts[k-1] =
    155 				    menu_def[menuID].opts[k];
    156 			}
    157 			menu_def[menuID].numopts--;
    158 			return;
    159 
    160 		}
    161 	}
    162 }
    163 #endif
    164 
    165 void
    166 remove_color_options()
    167 {
    168 	/*
    169 	 * Current terminal type does not support colors, so remove all
    170 	 * menu entries (actually that is: Utils/Color Scheme) that do not
    171 	 * make any sense in this case.
    172 	 */
    173 	remove_sub_menu(MENU_colors);
    174 }
    175 
    176 #ifndef NO_PARTMAN
    177 void
    178 remove_raid_options()
    179 {
    180 	/*
    181 	 * No raidframe available, remove the following menu entries:
    182 	 */
    183 	remove_menu_option(MENU_pmdiskentry, MSG_fmtasraid);
    184 	remove_menu_option(MENU_pmpartentry, MSG_fmtasraid);
    185 }
    186 
    187 void
    188 remove_lvm_options()
    189 {
    190 	/*
    191 	 * No LVM available, remove the following menu entries:
    192 	 */
    193 	remove_menu_option(MENU_pmdiskentry, MSG_fmtaslvm);
    194 	remove_menu_option(MENU_pmpartentry, MSG_fmtaslvm);
    195 }
    196 
    197 void
    198 remove_cgd_options()
    199 {
    200 	/*
    201 	 * No CGD available, remove the following menu entries:
    202 	 */
    203 	remove_menu_option(MENU_pmdiskentry, MSG_encrypt);
    204 	remove_menu_option(MENU_pmpartentry, MSG_encrypt);
    205 }
    206 #endif
    207 
    208 }
    209 
    210 default y=12, no exit, scrollable;
    211 
    212 allow dynamic menus;
    213 allow dynamic messages;
    214 allow expand;
    215 
    216 error action {
    217 	fprintf (stderr, "Could not initialize menu system, please check "
    218 	    "your terminal type.\n");
    219 	exit(4);
    220 };
    221 
    222 /*
    223  * Called with arg = struct single_part_fs_edit*
    224  */
    225 menu mountoptions, title MSG_toggle, y=5, x=30, exitstring MSG_unchanged;
    226 	/*
    227 	 *  XXX - enable / disable options depending on FS type in
    228 	 *  display action
    229 	*/
    230 	option "log", exit, action
    231 		{ struct single_part_fs_edit *edit = arg;
    232 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_LOG; };
    233 	option "async", exit, action
    234 		{ struct single_part_fs_edit *edit = arg;
    235 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_ASYNC; };
    236 	option "noatime", exit, action
    237 		{ struct single_part_fs_edit *edit = arg;
    238 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NOATIME; };
    239 	option "nodev", exit, action
    240 		{ struct single_part_fs_edit *edit = arg;
    241 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NODEV; };
    242 	option "nodevmtime", exit, action
    243 		{ struct single_part_fs_edit *edit = arg;
    244 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NODEVMTIME; };
    245 	option "noexec", exit, action
    246 		{ struct single_part_fs_edit *edit = arg;
    247 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NOEXEC; };
    248 	option "nosuid", exit, action
    249 		{ struct single_part_fs_edit *edit = arg;
    250 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NOSUID; };
    251 	option "noauto", exit, action
    252 		{ struct single_part_fs_edit *edit = arg;
    253 		  edit->pset->infos[edit->index].mountflags ^= PUIMNT_NOAUTO; };
    254 
    255 menu netbsd, title MSG_NetBSD_VERSION_Install_System, y=-1,
    256     exit, exitstring MSG_Exit_Install_System;
    257 	display action  { toplevel(); };
    258 	option MSG_Install_NetBSD_to_hard_disk,
    259 		action { do_install(); };
    260 	option MSG_Upgrade_NetBSD_on_a_hard_disk,
    261 		action { do_upgrade(); };
    262 	option MSG_Re_install_sets_or_install_additional_sets,
    263 		action { do_reinstall_sets(); };
    264 	option MSG_Reboot_the_computer, exit,
    265 		action (endwin) { system("/sbin/reboot -q"); };
    266 	option MSG_Utility_menu, sub menu utility;
    267 	option MSG_Config_menu, action { do_configmenu(NULL); };
    268 
    269 menu utility, title MSG_NetBSD_VERSION_Utilities, exit,
    270 		exitstring MSG_exit_menu_generic;
    271 	display action  { toplevel(); };
    272 	option MSG_Run_bin_sh,
    273 		action (endwin) { system("/bin/sh"); };
    274 	option MSG_Set_timezone,
    275 		action { set_timezone(); };
    276 	option MSG_Configure_network,
    277 		action {
    278 			extern int network_up;
    279 			network_up = 0;
    280 			config_network(1);
    281 		};
    282 	option MSG_Partition_a_disk,
    283 		action {
    284 #ifndef NO_PARTMAN
    285 			partman_go = 1;
    286 			partman(NULL);
    287 #endif
    288 		};
    289 	option MSG_Logging_functions, action { do_logging(); };
    290 	option MSG_Color_scheme, sub menu colors;
    291 	option MSG_Halt_the_system, exit,
    292 		action (endwin) { system("/sbin/halt -q"); };
    293 
    294 menu colors, title MSG_Color_scheme, exit,
    295 		exitstring MSG_exit_menu_generic;
    296 	option MSG_White_on_black, action { do_coloring(COLOR_WHITE,COLOR_BLACK); };
    297 	option MSG_Black_on_white, action { do_coloring(COLOR_BLACK,COLOR_WHITE); };
    298 	option MSG_White_on_blue,  action { do_coloring(COLOR_WHITE,COLOR_BLUE); };
    299 	option MSG_Green_on_black, action { do_coloring(COLOR_GREEN,COLOR_BLACK); };
    300 
    301 
    302 menu yesno, y=-10;
    303 	display action { arg_rv *p = arg;
    304 		menu->title = p->arg ? p->arg : MSG_yes_or_no; };
    305 	option MSG_Yes, exit, action  { ((arg_rv*)arg)->rv = 1; };
    306 	option MSG_No,  exit, action  { ((arg_rv*)arg)->rv = 0; };
    307 
    308 menu noyes, y=-10;
    309 	display action { arg_rv *p = arg;
    310 		menu->title = p->arg ? p->arg : MSG_yes_or_no; };
    311 	option MSG_No,  exit, action  { ((arg_rv*)arg)->rv = 0; };
    312 	option MSG_Yes, exit, action  { ((arg_rv*)arg)->rv = 1; };
    313 
    314 menu ok, no shortcut, y=-10;
    315 	display action { menu->title = arg; };
    316 	option MSG_Hit_enter_to_continue, exit;
    317 
    318 menu sizechoice, sub menu, y=0, title MSG_Choose_your_size_specifier;
    319 	display action {
    320 		if (sizemult == pm->current_cylsize)
    321 			menu->cursel = 2;
    322 		else if (sizemult == 1)
    323 			menu->cursel = 3;
    324 		else if (sizemult == (GIG/pm->sectorsize))
    325 			menu->cursel = 0;
    326 		else
    327 			menu->cursel = 1; };
    328 	option MSG_Gigabytes, exit, action
    329 		{ set_sizemult(GIG, pm->sectorsize); };
    330 	option MSG_Megabytes, exit, action
    331 		{ set_sizemult(MEG, pm->sectorsize); };
    332 	option MSG_Cylinders, exit, action
    333 		{ set_sizemult(pm->current_cylsize*pm->sectorsize, pm->sectorsize); };
    334 	option MSG_Sectors, exit, action
    335 		{ set_sizemult(pm->sectorsize, pm->sectorsize); };
    336 
    337 menu ptnsize_replace_existing_partition, sub menu, y=0,
    338 	title MSG_ptnsize_replace_existing;
    339 	display action { menu->cursel = 1; };
    340 	option MSG_Yes, exit, action { *((int*)arg) = 1; };
    341 	option MSG_cancel, exit, action { *((int*)arg) = 0; };
    342 
    343 menu distmedium, title MSG_Select_medium, y=-5;
    344 	option MSG_cdrom,     exit, action { *(int *)arg = get_via_cdrom(); };
    345 	option MSG_http,      exit, action { *(int *)arg = get_via_ftp(XFER_HTTP); };
    346 	option MSG_ftp,	      exit, action { *(int *)arg = get_via_ftp(XFER_FTP); };
    347 	option MSG_nfs,	      exit, action { *(int *)arg = get_via_nfs(); };
    348 	option MSG_floppy,    exit, action { *(int *)arg = get_via_floppy(); };
    349 	option MSG_local_fs,  exit, action { *(int *)arg = get_via_localfs(); };
    350 	option MSG_local_dir, exit, action { *(int *)arg = get_via_localdir();};
    351 	option MSG_Skip_set,  exit, action { *(int *)arg = SET_SKIP; };
    352 	option MSG_Skip_group,exit, action { *(int *)arg = SET_SKIP_GROUP; };
    353 	option MSG_Abandon,   exit, action { *(int *)arg = SET_ABANDON; };
    354 
    355 menu distset, title MSG_Select_your_distribution, exit,
    356 	    no default exit, exitstring MSG_Abandon;
    357 	display action { msg_display (MSG_distset); };
    358 	option MSG_Full_installation, exit, action { *(int *)arg = 1; init_set_status(0);  };
    359 	option MSG_Full_installation_nox, exit, action { *(int *)arg = 1; init_set_status(SFLAG_NOX); };
    360 	option MSG_Minimal_installation, exit, action { *(int *)arg = 1; init_set_status(SFLAG_MINIMAL); };
    361 	option MSG_Custom_installation, exit, action { *(int *)arg = 1; init_set_status(SFLAG_MINIMAL); customise_sets(); };
    362 
    363 menu ftpsource, y=-4, x=0, w=70, no box, no clear,
    364 	    exitstring MSG_Get_Distribution;
    365 	display action {
    366 		msg_display_subst(MSG_ftpsource, 2, "." SETS_TAR_SUFF,
    367 		    url_proto((uintptr_t)((arg_rv*)arg)->arg));
    368 	    };
    369 	option {src_legend(menu, MSG_Host, ftp.xfer_host[(uintptr_t)((arg_rv*)arg)->arg]);},
    370 		action { src_prompt(MSG_Host, ftp.xfer_host[(uintptr_t)((arg_rv*)arg)->arg], sizeof ftp.xfer_host[(uintptr_t)((arg_rv*)arg)->arg]); };
    371 	option {src_legend(menu, MSG_Base_dir, ftp.dir);},
    372 		action { src_prompt(MSG_Base_dir, ftp.dir, sizeof ftp.dir); };
    373 	option {src_legend(menu, MSG_Set_dir_bin, set_dir_bin);},
    374 		action { src_prompt(MSG_Set_dir_bin, set_dir_bin, sizeof set_dir_bin); };
    375 	option {src_legend(menu, MSG_Set_dir_src, set_dir_src);},
    376 		action { src_prompt(MSG_Set_dir_src, set_dir_src, sizeof set_dir_src); };
    377 	option {src_legend(menu, MSG_Dist_postfix, dist_postfix);},
    378 		action { src_prompt(MSG_Dist_postfix, dist_postfix, sizeof dist_postfix); };
    379 	option {src_legend(menu, MSG_User, ftp.user);},
    380 		action { src_prompt(MSG_User, ftp.user, sizeof ftp.user);
    381 			ftp.pass[0] = 0;
    382 		};
    383 	option {src_legend(menu, MSG_Password,
    384 		    strcmp(ftp.user, "ftp") == 0 || ftp.pass[0] == 0
    385 			? ftp.pass : msg_string(MSG_hidden));},
    386 		action { if (strcmp(ftp.user, "ftp") == 0)
    387 			src_prompt(MSG_email, ftp.pass, sizeof ftp.pass);
    388 		  else {
    389 			msg_prompt_noecho(MSG_Password, "",
    390 					ftp.pass, sizeof ftp.pass);
    391 		  }
    392 		};
    393 	option {src_legend(menu, MSG_Proxy, ftp.proxy);},
    394 		action { src_prompt(MSG_Proxy, ftp.proxy, sizeof ftp.proxy);
    395 		  if (strcmp(ftp.proxy, "") == 0) {
    396 			unsetenv("ftp_proxy");
    397 			unsetenv("http_proxy");
    398 		  } else {
    399 			setenv("ftp_proxy", ftp.proxy, 1);
    400 			setenv("http_proxy", ftp.proxy, 1);
    401 		  }
    402 		};
    403 	option {src_legend(menu, MSG_Xfer_dir, xfer_dir);},
    404 		action { src_prompt(MSG_Xfer_dir, xfer_dir, sizeof xfer_dir); };
    405 	option {src_legend(menu, MSG_delete_xfer_file,
    406 			clean_xfer_dir ? MSG_Yes : MSG_No);},
    407 		action {clean_xfer_dir = ask_yesno(MSG_delete_xfer_file); };
    408 	option MSG_Configure_network,
    409 		action {
    410 			extern int network_up;
    411 			network_up = 0;
    412 			config_network(1);
    413 		};
    414 	option MSG_exit_menu_generic, exit, action { ((arg_rv*)arg)->rv = SET_RETRY; };
    415 
    416 
    417 menu nfssource, y=-4, x=0, w=70, no box, no clear,
    418 	    exitstring MSG_Get_Distribution;
    419 	display action { const char suff[] = "." SETS_TAR_SUFF;
    420 		msg_display_subst(MSG_nfssource, 1, &suff); };
    421 	option {src_legend(menu, MSG_Host, nfs_host);},
    422 		action { src_prompt(MSG_Host, nfs_host, sizeof nfs_host); };
    423 	option {src_legend(menu, MSG_Base_dir, nfs_dir);},
    424 		action { src_prompt(MSG_Base_dir, nfs_dir, sizeof nfs_dir); };
    425 	option {src_legend(menu, MSG_Set_dir_bin, set_dir_bin);},
    426 		action { src_prompt(MSG_Set_dir_bin, set_dir_bin, sizeof set_dir_bin); };
    427 	option {src_legend(menu, MSG_Set_dir_src, set_dir_src);},
    428 		action { src_prompt(MSG_Set_dir_src, set_dir_src, sizeof set_dir_src); };
    429 	option {src_legend(menu, MSG_Dist_postfix, dist_postfix);},
    430 		action { src_prompt(MSG_Dist_postfix, dist_postfix, sizeof dist_postfix); };
    431 	option MSG_Configure_network,
    432 		action {
    433 			extern int network_up;
    434 			network_up = 0;
    435 			config_network(1);
    436 		};
    437 	option MSG_exit_menu_generic, exit, action { *((int*)arg) = SET_RETRY; };
    438 
    439 menu fdremount, title MSG_What_do_you_want_to_do;
    440 	option MSG_Try_again, exit, action { *(int *)arg = SET_CONTINUE; };
    441 	option MSG_Set_finished, exit, action { *(int *)arg = SET_OK; };
    442 	option MSG_Abort_fetch, exit, action { *(int *)arg = SET_RETRY; };
    443 
    444 menu fdok, title MSG_What_do_you_want_to_do;
    445 	option MSG_OK, exit, action { *(int *)arg = SET_CONTINUE; };
    446 	option MSG_Set_finished, exit, action { *(int *)arg = SET_OK; };
    447 	option MSG_Abort_fetch, exit, action { *(int *)arg = SET_RETRY; };
    448 
    449 menu fd_type, title MSG_fd_type, y=16;
    450 	option "msdos", exit, action { fd_type = "msdos"; };
    451 	option "ffs",   exit, action { fd_type = "ffs"; };
    452 .if ADOS_FLOPPY
    453 	option "ados",  exit, action { fd_type = "ados"; };
    454 .endif
    455 
    456 menu floppysource, y=-4, x=0, w=70, no box, no clear, exitstring MSG_Continue;
    457 	display action { msg_display(MSG_floppysource); };
    458 	option {src_legend(menu, MSG_Device, fd_dev);},
    459 		action { src_prompt(MSG_dev, fd_dev, sizeof fd_dev); };
    460 	option {src_legend(menu, MSG_fd_type, fd_type);}, sub menu fd_type;
    461 	option {src_legend(menu, MSG_Xfer_dir, xfer_dir);},
    462 		action { src_prompt(MSG_Xfer_dir, xfer_dir, sizeof xfer_dir); };
    463 	option {src_legend(menu, MSG_delete_xfer_file,
    464 			clean_xfer_dir ? MSG_Yes : MSG_No);},
    465 		action {clean_xfer_dir = ask_yesno(MSG_delete_xfer_file); };
    466 	option MSG_exit_menu_generic, exit, action { *((int*)arg) = SET_RETRY; };
    467 
    468 menu cdromsource, y=-4, x=0, w=70, no box, no clear, exitstring MSG_Continue;
    469 	display action { const char suff[] = "." SETS_TAR_SUFF;
    470 		msg_display_add_subst(MSG_cdromsource, 1, &suff); };
    471 	option {src_legend(menu, MSG_Device, cdrom_dev);},
    472 		action { src_prompt(MSG_dev, cdrom_dev, sizeof cdrom_dev); };
    473 	option {src_legend(menu, MSG_Set_dir_bin, set_dir_bin);},
    474 		action { src_prompt(MSG_Set_dir_bin, set_dir_bin, sizeof set_dir_bin); };
    475 	option {src_legend(menu, MSG_Set_dir_src, set_dir_src);},
    476 		action { src_prompt(MSG_Set_dir_src, set_dir_src, sizeof set_dir_src); };
    477 	option {src_legend(menu, MSG_Dist_postfix, dist_postfix);},
    478 		action { src_prompt(MSG_Dist_postfix, dist_postfix, sizeof dist_postfix); };
    479 	option MSG_abort_install, exit, action { *((int*)arg) = SET_ABANDON; };
    480 	option MSG_source_sel_retry, exit, action { *((int*)arg) = SET_RETRY; };
    481 
    482 menu localfssource, y=-4, x=0, w=70, no box, no clear, exitstring MSG_Continue;
    483 	display action { const char suff[] = "." SETS_TAR_SUFF;
    484 		msg_display_subst(MSG_localfssource, 1, &suff); };
    485 	option {src_legend(menu, MSG_Device, localfs_dev);},
    486 		action { src_prompt(MSG_dev, localfs_dev, sizeof localfs_dev);};
    487 	option {src_legend(menu, MSG_File_system, localfs_fs);},
    488 		action { src_prompt(MSG_filesys, localfs_fs, sizeof localfs_fs); };
    489 	option {src_legend(menu, MSG_Base_dir, localfs_dir);},
    490 		action { src_prompt(MSG_Base_dir, localfs_dir, sizeof localfs_dir);};
    491 	option {src_legend(menu, MSG_Set_dir_bin, set_dir_bin);},
    492 		action { src_prompt(MSG_Set_dir_bin, set_dir_bin, sizeof set_dir_bin); };
    493 	option {src_legend(menu, MSG_Set_dir_src, set_dir_src);},
    494 		action { src_prompt(MSG_Set_dir_src, set_dir_src, sizeof set_dir_src); };
    495 	option {src_legend(menu, MSG_Dist_postfix, dist_postfix);},
    496 		action { src_prompt(MSG_Dist_postfix, dist_postfix, sizeof dist_postfix); };
    497 	option MSG_exit_menu_generic, exit, action { *((int*)arg) = SET_RETRY; };
    498 
    499 menu localdirsource, y=-4, x=0, w=70, no box, no clear, exitstring MSG_Continue;
    500 	display action { const char suff[] = "." SETS_TAR_SUFF;
    501 		msg_display_subst(MSG_localdir, 1, &suff); };
    502 	option {src_legend(menu, MSG_Base_dir, localfs_dir);},
    503 		action { src_prompt(MSG_Base_dir, localfs_dir, 60); };
    504 	option {src_legend(menu, MSG_Set_dir_bin, set_dir_bin);},
    505 		action { src_prompt(MSG_Set_dir_bin, set_dir_bin, 60); };
    506 	option {src_legend(menu, MSG_Set_dir_src, set_dir_src);},
    507 		action { src_prompt(MSG_Set_dir_src, set_dir_src, 60); };
    508 	option {src_legend(menu, MSG_Dist_postfix, dist_postfix);},
    509 		action { src_prompt(MSG_Dist_postfix, dist_postfix, 60); };
    510 	option MSG_exit_menu_generic, exit, action { *((int*)arg) = SET_RETRY; };
    511 
    512 menu namesrv6, title MSG_Select_DNS_server;
    513 	option "google-public-dns-a.google.com (IPv4)", exit, action
    514 		{
    515 #ifdef INET6
    516 		  strlcpy(net_namesvr, "8.8.8.8",
    517 		      sizeof(net_namesvr));
    518 		  *((int*)arg) = 1;
    519 #else
    520 		  *((int*)arg) = 0;
    521 #endif
    522 		};
    523 	option "google-public-dns-b.google.com (IPv4)", exit, action
    524 		{
    525 #ifdef INET6
    526 		  strlcpy(net_namesvr, "8.8.4.4",
    527 		      sizeof(net_namesvr));
    528 		  *((int*)arg) = 1;
    529 #else
    530 		  *((int*)arg) = 0;
    531 #endif
    532 		};
    533 	option "google-public-dns-a.google.com (IPv6)", exit, action
    534 		{
    535 #ifdef INET6
    536 		  strlcpy(net_namesvr, "2001:4860:4860::8888",
    537 		      sizeof(net_namesvr));
    538 		  *((int*)arg) = 1;
    539 #else
    540 		  *((int*)arg) = 0;
    541 #endif
    542 		};
    543 	option "google-public-dns-b.google.com (IPv6)", exit, action
    544 		{
    545 #ifdef INET6
    546 		  strlcpy(net_namesvr, "2001:4860:4860::8844",
    547 		      sizeof(net_namesvr));
    548 		  *((int*)arg) = 1;
    549 #else
    550 		  *((int*)arg) = 0;
    551 #endif
    552 		};
    553 	option MSG_other, exit, action
    554 		{ *((int*)arg) = 0; };
    555 
    556 menu rootsh, title MSG_Root_shell, no clear;
    557 	option "/bin/sh",  exit, action {*(const char **)arg = "/bin/sh";};
    558 	option "/bin/ksh", exit, action {*(const char **)arg = "/bin/ksh";};
    559 	option "/bin/csh", exit, action {*(const char **)arg = "/bin/csh";};
    560 
    561 menu zeroconf, title "Zeroconf", no clear;
    562 	option "run mdnsd only", exit, action {*(const char **)arg = "mdnsd";};
    563 	option "run mdnsd and resolve local names", exit, action {*(const char **) arg = "mdnsd+nsswitch";};
    564 	option "do not run mdnsd", exit, action {*(const char **)arg = "No";};
    565 
    566 menu binpkg, y=-4, x=0, w=70, no box, no clear,
    567 	    exitstring MSG_Install_pkgin;
    568 	display action { msg_display(MSG_pkgpath); };
    569 	option {src_legend(menu, MSG_Host, pkg.xfer_host[pkg.xfer]);},
    570 		action { src_prompt(MSG_Host, pkg.xfer_host[pkg.xfer], sizeof pkg.xfer_host[pkg.xfer]); };
    571 	option {src_legend(menu, MSG_Base_dir, pkg.dir);},
    572 		action { src_prompt(MSG_Base_dir, pkg.dir, sizeof pkg.dir); };
    573 	option {src_legend(menu, MSG_Pkg_dir, pkg_dir);},
    574 		action { src_prompt(MSG_Pkg_dir, pkg_dir, sizeof pkg_dir); };
    575 	option {src_legend(menu, MSG_User, pkg.user);},
    576 		action { src_prompt(MSG_User, pkg.user, sizeof pkg.user);
    577 			pkg.pass[0] = 0;
    578 		};
    579 	option {src_legend(menu, MSG_Password,
    580 		    strcmp(pkg.user, "ftp") == 0 || pkg.pass[0] == 0
    581 			? pkg.pass : msg_string(MSG_hidden));},
    582 		action { if (strcmp(pkg.user, "ftp") == 0)
    583 			src_prompt(MSG_email, pkg.pass, sizeof pkg.pass);
    584 		  else {
    585 			msg_prompt_noecho(MSG_Password, "",
    586 					pkg.pass, sizeof pkg.pass);
    587 		  }
    588 		};
    589 	option {src_legend(menu, MSG_Proxy, pkg.proxy);},
    590 		action { src_prompt(MSG_Proxy, pkg.proxy, sizeof pkg.proxy);
    591 		  if (strcmp(pkg.proxy, "") == 0) {
    592 			unsetenv("ftp_proxy");
    593 			unsetenv("http_proxy");
    594 		  } else {
    595 			setenv("ftp_proxy", pkg.proxy, 1);
    596 			setenv("http_proxy", pkg.proxy, 1);
    597 		  }
    598 		};
    599 	option {src_legend(menu, "Additional packages", (char*)(((arg_rv*)arg)->arg)); }, /*TODO*/
    600 		action { src_prompt("Additional packages", (char*)(((arg_rv*)arg)->arg),
    601 			 sizeof(char) * STRSIZE); };
    602 	option MSG_Configure_network,
    603 		action {
    604 			extern int network_up;
    605 			network_up = 0;
    606 			config_network(1);
    607 			mnt_net_config();
    608 		};
    609 	option {src_legend(menu, MSG_transfer_method, url_proto(pkg.xfer));},
    610 		action { pkg.xfer = (pkg.xfer+1) % (XFER_MAX+1); };
    611 	option MSG_quit_pkgs_install, exit, action { ((arg_rv*)arg)->rv = SET_SKIP; };
    612 
    613 menu pkgsrc, y=-4, x=0, w=70, no box, no clear,
    614 	    exit, exitstring MSG_Install_pkgsrc;
    615 	display action { msg_display(MSG_pkgsrc); };
    616 	option {src_legend(menu, MSG_Host, pkgsrc.xfer_host[pkgsrc.xfer]);},
    617 		action { src_prompt(MSG_Host, pkgsrc.xfer_host[pkgsrc.xfer],
    618 			sizeof pkgsrc.xfer_host[pkgsrc.xfer]); };
    619 	option {src_legend(menu, MSG_Pkgsrc_dir, pkgsrc_dir);},
    620 		action { src_prompt(MSG_Pkgsrc_dir, pkgsrc_dir, sizeof pkgsrc_dir); };
    621 	option {src_legend(menu, MSG_User, pkgsrc.user);},
    622 		action { src_prompt(MSG_User, pkgsrc.user, sizeof pkgsrc.user);
    623 			pkgsrc.pass[0] = 0;
    624 		};
    625 	option {src_legend(menu, MSG_Password,
    626 		    strcmp(pkgsrc.user, "ftp") == 0 || pkgsrc.pass[0] == 0
    627 			? pkgsrc.pass : msg_string(MSG_hidden));},
    628 		action { if (strcmp(pkgsrc.user, "ftp") == 0)
    629 			src_prompt(MSG_email, pkgsrc.pass, sizeof pkgsrc.pass);
    630 		  else {
    631 			msg_prompt_noecho(MSG_Password, "",
    632 					pkgsrc.pass, sizeof pkgsrc.pass);
    633 		  }
    634 		};
    635 	option {src_legend(menu, MSG_Proxy, pkgsrc.proxy);},
    636 		action { src_prompt(MSG_Proxy, pkgsrc.proxy, sizeof pkgsrc.proxy);
    637 		  if (strcmp(pkgsrc.proxy, "") == 0) {
    638 			unsetenv("ftp_proxy");
    639 			unsetenv("http_proxy");
    640 		  } else {
    641 			setenv("ftp_proxy", pkgsrc.proxy, 1);
    642 			setenv("http_proxy", pkgsrc.proxy, 1);
    643 		  }
    644 		};
    645 	option {src_legend(menu, MSG_Xfer_dir, xfer_dir);},
    646 		action { src_prompt(MSG_Xfer_dir, xfer_dir, sizeof xfer_dir); };
    647 	option {src_legend(menu, MSG_delete_xfer_file,
    648 			clean_xfer_dir ? MSG_Yes : MSG_No);},
    649 		action {clean_xfer_dir = ask_yesno(MSG_delete_xfer_file); };
    650 	option {src_legend(menu, MSG_transfer_method, url_proto(pkgsrc.xfer));},
    651 		action { pkgsrc.xfer = (pkgsrc.xfer+1) % (XFER_MAX+1); };
    652 	option MSG_quit_pkgsrc, exit, action { *((int*)arg) = SET_SKIP;};
    653 
    654 menu usersh, title MSG_User_shell, no clear;
    655 	option "/bin/sh",  exit, action { ushell = "/bin/sh";};
    656 	option "/bin/ksh", exit, action { ushell = "/bin/ksh";};
    657 	option "/bin/csh", exit, action { ushell = "/bin/csh";};
    658 
    659 menu convertscheme, title MSG_cvtscheme_hdr;
    660 	option MSG_cvtscheme_keep,		exit, action { *(int*)arg = 0; };
    661 	option MSG_cvtscheme_delete,		exit, action { *(int*)arg = 1; };
    662 	option MSG_cvtscheme_convert,		exit, action { *(int*)arg = 2; };
    663 	option MSG_cvtscheme_abort,		exit, action { *(int*)arg = 3; };
    664 
    665 
    666 menu reedit, title MSG_reeditpart, y=-10;
    667 	expand action { expand_all_option_texts(menu, arg); };
    668 	option MSG_reedit_partitions, exit,
    669 	    action  {((arg_rep_int*)arg)->rv = 1;};
    670 	option MSG_use_partitions_anyway, exit,
    671 	    action  {((arg_rep_int*)arg)->rv = 2;};
    672 	option MSG_abort_installation,       exit,
    673 	    action  {((arg_rep_int*)arg)->rv = 0;};
    674