1 /*
2  * Copyright (c)2004 The DragonFly Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  *   Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  *
11  *   Redistributions in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in
13  *   the documentation and/or other materials provided with the
14  *   distribution.
15  *
16  *   Neither the name of the DragonFly Project nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * flow.c
36  * Workflow logic for installer.
37  * $Id: flow.c,v 1.67 2005/04/08 08:09:23 cpressey Exp $
38  */
39 
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 
45 #ifdef ENABLE_NLS
46 #include <libintl.h>
47 #include <locale.h>
48 #include "libdfui/lang.h"
49 #define _(String) gettext (String)
50 extern int _nl_msg_cat_cntr;
51 #else
52 #define _(String) (String)
53 #endif
54 
55 #include "libaura/mem.h"
56 #include "libaura/dict.h"
57 #include "libaura/fspred.h"
58 
59 #include "libdfui/dfui.h"
60 #ifdef DEBUG
61 #include "libdfui/dump.h"
62 #endif
63 #include "libdfui/system.h"
64 
65 #include "libinstaller/commands.h"
66 #include "libinstaller/confed.h"
67 #include "libinstaller/diskutil.h"
68 #include "libinstaller/functions.h"
69 #include "libinstaller/package.h"
70 #include "libinstaller/uiutil.h"
71 
72 #include "flow.h"
73 #include "fn.h"
74 #include "pathnames.h"
75 
76 /*** GLOBALS ***/
77 
78 void (*state)(struct i_fn_args *) = NULL;
79 int do_reboot;
80 
81 /*** STATES ***/
82 
83 /*
84  * The installer works like a big state machine.  Each major form is
85  * a state.  When the user has filled out the form satisfactorily,
86  * and selects "OK", there is a transition to the next state, in a
87  * mostly-linear order towards the final, "successfully installed"
88  * state.  The user may also "Cancel", which generally causes a
89  * transition to the previous state (but may also take them back to
90  * the very first state in some cases.)
91  *
92  * Installer States:
93  * - Select localization	optional
94  * - Welcome to DragonFly	required
95  * - Begin Installation		required
96  * - Select Disk		required
97  * - Format Disk		optional	dd, fdisk
98  * - Select Partition		required	dd, disklabel
99  * - Create Subpartitions	required	disklabel, newfs
100  * - Install DragonFly		required	swapon, mkdir, mount, cpdup
101  * - Install Bootstrap		optional	boot0cfg
102  * - Reboot			optional	reboot
103  */
104 
105 #ifdef ENABLE_NLS
106 void
107 state_lang_menu(struct i_fn_args *a)
108 {
109 	struct dfui_form *f;
110 	struct dfui_response *r;
111 	int done = 0;
112 	char *id;
113 	int cancelled = 0;
114 
115 	while (!done) {
116 		f = dfui_form_create(
117 			"main_menu",
118 			_("Select Language"),
119 			_("Please select the language you wish you use."),
120 			"",
121 
122 			"p", "role", "menu",
123 
124 			"a", "default", "English",
125 			"English Standard Default", "",
126 			"a", "ru", "Russian",
127 			"Russian KOI8-R", "",
128 			NULL
129 		);
130 
131 		if (!dfui_be_present(a->c, f, &r))
132 			abort_backend();
133 
134 		id = aura_strdup(dfui_response_get_action_id(r));
135 
136 		if (strcmp(id, "default") == 0) {
137 			state = state_welcome;
138 			return;
139 		} else {
140 			state = state_welcome;
141 			done = 1;
142 		}
143 
144 		dfui_form_free(f);
145 		dfui_response_free(r);
146 	}
147 
148 	/* set keymap, scrnmap, fonts */
149 	if (!set_lang_syscons(id))
150 		return;
151 
152 	/* set envars */
153 	if (!set_lang_envars(id))
154 		return;
155 
156 	dfui_be_set_global_setting(a->c, "lang", id, &cancelled);
157 
158 	/* XXX if (!cancelled) ... ? */
159 
160 	/* let gettext know about changes */
161 	++_nl_msg_cat_cntr;
162 }
163 #endif
164 
165 /*
166  * state_welcome_livecd: the start state of the installer state machine,
167  * when run from the Live CD.  Briefly describe DragonFly to the user,
168  * and present them with a set of reasonable options of how to proceed.
169  */
170 void
171 state_welcome(struct i_fn_args *a)
172 {
173 	struct dfui_form *f;
174 	struct dfui_action *k;
175 	struct dfui_response *r;
176 	char msg_buf[2][1024];
177 
178 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
179 	    _("Welcome to %s"), OPERATING_SYSTEM_NAME);
180 
181 	snprintf(msg_buf[1], sizeof(msg_buf[1]),
182 	    _("Welcome to the %s Live CD."
183 	    "\n\n"
184 	    "%s is an efficient and elegant BSD "
185 	    "Unix-derived operating system.  For more information, see %s"
186 	    "\n\n"
187 	    "From this CD, you can boot into %s ``live'' "
188 	    "(without installing it) to evaluate it, to install it "
189 	    "manually, or to troubleshoot problems with an "
190 	    "existing installation, using either a command prompt "
191 	    "or menu-driven utilities."
192 	    "\n\n"
193 	    "Also, you can use this automated application to assist "
194 	    "you in installing %s on this computer and "
195 	    "configuring it once it is installed."
196 	    ""),
197 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_URL,
198 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
199 
200 	if (!a->booted_from_livecd) {
201 		state = state_welcome_system;
202 		return;
203 	}
204 
205 	f = dfui_form_create(
206 	    "welcome",
207 	    msg_buf[0],
208 
209 	    msg_buf[1],
210 
211 	    "",
212 
213 	    "p",	"special", 	"dfinstaller_welcome",
214 
215 	    NULL
216 	);
217 
218 	if (a->upgrade_menu_toggle) {
219 		snprintf(msg_buf[0], sizeof(msg_buf[0]),
220 		    _("Upgrade a FreeBSD 4.X system to %s"),
221 		    OPERATING_SYSTEM_NAME);
222 		dfui_form_action_add(f, "upgrade",
223 		    dfui_info_new(_("Upgrade"),
224 		    msg_buf[0], ""));
225 	} else {
226 		snprintf(msg_buf[0], sizeof(msg_buf[0]),
227 		    _("Install %s"), OPERATING_SYSTEM_NAME);
228 		snprintf(msg_buf[1], sizeof(msg_buf[1]),
229 		    _("Install %s on a HDD or HDD partition on this computer"),
230 		    OPERATING_SYSTEM_NAME);
231 		dfui_form_action_add(f, "install",
232 		    dfui_info_new(msg_buf[0],
233 		    msg_buf[1], ""));
234 	}
235 
236 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
237 	    _("Configure a %s system once it has been installed on HDD"),
238 	    OPERATING_SYSTEM_NAME);
239 	dfui_form_action_add(f, "configure",
240 	    dfui_info_new(_("Configure an Installed System"),
241 	    msg_buf[0], ""));
242 
243 	dfui_form_action_add(f, "utilities",
244 	    dfui_info_new(_("Live CD Utilities"),
245 	    _("Utilities to work with disks, diagnostics, and the LiveCD Environment"), ""));
246 
247 	k = dfui_form_action_add(f, "exit",
248 	    dfui_info_new(_("Exit to Live CD"),
249 	    _("Exit this program to a login prompt with access to the LiveCD"), ""));
250 
251 	dfui_form_action_add(f, "reboot",
252 	    dfui_info_new(_("Reboot this Computer"),
253 	    _("Reboot this computer (e.g. to boot into a newly installed system)"), ""));
254 
255 	dfui_form_action_add(f, "configure_netboot",
256 	    dfui_info_new(_("Setup NetBoot Install Services"),
257 	    _("Setup machine as remote installation server"), ""));
258 
259 	if (!dfui_be_present(a->c, f, &r))
260 		abort_backend();
261 
262 	if (strcmp(dfui_response_get_action_id(r), "install") == 0) {
263 		state = state_begin_install;
264 	} else if (strcmp(dfui_response_get_action_id(r), "upgrade") == 0) {
265 		state = state_begin_upgrade;
266 	} else if (strcmp(dfui_response_get_action_id(r), "configure") == 0) {
267 		storage_set_selected_disk(a->s, NULL);
268 		storage_set_selected_slice(a->s, NULL);
269 		state = state_configure_menu;
270 	} else if (strcmp(dfui_response_get_action_id(r), "utilities") == 0) {
271 		state = state_utilities_menu;
272 	} else if (strcmp(dfui_response_get_action_id(r), "exit") == 0) {
273 		state = NULL;
274         } else if (strcmp(dfui_response_get_action_id(r), "configure_netboot") == 0) {
275                 state = state_setup_remote_installation_server;
276 	} else if (strcmp(dfui_response_get_action_id(r), "reboot") == 0) {
277 		state = state_reboot;
278 	}
279 
280 	dfui_form_free(f);
281 	dfui_response_free(r);
282 }
283 
284 /*
285  * state_welcome_system: the start state of the installer state machine,
286  * when run from the installed system.  Allow the user to configure the
287  * system.
288  */
289 void
290 state_welcome_system(struct i_fn_args *a)
291 {
292 	struct dfui_form *f;
293 	struct dfui_response *r;
294 	char msg_buf[2][1024];
295 
296 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
297 	    _("Configure this %s System"), OPERATING_SYSTEM_NAME);
298 
299 	snprintf(msg_buf[1], sizeof(msg_buf[1]),
300 	    _("Thank you for choosing %s."
301 	    "\n\n"
302 	    "For up-to-date news and information on %s, "
303 	    "make sure to check out"
304 	    "\n\n"
305 	    "%s"
306 	    "\n\n"
307 	    "You can use this automated application to assist "
308 	    "you in setting up this %s system."
309 	    ""),
310 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME,
311 	    OPERATING_SYSTEM_URL, OPERATING_SYSTEM_NAME);
312 
313 
314 	f = dfui_form_create(
315 	    "welcome",
316 	    msg_buf[0],
317 
318 	    msg_buf[1],
319 
320 	    "",
321 
322 	    "p",	"special", 	"dfinstaller_welcome",
323 
324 	    NULL
325 	);
326 
327 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
328 	    _("Configure this %s system"), OPERATING_SYSTEM_NAME);
329 
330 	dfui_form_action_add(f, "environment",
331 	    dfui_info_new(_("Configure this System"),
332 	    msg_buf[0], ""));
333 
334 	dfui_form_action_add(f, "utilities",
335 	    dfui_info_new(_("Utilities"),
336 	    _("Utilities to work with and diagnose disks and other subsystems"), ""));
337 
338 	dfui_form_action_add(f, "exit",
339 	    dfui_info_new(_("Exit Installer"),
340 	    _("Exit this program and return to the system"), ""));
341 
342 	if (!dfui_be_present(a->c, f, &r))
343 		abort_backend();
344 
345 	if (strcmp(dfui_response_get_action_id(r), "environment") == 0) {
346 		state = state_environment_menu;
347 	} else if (strcmp(dfui_response_get_action_id(r), "utilities") == 0) {
348 		state = state_utilities_menu;
349 	} else if (strcmp(dfui_response_get_action_id(r), "exit") == 0) {
350 		state = NULL;
351 	} else if (strcmp(dfui_response_get_action_id(r), "reboot") == 0) {
352 		state = state_reboot;
353 	}
354 
355 	dfui_form_free(f);
356 	dfui_response_free(r);
357 }
358 
359 void
360 state_configure_menu(struct i_fn_args *a)
361 {
362 	struct dfui_form *f = NULL;
363 	struct dfui_response *r = NULL;
364 	struct commands *cmds;
365 	int done = 0;
366 	char msg_buf[2][1024];
367 
368 	if (storage_get_selected_disk(a->s) == NULL || storage_get_selected_slice(a->s) == NULL) {
369 		if (!survey_storage(a)) {
370 			inform(a->c, _("Errors occurred while probing "
371 			    "the system for its storage capabilities."));
372 		}
373 
374 		a->short_desc = _("Select the disk containing the installation.");
375 		a->cancel_desc = _("Return to Welcome Menu");
376 		fn_select_disk(a);
377 		if (!a->result || storage_get_selected_disk(a->s) == NULL) {
378 			state = state_welcome;
379 			return;
380 		}
381 
382 		a->short_desc = _("Select the primary partition containing the installation.");
383 		a->cancel_desc = _("Return to Welcome Menu");
384 		fn_select_slice(a);
385 
386 		if (!a->result || storage_get_selected_slice(a->s) == NULL) {
387 			state = state_welcome;
388 			return;
389 		}
390 	}
391 
392 	a->cfg_root = "mnt";
393 
394 	if (during_install == 0) {
395 		switch (dfui_be_present_dialog(a->c, _("Select file system"),
396 		    _("HAMMER|UFS|Return to Welcome Menu"),
397 		    _("Please select the file system installed on the disk.\n\n")))
398 		{
399 		case 1:
400 			/* HAMMER */
401 			use_hammer = 1;
402 			break;
403 		case 2:
404 			/* UFS */
405 			use_hammer = 0;
406 			break;
407 		case 3:
408 			state = state_welcome;
409 			return;
410 			/* NOTREACHED */
411 			break;
412 		default:
413 			abort_backend();
414 			break;
415 		}
416 	}
417 
418 	if (!mount_target_system(a)) {
419 		inform(a->c, _("Target system could not be mounted."));
420 		state = state_welcome;
421 		return;
422 	}
423 
424 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
425 	    _("The options on this menu allow you to configure a "
426 	    "%s system after it has already been "
427 	    "installed."), OPERATING_SYSTEM_NAME);
428 
429 	while (!done) {
430 		f = dfui_form_create(
431 		    "configure_menu",
432 		    _("Configure an Installed System"),
433 		    msg_buf[0],
434 		    "",
435 		    "p", "role", "menu",
436 
437 		    "a", "set_timezone",
438 		    _("Select timezone"),
439 		    _("Set the Time Zone of your physical location"), "",
440 		    "a", "set_datetime",
441 		    _("Set date and time"),
442 		    _("Set the Time and Date of your machine"), "",
443 
444 		    "a", "set_kbdmap",
445 		    _("Set keyboard map"),
446 		    _("Set what kind of keyboard layout you have"), "",
447 		    "a", "root_passwd",	_("Set root password"),
448 		    _("Set the password that the root (superuser) account will use"), "",
449 		    "a", "add_user", _("Add a user"),
450 		    _("Add a user to the system"), "",
451 		    "a", "assign_ip", _("Configure network interfaces"),
452 		    _("Set up network interfaces (NICs, ethernet, TCP/IP, etc)"), "",
453 		    "a", "assign_hostname_domain",
454 		    _("Configure hostname and domain"),
455 		    _("Configure the hostname and domain for this system"), "",
456 		    /*
457 		    "a", "select_services", "Select Services",
458 		    "Enable/Disable system services (servers, daemons, etc.)", "",
459 		    */
460 		    "a", "set_vidfont",
461 		    _("Set console font"),
462 		    _("Set how the characters on your video console look"), "",
463 		    "a", "set_scrnmap",
464 		    _("Set screen map"),
465 		    _("Set how characters are translated before console display"), "",
466 		    /*
467 		    "a", "install_pkgs", _("Install extra software packages"),
468 		    _("Install third-party software packages from the LiveCD"), "",
469 		    */
470 		    "a", "remove_pkgs",	_("Remove software packages"),
471 		    _("Remove third-party software packages from the installed system"), "",
472 
473 		    "a", "cancel", _("Return to Welcome Menu"), "", "",
474 		    "p", "accelerator", "ESC",
475 
476 		    NULL
477 		);
478 
479 		if (!dfui_be_present(a->c, f, &r))
480 			abort_backend();
481 
482 		/* XXX set up a */
483 		a->cfg_root = "mnt/";
484 		if (strcmp(dfui_response_get_action_id(r), "root_passwd") == 0) {
485 			fn_root_passwd(a);
486 		} else if (strcmp(dfui_response_get_action_id(r), "add_user") == 0) {
487 			fn_add_user(a);
488 		} else if (strcmp(dfui_response_get_action_id(r), "install_pkgs") == 0) {
489 			fn_install_packages(a);
490 		} else if (strcmp(dfui_response_get_action_id(r), "remove_pkgs") == 0) {
491 			fn_remove_packages(a);
492 		} else if (strcmp(dfui_response_get_action_id(r), "assign_ip") == 0) {
493 			fn_assign_ip(a);
494 		} else if (strcmp(dfui_response_get_action_id(r), "assign_hostname_domain") == 0) {
495 			fn_assign_hostname_domain(a);
496 		} else if (strcmp(dfui_response_get_action_id(r), "select_services") == 0) {
497 			fn_select_services(a);
498 		} else if (strcmp(dfui_response_get_action_id(r), "set_kbdmap") == 0) {
499 			fn_set_kbdmap(a);
500 		} else if (strcmp(dfui_response_get_action_id(r), "set_vidfont") == 0) {
501 			fn_set_vidfont(a);
502 		} else if (strcmp(dfui_response_get_action_id(r), "set_scrnmap") == 0) {
503 			fn_set_scrnmap(a);
504 		} else if (strcmp(dfui_response_get_action_id(r), "set_timezone") == 0) {
505 			fn_set_timezone(a);
506 		} else if (strcmp(dfui_response_get_action_id(r), "set_datetime") == 0) {
507 			fn_assign_datetime(a);
508 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
509 			state = state_welcome;
510 			done = 1;
511 		}
512 
513 		dfui_form_free(f);
514 		dfui_response_free(r);
515 	}
516 
517 	/*
518 	 * Before unmounting the system, write out any changes to rc.conf.
519 	 */
520 	config_vars_write(rc_conf, CONFIG_TYPE_SH,
521 	    "%s%setc/rc.conf", a->os_root, a->cfg_root);
522 
523 	/*
524 	 * Clear out configuration variable table in memory.
525 	 */
526 	config_vars_free(rc_conf);
527 	rc_conf = config_vars_new();
528 
529 	/*
530 	 * Finally, unmount the system we mounted on /mnt.
531 	 */
532 	cmds = commands_new();
533 	unmount_all_under(a, cmds, "%smnt", a->os_root);
534 	commands_execute(a, cmds);
535 	commands_free(cmds);
536 }
537 
538 void
539 state_utilities_menu(struct i_fn_args *a)
540 {
541 	struct dfui_form *f;
542 	struct dfui_response *r;
543 
544 	if (!survey_storage(a)) {
545 		inform(a->c, _("Errors occurred while probing "
546 		    "the system for its storage capabilities."));
547 	}
548 
549 	f = dfui_form_create(
550 	    "utilities_menu",
551 	    _("Live CD Utilities Menu"),
552 	    _("On these submenus you will find utilities to help "
553 	    "you set up your Live CD environment, diagnose "
554 	    "and analyse this system, and work with "
555 	    "the devices attached to this computer."),
556 	    "",
557 	    "p", "role", "menu",
558 	    "a", "environment", _("LiveCD Environment"),
559 	    _("Configure the LiveCD Environment"), "",
560 	    "a", "diagnostics", _("System Diagnostics"),
561 	    _("Probe and display detailed information about this system"), "",
562 	    "a", "diskutil", _("Disk Utilities"),
563 	    _("Format and check hard drives and floppy disks"), "",
564 	    "a", "livecd", _("Exit to Live CD"),
565 	    _("Exit this program to a login prompt with access to the LiveCD"), "",
566 	    "a", "reboot",
567 	    _("Reboot this Computer"), "", "",
568 	    "a", "cancel",
569 	    _("Return to Welcome Menu"), "", "",
570 	    "p", "accelerator", "ESC",
571 	    NULL
572 	);
573 
574 	if (!dfui_be_present(a->c, f, &r))
575 		abort_backend();
576 
577 	if (strcmp(dfui_response_get_action_id(r), "environment") == 0)
578 		state = state_environment_menu;
579 	else if (strcmp(dfui_response_get_action_id(r), "diagnostics") == 0)
580 		state = state_diagnostics_menu;
581 	else if (strcmp(dfui_response_get_action_id(r), "diskutil") == 0)
582 		state = state_diskutil_menu;
583 	else if (strcmp(dfui_response_get_action_id(r), "livecd") == 0)
584 		state = NULL;
585 	else if (strcmp(dfui_response_get_action_id(r), "reboot") == 0)
586 		state = state_reboot;
587 	else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0)
588 		state = state_welcome;
589 
590 	dfui_form_free(f);
591 	dfui_response_free(r);
592 }
593 
594 void
595 state_environment_menu(struct i_fn_args *a)
596 {
597 	struct dfui_form *f;
598 	struct dfui_response *r;
599 	int done = 0;
600 	char msg_buf[2][1024];
601 
602 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
603 	    _("On this menu you will find utilities to help you "
604 	    "set up your Live CD environment.\n\nNote "
605 	    "that these functions affect only the LiveCD "
606 	    "environment you are currently using, and they will "
607 	    "not affect any system that may be installed on "
608 	    "this computer UNLESS you subsequently choose to "
609 	    "install %s from this environment, in which "
610 	    "case they will be copied to the newly installed "
611 	    "system."), OPERATING_SYSTEM_NAME);
612 
613 	while (!done) {
614 		f = dfui_form_create(
615 		    "environment_menu",
616 		    _("Live CD Environment Menu"),
617 		    msg_buf[0],
618 		    "",
619 		    "p", "role", "menu",
620 
621 		    "a", "set_timezone",
622 		    _("Select timezone"),
623 		    _("Set the Time Zone of your physical location"), "",
624 		    "a", "set_datetime",
625 		    _("Set date and time"),
626 		    _("Set the Time and Date of your machine"), "",
627 
628 		    "a", "set_kbdmap",
629 		    _("Set keyboard map"),
630 		    _("Set what kind of keyboard layout you have"), "",
631 		    "a", "set_vidfont",
632 		    _("Set console font"),
633 		    _("Set how the characters on your video console look"), "",
634 		    "a", "set_scrnmap",
635 		    _("Set screen map"),
636 		    _("Set how characters are translated before console display"), "",
637 
638 		    "a", "assign_hostname_domain",
639 		    _("Configure hostname and domain"),
640 		    _("Configure the hostname and domain for this system"), "",
641 		    "a", "assign_ip",
642 		    _("Configure network interfaces"),
643 		    _("Set up network interfaces (NICs, ethernet, TCP/IP, etc)"), "",
644 
645 		    "a", "cancel",
646 		    _("Return to Utilities Menu"), "", "",
647 		    "p", "accelerator", "ESC",
648 
649 		    NULL
650 		);
651 
652 		if (!dfui_be_present(a->c, f, &r))
653 			abort_backend();
654 
655 		/* Set up a */
656 		a->cfg_root = "";
657 		if (strcmp(dfui_response_get_action_id(r), "set_kbdmap") == 0) {
658 			fn_set_kbdmap(a);
659 		} else if (strcmp(dfui_response_get_action_id(r), "set_vidfont") == 0) {
660 			fn_set_vidfont(a);
661 		} else if (strcmp(dfui_response_get_action_id(r), "set_scrnmap") == 0) {
662 			fn_set_scrnmap(a);
663 		} else if (strcmp(dfui_response_get_action_id(r), "assign_hostname_domain") == 0) {
664 			fn_assign_hostname_domain(a);
665 		} else if (strcmp(dfui_response_get_action_id(r), "assign_ip") == 0) {
666 			fn_assign_ip(a);
667 		} else if (strcmp(dfui_response_get_action_id(r), "set_timezone") == 0) {
668 			fn_set_timezone(a);
669 		} else if (strcmp(dfui_response_get_action_id(r), "set_datetime") == 0) {
670 			fn_assign_datetime(a);
671 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
672 			state = state_utilities_menu;
673 			done = 1;
674 		}
675 
676 		dfui_form_free(f);
677 		dfui_response_free(r);
678 	}
679 }
680 
681 void
682 state_diagnostics_menu(struct i_fn_args *a)
683 {
684 	struct dfui_form *f;
685 	struct dfui_action *k;
686 	struct dfui_response *r;
687 	int done = 0;
688 
689 	while (!done) {
690 		f = dfui_form_create(
691 		    "utilities_menu",
692 		    _("Live CD Diagnostics Menu"),
693 		    _("These functions can help you diagnose this system."),
694 		    "",
695 		    "p", "role", "menu",
696 
697 		    "a", "show_dmesg",
698 		    _("Display system startup messages"),
699 		    _("Display system startup messages (dmesg)"), "",
700 		    "a", "pciconf",
701 		    _("Display PCI devices"),
702 		    _("Display PCI devices (pciconf)"), "",
703 		    "a", "pnpinfo",
704 		    _("Display Plug'n'Play ISA devices"),
705 		    _("Display Plug'n'Play ISA devices (pnpinfo)"), "",
706 		    "a", "natacontrol",
707 		    _("Display ATA devices"),
708 		    _("Display ATA devices (natacontrol)"), "",
709 		    NULL
710 		);
711 
712 		k = dfui_form_action_add(f, "cancel",
713 		    dfui_info_new(_("Return to Utilities Menu"), "", ""));
714 		dfui_action_property_set(k, "accelerator", "ESC");
715 
716 		if (!dfui_be_present(a->c, f, &r))
717 			abort_backend();
718 
719 		/* XXX set up a */
720 		if (strcmp(dfui_response_get_action_id(r), "show_dmesg") == 0) {
721 			fn_show_dmesg(a);
722 		} else if (strcmp(dfui_response_get_action_id(r), "pciconf") == 0) {
723 			fn_show_pciconf(a);
724 		} else if (strcmp(dfui_response_get_action_id(r), "pnpinfo") == 0) {
725 			fn_show_pnpinfo(a);
726 		} else if (strcmp(dfui_response_get_action_id(r), "natacontrol") == 0) {
727 			fn_show_natacontrol(a);
728 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
729 			state = state_utilities_menu;
730 			done = 1;
731 		}
732 
733 		dfui_form_free(f);
734 		dfui_response_free(r);
735 	}
736 }
737 
738 void
739 state_diskutil_menu(struct i_fn_args *a)
740 {
741 	struct dfui_form *f;
742 	struct dfui_action *k;
743 	struct dfui_response *r;
744 	int done = 0;
745 
746 	while (!done) {
747 		f = dfui_form_create(
748 		    "utilities_menu",
749 		    _("Disk Utilities Menu"),
750 		    _("These functions let you manipulate the storage devices "
751 		    "attached to this computer."),
752 		    "",
753 
754 		    "p", "role", "menu",
755 
756 		    "a", "format_hdd",
757 		    _("Format a hard disk drive"), "", "",
758 		    "a", "wipe_start_of_disk",
759 		    _("Wipe out the start of a disk"), "", "",
760 		    "a", "wipe_start_of_slice",
761 		    _("Wipe out the start of a primary partition"), "", "",
762 		    "a", "install_bootblocks",
763 		    _("Install bootblocks on disks"), "", "",
764 		    "a", "format_msdos_floppy",
765 		    _("Format an MSDOS floppy"), "", "",
766 		    NULL
767 		);
768 
769 		if (is_file("%sboot/cdboot.flp.bz2", a->os_root)) {
770 			dfui_form_action_add(f, "create_cdboot_floppy",
771 			    dfui_info_new(_("Create a CDBoot floppy"),
772 			    "",
773 			    ""));
774 		}
775 
776 		k = dfui_form_action_add(f, "cancel",
777 		    dfui_info_new(_("Return to Utilities Menu"), "", ""));
778 		dfui_action_property_set(k, "accelerator", "ESC");
779 
780 		if (!dfui_be_present(a->c, f, &r))
781 			abort_backend();
782 
783 		/* XXX set up a */
784 		if (strcmp(dfui_response_get_action_id(r), "format_hdd") == 0) {
785 			storage_set_selected_disk(a->s, NULL);
786 			storage_set_selected_slice(a->s, NULL);
787 			fn_format_disk(a);
788 		} else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_disk") == 0) {
789 			fn_wipe_start_of_disk(a);
790 		} else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_slice") == 0) {
791 			fn_wipe_start_of_slice(a);
792 		} else if (strcmp(dfui_response_get_action_id(r), "install_bootblocks") == 0) {
793 			a->short_desc = _("Select the disks on which "
794 			    "you wish to install bootblocks.");
795 			a->cancel_desc = _("Return to Utilities Menu");
796 			fn_install_bootblocks(a);
797 		} else if (strcmp(dfui_response_get_action_id(r), "format_msdos_floppy") == 0) {
798 			fn_format_msdos_floppy(a);
799 		} else if (strcmp(dfui_response_get_action_id(r), "create_cdboot_floppy") == 0) {
800 			fn_create_cdboot_floppy(a);
801 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
802 			state = state_utilities_menu;
803 			done = 1;
804 		}
805 
806 		dfui_form_free(f);
807 		dfui_response_free(r);
808 	}
809 }
810 
811 /** INSTALLER STATES **/
812 
813 /*
814  * state_begin_upgrade: Ask the user where the freebsd
815  * 4.X install is and make sure its safe to proceed.
816  *
817  */
818 void
819 state_begin_upgrade(struct i_fn_args *a)
820 {
821         //struct dfui_form *f = NULL;
822         //struct dfui_response *r = NULL;
823         //int done = 0;
824 
825         if (storage_get_selected_disk(a->s) == NULL || storage_get_selected_slice(a->s) == NULL) {
826 		if (!survey_storage(a)) {
827 			inform(a->c, _("Errors occurred while probing "
828 			    "the system for its storage capabilities."));
829 		}
830 
831                 a->short_desc = _("Select the disk containing the installation that you would like to upgrade.");
832                 a->cancel_desc = _("Return to Welcome Menu");
833                 fn_select_disk(a);
834                 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
835                         state = state_welcome;
836                         return;
837                 }
838 
839                 a->short_desc = _("Select the primary partition containing the installation you would like to upgrade.");
840                 a->cancel_desc = _("Return to Welcome Menu");
841                 fn_select_slice(a);
842 
843                 if (!a->result || storage_get_selected_slice(a->s) == NULL) {
844                         state = state_welcome;
845                         return;
846                 }
847         }
848 
849         a->cfg_root = "mnt";
850         if (!mount_target_system(a)) {
851                 inform(a->c, _("Target system could not be mounted."));
852                 state = state_welcome;
853                 return;
854         }
855 }
856 
857 /*
858  * state_begin_install: Briefly describe the install process
859  * to the user, and let them proceed (or not.)
860  */
861 void
862 state_begin_install(struct i_fn_args *a)
863 {
864 	struct dfui_form *f;
865 	struct dfui_response *r;
866 	char msg_buf[3][1024];
867 
868 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
869 	    _("This experimental application will install %s"
870 	    " on one of the hard disk drives attached to this computer. "
871 	    "It has been designed to make it easy to install "
872 	    "%s in the typical case. "
873 	    "If you have special requirements that are not addressed "
874 	    "by this installer, or if you have problems using it, you "
875 	    "are welcome to install %s manually. "
876 	    "To do so select Exit to Live CD, login as root, and follow "
877 	    "the instructions given in the file /README ."
878 	    "\n\n"
879 	    "NOTE! As with any installation process, YOU ARE "
880 	    "STRONGLY ENCOURAGED TO BACK UP ANY IMPORTANT DATA ON THIS "
881 	    "COMPUTER BEFORE PROCEEDING!"
882 	    ""),
883 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME,
884 	    OPERATING_SYSTEM_NAME);
885 
886 	snprintf(msg_buf[1], sizeof(msg_buf[1]),
887 	    _("Some situations in which you might not wish to use this "
888 	    "installer are:\n\n"
889 	    "- you want to install %s onto a "
890 	    "logical/extended partition;\n"
891 	    "- you want to install %s "
892 	    "onto a ``dangerously dedicated'' disk; or\n"
893 	    "- you want full and utter control over the install process."
894 	    ""),
895 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
896 
897 	snprintf(msg_buf[2], sizeof(msg_buf[2]),
898 	    _("Install %s"), OPERATING_SYSTEM_NAME);
899 
900 	f = dfui_form_create(
901 	    "begin_install",
902 	    _("Begin Installation"),
903 	    msg_buf[0],
904 
905 	    msg_buf[1],
906 	    "p", "special", "dfinstaller_begin_install",
907 	    "p", "minimum_width", "76",
908 
909 	    "a", "proceed", msg_buf[2],
910 	    "", "",
911 	    "a", "cancel", _("Return to Welcome Menu"),
912 	    "", "",
913 	    "p", "accelerator", "ESC",
914 	    "a", "livecd", _("Exit to Live CD"),
915 	    "", "",
916 	    NULL
917 	);
918 
919 	if (!dfui_be_present(a->c, f, &r))
920 		abort_backend();
921 
922 	if (strcmp(dfui_response_get_action_id(r), "proceed") == 0) {
923 		if (!survey_storage(a)) {
924 			inform(a->c, _("Errors occurred while probing "
925 			    "the system for its storage capabilities."));
926 		}
927 		state = state_select_disk;
928 	} else if (strcmp(dfui_response_get_action_id(r), "livecd") == 0) {
929 		state = NULL;
930 	} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
931 		state = state_welcome;
932 	}
933 
934 	dfui_form_free(f);
935 	dfui_response_free(r);
936 }
937 
938 /*
939  * state_select_disk: ask the user on which physical disk they wish
940  * to install DragonFly.
941  */
942 void
943 state_select_disk(struct i_fn_args *a)
944 {
945 	struct disk *d;
946 	int num_disks = 0;
947 	char msg_buf[1][1024];
948 
949 	for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d))
950 		num_disks++;
951 
952 	if (num_disks == 0) {
953 		inform(a->c, _("The installer could not find any disks suitable "
954 		    "for installation (IDE or SCSI) attached to this "
955 		    "computer.  If you wish to install %s"
956 		    " on an unorthodox storage device, you will have to "
957 		    "exit to a LiveCD command prompt and install it "
958 		    "manually, using the file /README as a guide."),
959 		    OPERATING_SYSTEM_NAME);
960 		state = state_welcome;
961 		return;
962 	}
963 
964 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
965 	    _("Select a disk on which to install %s"),
966 	    OPERATING_SYSTEM_NAME);
967 	a->short_desc = msg_buf[0];
968 	a->cancel_desc = _("Return to Begin Installation");
969 	fn_select_disk(a);
970 	if (!a->result || storage_get_selected_disk(a->s) == NULL) {
971 		state = state_begin_install;
972 	} else {
973 #if 0
974 		if (disk_get_capacity(storage_get_selected_disk(a->s)) < DISK_MIN) {
975 			inform(a->c, _("WARNING: you should have a disk "
976 			    "at least %dM in size, or "
977 			    "you may encounter problems trying to "
978 			    "install %s."), DISK_MIN, OPERATING_SYSTEM_NAME);
979 		}
980 #endif
981 		state = state_format_disk;
982 	}
983 }
984 
985 void
986 state_ask_fs(struct i_fn_args *a)
987 {
988 	use_hammer = 0;
989 
990 	switch (dfui_be_present_dialog(a->c, _("Select file system"),
991 	    _("Use HAMMER|Use UFS|Return to Select Disk"),
992 	    _("Please select the file system you want to use with %s.\n\n"
993 	      "HAMMER is the new %s file system.  UFS is the traditional BSD file system."),
994 	    OPERATING_SYSTEM_NAME,
995 	    OPERATING_SYSTEM_NAME))
996 	{
997 	case 1:
998 		/* HAMMER */
999 		use_hammer = 1;
1000 		break;
1001 	case 2:
1002 		/* UFS */
1003 		break;
1004 	case 3:
1005 		state = state_select_disk;
1006 		return;
1007 		/* NOTREACHED */
1008 		break;
1009 	default:
1010 		abort_backend();
1011 		break;
1012 	}
1013 	state = state_create_subpartitions;
1014 }
1015 
1016 /*
1017  * state_format_disk: ask the user if they wish to format the disk they
1018  * selected.
1019  */
1020 void
1021 state_format_disk(struct i_fn_args *a)
1022 {
1023 	switch (dfui_be_present_dialog(a->c, _("How Much Disk?"),
1024 	    _("Use Entire Disk|Use Part of Disk|Return to Select Disk"),
1025 	    _("Select how much of this disk you want to use for %s.\n\n%s"),
1026 	    OPERATING_SYSTEM_NAME,
1027 	    disk_get_desc(storage_get_selected_disk(a->s)))) {
1028 	case 1:
1029 		/* Entire Disk */
1030 		if (measure_activated_swap_from_disk(a, storage_get_selected_disk(a->s)) > 0) {
1031 			if (swapoff_all(a) == NULL) {
1032 				inform(a->c, _("Warning: swap could not be turned off."));
1033 				state = state_select_disk;
1034 				return;
1035 			}
1036 		}
1037 
1038 		fn_format_disk(a);
1039 		if (a->result)
1040 			state = state_ask_fs;
1041 		else
1042 			state = state_format_disk;
1043 		break;
1044 	case 2:
1045 		/* Part of Disk */
1046 		state = state_select_slice;
1047 		break;
1048 	case 3:
1049 		/* Return */
1050 		state = state_select_disk;
1051 		break;
1052 	default:
1053 		abort_backend();
1054 		break;
1055 	}
1056 }
1057 
1058 /*
1059  * state_select_slice: ask the user which slice they wish to install
1060  * DragonFly on.  In order to avoid confusing them, refer to it as
1061  * a primary partition, but tell them what BSD has traditionally called
1062  * it, too.
1063  */
1064 void
1065 state_select_slice(struct i_fn_args *a)
1066 {
1067 	char msg_buf[1][1024];
1068 
1069 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1070 	    _("Select the existing primary partition (also "
1071 	    "known as a `slice' in the BSD tradition) on "
1072 	    "which to install %s.\n\n"
1073 	    "Note that if you do not have any existing "
1074 	    "primary partitions on this disk, you must "
1075 	    "first create some. This installer does not "
1076 	    "currently have the ability to do this, so "
1077 	    "you will have to exit and run fdisk (in "
1078 	    "DOS or *BSD) or parted (in Linux) to do so."),
1079 	    OPERATING_SYSTEM_NAME);
1080 
1081 	a->short_desc = msg_buf[0];
1082 	a->cancel_desc = _("Return to Select Disk");
1083 	fn_select_slice(a);
1084 	if (!a->result || storage_get_selected_slice(a->s) == NULL) {
1085 		state = state_select_disk;
1086 	} else {
1087 		if (measure_activated_swap_from_slice(a, storage_get_selected_disk(a->s),
1088 		    storage_get_selected_slice(a->s)) > 0) {
1089 			if (swapoff_all(a) == NULL) {
1090 				inform(a->c, _("Warning: swap could not be turned off."));
1091 				state = state_select_slice;
1092 				return;
1093 			}
1094 		}
1095 
1096 		if (slice_get_capacity(storage_get_selected_slice(a->s)) < DISK_MIN) {
1097 			inform(a->c, _("WARNING: you should have a primary "
1098 			    "partition at least %dM in size, or "
1099 			    "you may encounter problems trying to "
1100 			    "install %s."), DISK_MIN, OPERATING_SYSTEM_NAME);
1101 		}
1102 
1103 		if (confirm_dangerous_action(a->c,
1104 		    _("WARNING!  ALL data in primary partition #%d,\n\n%s\n\non the "
1105 		    "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
1106 		    "ABSOLUTELY SURE you wish to take this action?  This is "
1107 		    "your LAST CHANCE to cancel!"),
1108 		    slice_get_number(storage_get_selected_slice(a->s)),
1109 		    slice_get_desc(storage_get_selected_slice(a->s)),
1110 		    disk_get_desc(storage_get_selected_disk(a->s)))) {
1111 			if (!format_slice(a)) {
1112 				inform(a->c, _("Primary partition #%d was "
1113 				    "not correctly formatted, and may "
1114 				    "now be in an inconsistent state. "
1115 				    "We recommend re-formatting it "
1116 				    "before proceeding."),
1117 				    slice_get_number(storage_get_selected_slice(a->s)));
1118 			} else {
1119 				inform(a->c, _("Primary partition #%d was formatted."),
1120 				    slice_get_number(storage_get_selected_slice(a->s)));
1121 				state = state_ask_fs;
1122 			}
1123 		} else {
1124 			inform(a->c, _("Action cancelled - no primary partitions were formatted."));
1125 			state = state_select_slice;
1126 		}
1127 	}
1128 }
1129 
1130 /*
1131  * state_create_subpartitions: let the user specify what subpartitions they
1132  * want on the disk, how large each should be, and where it should be mounted.
1133  */
1134 void
1135 state_create_subpartitions(struct i_fn_args *a)
1136 {
1137 	struct commands *cmds;
1138 
1139 	if (measure_activated_swap_from_slice(a, storage_get_selected_disk(a->s),
1140 	    storage_get_selected_slice(a->s)) > 0) {
1141 		if (swapoff_all(a) == NULL) {
1142 			inform(a->c, _("Warning: swap could not be turned off."));
1143 			state = disk_get_formatted(storage_get_selected_disk(a->s)) ?
1144 			    state_select_disk : state_select_slice;
1145 			return;
1146 		}
1147 	}
1148 
1149 	cmds = commands_new();
1150 
1151 	/*
1152 	 * Auto-disklabel the slice.
1153 	 * NB: one cannot use "/dev/adXsY" here -
1154 	 * it must be in the form "adXsY".
1155 	 */
1156 	command_add(cmds, "%s%s -W %s",
1157 	    a->os_root, cmd_name(a, "DISKLABEL64"),
1158 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1159 	command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
1160 	    a->os_root, cmd_name(a, "DD"),
1161 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1162 	command_add(cmds, "%s%s -B -r -w %s auto",
1163 	    a->os_root, cmd_name(a, "DISKLABEL64"),
1164 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1165 	commands_execute(a, cmds);
1166 	commands_free(cmds);
1167 
1168 	if (use_hammer)
1169 		fn_create_subpartitions_hammer(a);
1170 	else
1171 		fn_create_subpartitions_ufs(a);
1172 
1173 	if (a->result) {
1174 		state = state_install_os;
1175 	} else {
1176 		state = disk_get_formatted(storage_get_selected_disk(a->s)) ?
1177 		    state_select_disk : state_select_slice;
1178 	}
1179 }
1180 
1181 /*
1182  * state_install_os: actually put DragonFly on the disk.
1183  */
1184 void
1185 state_install_os(struct i_fn_args *a)
1186 {
1187 	struct dfui_form *f;
1188 	struct dfui_response *r;
1189 	char msg_buf[1][1024];
1190 
1191 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1192 	    _("Everything is now ready to install the actual files which "
1193 	    "comprise the %s operating system "
1194 	    "on the selected partition of the selected disk.\n\n"
1195 	    "Note that this process will take quite a while to finish. "
1196 	    "You may wish to take a break now and come back to the "
1197 	    "computer in a short while."),
1198 	    OPERATING_SYSTEM_NAME);
1199 
1200 	f = dfui_form_create(
1201 	    "install_os",
1202 	    _("Install OS"),
1203 	    msg_buf[0],
1204 
1205 	    "",
1206 
1207 	    "p", "role", "confirm",
1208 	    "p", "special", "dfinstaller_install_os",
1209 
1210 	    "a", "ok", _("Begin Installing Files"), "", "",
1211 	    "a", "cancel", _("Return to Create Subpartitions"), "", "",
1212 	    "p", "accelerator", "ESC",
1213 
1214 	    NULL
1215 	);
1216 
1217 	if (!dfui_be_present(a->c, f, &r))
1218 		abort_backend();
1219 
1220 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1221 		state = state_create_subpartitions;
1222 	} else {
1223 		fn_install_os(a);
1224 		if (a->result)
1225 			state = state_install_bootstrap;
1226 	}
1227 
1228 	dfui_form_free(f);
1229 	dfui_response_free(r);
1230 }
1231 
1232 /*
1233  * state_install_bootstrap: put boot0 bootblocks on selected disks.
1234  */
1235 void
1236 state_install_bootstrap(struct i_fn_args *a)
1237 {
1238 	char msg_buf[1][1024];
1239 
1240 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1241 	    _("You may now wish to install bootblocks on one or more disks. "
1242 	    "If you already have a boot manager installed, you can skip "
1243 	    "this step (but you may have to configure your boot manager "
1244 	    "separately.)  If you installed %s on a disk other "
1245 	    "than your first disk, you will need to put the bootblock "
1246 	    "on at least your first disk and the %s disk."),
1247 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
1248 
1249 	a->short_desc = msg_buf[0];
1250 	a->cancel_desc = _("Skip this Step");
1251 	fn_install_bootblocks(a);
1252 	state = state_finish_install;
1253 }
1254 
1255 /*
1256  * Finish up the install.
1257  */
1258 void
1259 state_finish_install(struct i_fn_args *a)
1260 {
1261 	char msg_buf[1][1024];
1262 	during_install = 1;
1263 
1264 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1265 	    "%s is Installed!",
1266 	    OPERATING_SYSTEM_NAME);
1267 
1268 	switch (dfui_be_present_dialog(a->c, msg_buf[0],
1269 	    _("Configure this System|Reboot|Return to Welcome Menu"),
1270 	    _("Congratulations!\n\n"
1271 	    "%s has successfully been installed on "
1272 	    "this computer. You may now proceed to configure "
1273 	    "the installation. Alternately, you may wish to "
1274 	    "reboot the computer and boot into the installed "
1275 	    "system to confirm that it works."),
1276 	    OPERATING_SYSTEM_NAME)) {
1277 	case 1:
1278 		state = state_configure_menu;
1279 		break;
1280 	case 2:
1281 		state = state_reboot;
1282 		break;
1283 	case 3:
1284 		state = state_welcome;
1285 		break;
1286 	default:
1287 		abort_backend();
1288 	}
1289 }
1290 
1291 /*
1292  * state_reboot: reboot the machine.
1293  */
1294 void
1295 state_reboot(struct i_fn_args *a)
1296 {
1297 	struct dfui_form *f;
1298 	struct dfui_response *r;
1299 
1300 	f = dfui_form_create(
1301 	    "reboot",
1302 	    _("Reboot"),
1303 	    _("This machine is about to be shut down. "
1304 	    "After the machine has reached its shutdown state, "
1305 	    "you may remove the CD from the CD-ROM drive tray "
1306 	    "and press Enter to reboot from the HDD."),
1307 
1308 	    "",
1309 
1310 	    "p", "role", "confirm",
1311 
1312 	    "a", "ok", _("Reboot"), "", "",
1313 	    "a", "cancel", _("Return to Welcome Menu"), "", "",
1314 	    "p", "accelerator", "ESC",
1315 	    NULL
1316 	);
1317 
1318 	if (!dfui_be_present(a->c, f, &r))
1319 		abort_backend();
1320 
1321 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1322 		state = state_welcome;
1323 	} else {
1324 		do_reboot = 1;
1325 		state = NULL;
1326 	}
1327 
1328 	dfui_form_free(f);
1329 	dfui_response_free(r);
1330 }
1331 
1332 /*
1333  *
1334  *  state_setup_remote_installation_server:
1335  *  Setup a remote boot installation environment where a machine
1336  *  can boot via DHCP/TFTP/NFS and have a running environment
1337  *  where the installer can setup the machine.
1338  *
1339  */
1340 void
1341 state_setup_remote_installation_server(struct i_fn_args *a)
1342 {
1343         FILE *p;
1344         struct commands *cmds;
1345         struct dfui_form *f;
1346 	struct dfui_action *k;
1347         struct dfui_response *r;
1348         char *word;
1349         char interface[256];
1350         char line[256];
1351 
1352         switch (dfui_be_present_dialog(a->c, _("Enable Netboot Installation Services?"),
1353             _("Enable NetBoot Installation Services|No thanks"),
1354             _("NetBoot Installation Services allows this machine to become "
1355             "a Installation Server that will allow the clients to boot over the network "
1356 	    "via PXE and start the Installation Environment."
1357 	    "\n\n*NOTE!*  This will assign the IP Address of 10.1.0.1/24 to the selected interface."
1358             "\n\nWould you like to provision this machine to serve up the LiveCD/Installer?"))) {
1359 		case 1:
1360 			/*
1361 			 * Get interface list.
1362 			 */
1363 			p = popen("/sbin/ifconfig -l", "r");
1364 			/* XXX it's possible (though extremely unlikely) this will fail. */
1365 			while (fgets(line, 255, p) != NULL)
1366 				line[strlen(line) - 1] = '\0';
1367 			pclose(p);
1368 
1369 			f = dfui_form_create(
1370 			    "assign_ip",
1371 			    _("Setup NetBoot Installation Environment"),
1372 			    _("Please select which interface you would like to configure:"),
1373 			    "",
1374 			    "p",        "role", "menu",
1375 			    NULL
1376 			);
1377 
1378 			/* Loop through array. */
1379 			word = strtok(line, " \t");
1380 			while (word != NULL) {
1381 				dfui_form_action_add(f, word,
1382 				    dfui_info_new(word, "", ""));
1383 				word = strtok(NULL, " ");
1384 			}
1385 
1386 			k = dfui_form_action_add(f, "cancel",
1387 			    dfui_info_new("Cancel", "", ""));
1388 			dfui_action_property_set(k, "accelerator", "ESC");
1389 
1390 			if (!dfui_be_present(a->c, f, &r))
1391 			abort_backend();
1392 
1393 			strlcpy(interface, dfui_response_get_action_id(r), 256);
1394 
1395 			if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1396 				dfui_form_free(f);
1397 				dfui_response_free(r);
1398 				return;
1399 			}
1400 
1401 			/*
1402 			 *
1403 			 * Issues the necessary commands to setup the remote boot environment
1404 			 *
1405 			 */
1406 			cmds = commands_new();
1407 			command_add(cmds, "%s%s %s 10.1.0.1 netmask 255.255.255.0",
1408 			    a->os_root, cmd_name(a, "IFCONFIG"), interface);
1409 			command_add(cmds, "%s%s -p %stftpdroot",
1410 			    a->os_root, cmd_name(a, "MKDIR"), a->tmp);
1411 			command_add(cmds, "%s%s %sboot/pxeboot %stftpdroot",
1412 			    a->os_root, cmd_name(a, "CP"), a->os_root, a->tmp);
1413 			command_add(cmds, "%s%s %s -ro -alldirs -maproot=root: -network 10.1.0.0 -mask 255.255.255.0 >> %setc/exports",
1414 			    a->os_root, cmd_name(a, "ECHO"), a->os_root, a->os_root);
1415 			command_add(cmds, "%s%s tftp dgram udp wait root %s%s tftpd -l -s %stftpdroot >> %setc/inetd.conf",
1416 			    a->os_root, cmd_name(a, "ECHO"),
1417 			    a->os_root, cmd_name(a, "TFTPD"),
1418 			    a->tmp, a->os_root);
1419 			command_add(cmds, "%s%s",
1420 			    a->os_root, cmd_name(a, "INETD"));
1421 			command_add(cmds, "%s%s %svar/db/dhcpd.leases",
1422 			    a->os_root, cmd_name(a, "TOUCH"), a->os_root);
1423 			command_add(cmds, "%s%s -cf /etc/dhcpd.conf >%sdev/null 2>&1",
1424 			    a->os_root, cmd_name(a, "DHCPD"), a->os_root);
1425 			command_add(cmds, "%s%s >%sdev/null 2>&1",
1426 			    a->os_root, cmd_name(a, "RPCBIND"), a->os_root);
1427 			command_add(cmds, "%s%s -ln >%sdev/null 2>&1",
1428 			    a->os_root, cmd_name(a, "MOUNTD"), a->os_root);
1429 			command_add(cmds, "%s%s -u -t -n 6 >%sdev/null 2>&1",
1430 			    a->os_root, cmd_name(a, "NFSD"), a->os_root);
1431 
1432 			if (commands_execute(a, cmds)) {
1433 				inform(a->c, _("NetBoot installation services are now started."));
1434 			} else {
1435 				inform(a->c, _("A failure occurred while provisioning the NetBoot environment.  Please check the logs."));
1436 			}
1437 
1438 			commands_free(cmds);
1439 			dfui_form_free(f);
1440 			dfui_response_free(r);
1441 
1442 			break;
1443 		case 2:
1444 
1445 			break;
1446 
1447 	};
1448 
1449 	state = state_welcome;
1450 
1451 }
1452 
1453 /*** MAIN ***/
1454 
1455 int
1456 flow(int transport, char *rendezvous, char *os_root,
1457      int booted_from_livecd __unused, int upgrade_menu_toggle __unused)
1458 {
1459 	struct i_fn_args *a;
1460 
1461 	rc_conf = config_vars_new();
1462 
1463 	if ((a = i_fn_args_new(os_root, DEFAULT_INSTALLER_TEMP,
1464 			       transport, rendezvous)) == NULL) {
1465 		return(0);
1466 	}
1467 
1468 	/*
1469 	 * XXX We can't handle this yet.
1470 	 *
1471 	   a->booted_from_livecd = booted_from_livecd;
1472 	   a->upgrade_menu_toggle = upgrade_menu_toggle;
1473 	*/
1474 	a->booted_from_livecd = 1;
1475 	a->upgrade_menu_toggle = 0;
1476 
1477 	/*
1478 	 * Execute the state machine here.  The global function pointer
1479 	 * variable `state' points to the next state_* function to execute.
1480 	 * Before it exits, this function should set `state' to the next
1481 	 * state to make a transition to, or NULL to indicate that the
1482 	 * state machine is finished.
1483 	 */
1484 #ifdef ENABLE_NLS
1485 	state = state_lang_menu;
1486 #else
1487 	state = state_welcome;
1488 #endif
1489 	for (; state != NULL; )
1490 		state(a);
1491 
1492 	config_vars_free(rc_conf);
1493 
1494 	i_fn_args_free(a);
1495 
1496 	return(do_reboot);
1497 }
1498