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 and remove mappings.
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 	if (remove_all_mappings(a) == NULL)
538 		inform(a->c, _("Warning: mappings could not be removed."));
539 }
540 
541 void
542 state_utilities_menu(struct i_fn_args *a)
543 {
544 	struct dfui_form *f;
545 	struct dfui_response *r;
546 
547 	if (!survey_storage(a)) {
548 		inform(a->c, _("Errors occurred while probing "
549 		    "the system for its storage capabilities."));
550 	}
551 
552 	f = dfui_form_create(
553 	    "utilities_menu",
554 	    _("Live CD Utilities Menu"),
555 	    _("On these submenus you will find utilities to help "
556 	    "you set up your Live CD environment, diagnose "
557 	    "and analyse this system, and work with "
558 	    "the devices attached to this computer."),
559 	    "",
560 	    "p", "role", "menu",
561 	    "a", "environment", _("LiveCD Environment"),
562 	    _("Configure the LiveCD Environment"), "",
563 	    "a", "diagnostics", _("System Diagnostics"),
564 	    _("Probe and display detailed information about this system"), "",
565 	    "a", "diskutil", _("Disk Utilities"),
566 	    _("Format and check hard drives and floppy disks"), "",
567 	    "a", "livecd", _("Exit to Live CD"),
568 	    _("Exit this program to a login prompt with access to the LiveCD"), "",
569 	    "a", "reboot",
570 	    _("Reboot this Computer"), "", "",
571 	    "a", "cancel",
572 	    _("Return to Welcome Menu"), "", "",
573 	    "p", "accelerator", "ESC",
574 	    NULL
575 	);
576 
577 	if (!dfui_be_present(a->c, f, &r))
578 		abort_backend();
579 
580 	if (strcmp(dfui_response_get_action_id(r), "environment") == 0)
581 		state = state_environment_menu;
582 	else if (strcmp(dfui_response_get_action_id(r), "diagnostics") == 0)
583 		state = state_diagnostics_menu;
584 	else if (strcmp(dfui_response_get_action_id(r), "diskutil") == 0)
585 		state = state_diskutil_menu;
586 	else if (strcmp(dfui_response_get_action_id(r), "livecd") == 0)
587 		state = NULL;
588 	else if (strcmp(dfui_response_get_action_id(r), "reboot") == 0)
589 		state = state_reboot;
590 	else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0)
591 		state = state_welcome;
592 
593 	dfui_form_free(f);
594 	dfui_response_free(r);
595 }
596 
597 void
598 state_environment_menu(struct i_fn_args *a)
599 {
600 	struct dfui_form *f;
601 	struct dfui_response *r;
602 	int done = 0;
603 	char msg_buf[2][1024];
604 
605 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
606 	    _("On this menu you will find utilities to help you "
607 	    "set up your Live CD environment.\n\nNote "
608 	    "that these functions affect only the LiveCD "
609 	    "environment you are currently using, and they will "
610 	    "not affect any system that may be installed on "
611 	    "this computer UNLESS you subsequently choose to "
612 	    "install %s from this environment, in which "
613 	    "case they will be copied to the newly installed "
614 	    "system."), OPERATING_SYSTEM_NAME);
615 
616 	while (!done) {
617 		f = dfui_form_create(
618 		    "environment_menu",
619 		    _("Live CD Environment Menu"),
620 		    msg_buf[0],
621 		    "",
622 		    "p", "role", "menu",
623 
624 		    "a", "set_timezone",
625 		    _("Select timezone"),
626 		    _("Set the Time Zone of your physical location"), "",
627 		    "a", "set_datetime",
628 		    _("Set date and time"),
629 		    _("Set the Time and Date of your machine"), "",
630 
631 		    "a", "set_kbdmap",
632 		    _("Set keyboard map"),
633 		    _("Set what kind of keyboard layout you have"), "",
634 		    "a", "set_vidfont",
635 		    _("Set console font"),
636 		    _("Set how the characters on your video console look"), "",
637 		    "a", "set_scrnmap",
638 		    _("Set screen map"),
639 		    _("Set how characters are translated before console display"), "",
640 
641 		    "a", "assign_hostname_domain",
642 		    _("Configure hostname and domain"),
643 		    _("Configure the hostname and domain for this system"), "",
644 		    "a", "assign_ip",
645 		    _("Configure network interfaces"),
646 		    _("Set up network interfaces (NICs, ethernet, TCP/IP, etc)"), "",
647 
648 		    "a", "cancel",
649 		    _("Return to Utilities Menu"), "", "",
650 		    "p", "accelerator", "ESC",
651 
652 		    NULL
653 		);
654 
655 		if (!dfui_be_present(a->c, f, &r))
656 			abort_backend();
657 
658 		/* Set up a */
659 		a->cfg_root = "";
660 		if (strcmp(dfui_response_get_action_id(r), "set_kbdmap") == 0) {
661 			fn_set_kbdmap(a);
662 		} else if (strcmp(dfui_response_get_action_id(r), "set_vidfont") == 0) {
663 			fn_set_vidfont(a);
664 		} else if (strcmp(dfui_response_get_action_id(r), "set_scrnmap") == 0) {
665 			fn_set_scrnmap(a);
666 		} else if (strcmp(dfui_response_get_action_id(r), "assign_hostname_domain") == 0) {
667 			fn_assign_hostname_domain(a);
668 		} else if (strcmp(dfui_response_get_action_id(r), "assign_ip") == 0) {
669 			fn_assign_ip(a);
670 		} else if (strcmp(dfui_response_get_action_id(r), "set_timezone") == 0) {
671 			fn_set_timezone(a);
672 		} else if (strcmp(dfui_response_get_action_id(r), "set_datetime") == 0) {
673 			fn_assign_datetime(a);
674 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
675 			state = state_utilities_menu;
676 			done = 1;
677 		}
678 
679 		dfui_form_free(f);
680 		dfui_response_free(r);
681 	}
682 }
683 
684 void
685 state_diagnostics_menu(struct i_fn_args *a)
686 {
687 	struct dfui_form *f;
688 	struct dfui_action *k;
689 	struct dfui_response *r;
690 	int done = 0;
691 
692 	while (!done) {
693 		f = dfui_form_create(
694 		    "utilities_menu",
695 		    _("Live CD Diagnostics Menu"),
696 		    _("These functions can help you diagnose this system."),
697 		    "",
698 		    "p", "role", "menu",
699 
700 		    "a", "show_dmesg",
701 		    _("Display system startup messages"),
702 		    _("Display system startup messages (dmesg)"), "",
703 		    "a", "pciconf",
704 		    _("Display PCI devices"),
705 		    _("Display PCI devices (pciconf)"), "",
706 		    "a", "pnpinfo",
707 		    _("Display Plug'n'Play ISA devices"),
708 		    _("Display Plug'n'Play ISA devices (pnpinfo)"), "",
709 		    "a", "natacontrol",
710 		    _("Display ATA devices"),
711 		    _("Display ATA devices (natacontrol)"), "",
712 		    NULL
713 		);
714 
715 		k = dfui_form_action_add(f, "cancel",
716 		    dfui_info_new(_("Return to Utilities Menu"), "", ""));
717 		dfui_action_property_set(k, "accelerator", "ESC");
718 
719 		if (!dfui_be_present(a->c, f, &r))
720 			abort_backend();
721 
722 		/* XXX set up a */
723 		if (strcmp(dfui_response_get_action_id(r), "show_dmesg") == 0) {
724 			fn_show_dmesg(a);
725 		} else if (strcmp(dfui_response_get_action_id(r), "pciconf") == 0) {
726 			fn_show_pciconf(a);
727 		} else if (strcmp(dfui_response_get_action_id(r), "pnpinfo") == 0) {
728 			fn_show_pnpinfo(a);
729 		} else if (strcmp(dfui_response_get_action_id(r), "natacontrol") == 0) {
730 			fn_show_natacontrol(a);
731 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
732 			state = state_utilities_menu;
733 			done = 1;
734 		}
735 
736 		dfui_form_free(f);
737 		dfui_response_free(r);
738 	}
739 }
740 
741 void
742 state_diskutil_menu(struct i_fn_args *a)
743 {
744 	struct dfui_form *f;
745 	struct dfui_action *k;
746 	struct dfui_response *r;
747 	int done = 0;
748 
749 	while (!done) {
750 		f = dfui_form_create(
751 		    "utilities_menu",
752 		    _("Disk Utilities Menu"),
753 		    _("These functions let you manipulate the storage devices "
754 		    "attached to this computer."),
755 		    "",
756 
757 		    "p", "role", "menu",
758 
759 		    "a", "format_hdd",
760 		    _("Format a hard disk drive"), "", "",
761 		    "a", "wipe_start_of_disk",
762 		    _("Wipe out the start of a disk"), "", "",
763 		    "a", "wipe_start_of_slice",
764 		    _("Wipe out the start of a primary partition"), "", "",
765 		    "a", "install_bootblocks",
766 		    _("Install bootblocks on disks"), "", "",
767 		    "a", "format_msdos_floppy",
768 		    _("Format an MSDOS floppy"), "", "",
769 		    NULL
770 		);
771 
772 		if (is_file("%sboot/cdboot.flp.bz2", a->os_root)) {
773 			dfui_form_action_add(f, "create_cdboot_floppy",
774 			    dfui_info_new(_("Create a CDBoot floppy"),
775 			    "",
776 			    ""));
777 		}
778 
779 		k = dfui_form_action_add(f, "cancel",
780 		    dfui_info_new(_("Return to Utilities Menu"), "", ""));
781 		dfui_action_property_set(k, "accelerator", "ESC");
782 
783 		if (!dfui_be_present(a->c, f, &r))
784 			abort_backend();
785 
786 		/* XXX set up a */
787 		if (strcmp(dfui_response_get_action_id(r), "format_hdd") == 0) {
788 			storage_set_selected_disk(a->s, NULL);
789 			storage_set_selected_slice(a->s, NULL);
790 			fn_format_disk(a);
791 		} else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_disk") == 0) {
792 			fn_wipe_start_of_disk(a);
793 		} else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_slice") == 0) {
794 			fn_wipe_start_of_slice(a);
795 		} else if (strcmp(dfui_response_get_action_id(r), "install_bootblocks") == 0) {
796 			a->short_desc = _("Select the disks on which "
797 			    "you wish to install bootblocks.");
798 			a->cancel_desc = _("Return to Utilities Menu");
799 			fn_install_bootblocks(a, NULL);
800 		} else if (strcmp(dfui_response_get_action_id(r), "format_msdos_floppy") == 0) {
801 			fn_format_msdos_floppy(a);
802 		} else if (strcmp(dfui_response_get_action_id(r), "create_cdboot_floppy") == 0) {
803 			fn_create_cdboot_floppy(a);
804 		} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
805 			state = state_utilities_menu;
806 			done = 1;
807 		}
808 
809 		dfui_form_free(f);
810 		dfui_response_free(r);
811 	}
812 }
813 
814 /** INSTALLER STATES **/
815 
816 /*
817  * state_begin_upgrade: Ask the user where the freebsd
818  * 4.X install is and make sure its safe to proceed.
819  *
820  */
821 void
822 state_begin_upgrade(struct i_fn_args *a)
823 {
824         //struct dfui_form *f = NULL;
825         //struct dfui_response *r = NULL;
826         //int done = 0;
827 
828         if (storage_get_selected_disk(a->s) == NULL || storage_get_selected_slice(a->s) == NULL) {
829 		if (!survey_storage(a)) {
830 			inform(a->c, _("Errors occurred while probing "
831 			    "the system for its storage capabilities."));
832 		}
833 
834                 a->short_desc = _("Select the disk containing the installation that you would like to upgrade.");
835                 a->cancel_desc = _("Return to Welcome Menu");
836                 fn_select_disk(a);
837                 if (!a->result || storage_get_selected_disk(a->s) == NULL) {
838                         state = state_welcome;
839                         return;
840                 }
841 
842                 a->short_desc = _("Select the primary partition containing the installation you would like to upgrade.");
843                 a->cancel_desc = _("Return to Welcome Menu");
844                 fn_select_slice(a);
845 
846                 if (!a->result || storage_get_selected_slice(a->s) == NULL) {
847                         state = state_welcome;
848                         return;
849                 }
850         }
851 
852         a->cfg_root = "mnt";
853         if (!mount_target_system(a)) {
854                 inform(a->c, _("Target system could not be mounted."));
855                 state = state_welcome;
856                 return;
857         }
858 }
859 
860 /*
861  * state_begin_install: Briefly describe the install process
862  * to the user, and let them proceed (or not.)
863  */
864 void
865 state_begin_install(struct i_fn_args *a)
866 {
867 	struct dfui_form *f;
868 	struct dfui_response *r;
869 	char msg_buf[3][1024];
870 
871 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
872 	    _("This experimental application will install %s"
873 	    " on one of the hard disk drives attached to this computer. "
874 	    "It has been designed to make it easy to install "
875 	    "%s in the typical case. "
876 	    "If you have special requirements that are not addressed "
877 	    "by this installer, or if you have problems using it, you "
878 	    "are welcome to install %s manually. "
879 	    "To do so select Exit to Live CD, login as root, and follow "
880 	    "the instructions given in the file /README ."
881 	    "\n\n"
882 	    "NOTE! As with any installation process, YOU ARE "
883 	    "STRONGLY ENCOURAGED TO BACK UP ANY IMPORTANT DATA ON THIS "
884 	    "COMPUTER BEFORE PROCEEDING!"
885 	    ""),
886 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME,
887 	    OPERATING_SYSTEM_NAME);
888 
889 	snprintf(msg_buf[1], sizeof(msg_buf[1]),
890 	    _("Some situations in which you might not wish to use this "
891 	    "installer are:\n\n"
892 	    "- you want to install %s onto a "
893 	    "logical/extended partition;\n"
894 	    "- you want to install %s "
895 	    "onto a ``dangerously dedicated'' disk; or\n"
896 	    "- you want full and utter control over the install process."
897 	    ""),
898 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
899 
900 	snprintf(msg_buf[2], sizeof(msg_buf[2]),
901 	    _("Install %s"), OPERATING_SYSTEM_NAME);
902 
903 	f = dfui_form_create(
904 	    "begin_install",
905 	    _("Begin Installation"),
906 	    msg_buf[0],
907 
908 	    msg_buf[1],
909 	    "p", "special", "dfinstaller_begin_install",
910 	    "p", "minimum_width", "76",
911 
912 	    "a", "proceed", msg_buf[2],
913 	    "", "",
914 	    "a", "cancel", _("Return to Welcome Menu"),
915 	    "", "",
916 	    "p", "accelerator", "ESC",
917 	    "a", "livecd", _("Exit to Live CD"),
918 	    "", "",
919 	    NULL
920 	);
921 
922 	if (!dfui_be_present(a->c, f, &r))
923 		abort_backend();
924 
925 	if (strcmp(dfui_response_get_action_id(r), "proceed") == 0) {
926 		if (!survey_storage(a)) {
927 			inform(a->c, _("Errors occurred while probing "
928 			    "the system for its storage capabilities."));
929 		}
930 		state = state_select_disk;
931 	} else if (strcmp(dfui_response_get_action_id(r), "livecd") == 0) {
932 		state = NULL;
933 	} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
934 		state = state_welcome;
935 	}
936 
937 	dfui_form_free(f);
938 	dfui_response_free(r);
939 }
940 
941 /*
942  * state_select_disk: ask the user on which physical disk they wish
943  * to install DragonFly.
944  */
945 void
946 state_select_disk(struct i_fn_args *a)
947 {
948 	struct disk *d;
949 	int num_disks = 0;
950 	char msg_buf[1][1024];
951 
952 	for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d))
953 		num_disks++;
954 
955 	if (num_disks == 0) {
956 		inform(a->c, _("The installer could not find any disks suitable "
957 		    "for installation (IDE or SCSI) attached to this "
958 		    "computer.  If you wish to install %s"
959 		    " on an unorthodox storage device, you will have to "
960 		    "exit to a LiveCD command prompt and install it "
961 		    "manually, using the file /README as a guide."),
962 		    OPERATING_SYSTEM_NAME);
963 		state = state_welcome;
964 		return;
965 	}
966 
967 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
968 	    _("Select a disk on which to install %s"),
969 	    OPERATING_SYSTEM_NAME);
970 	a->short_desc = msg_buf[0];
971 	a->cancel_desc = _("Return to Begin Installation");
972 	fn_select_disk(a);
973 	if (!a->result || storage_get_selected_disk(a->s) == NULL) {
974 		state = state_begin_install;
975 	} else {
976 #if 0
977 		if (disk_get_capacity(storage_get_selected_disk(a->s)) < DISK_MIN) {
978 			inform(a->c, _("WARNING: you should have a disk "
979 			    "at least %dM in size, or "
980 			    "you may encounter problems trying to "
981 			    "install %s."), DISK_MIN, OPERATING_SYSTEM_NAME);
982 		}
983 #endif
984 		state = state_format_disk;
985 	}
986 }
987 
988 void
989 state_ask_fs(struct i_fn_args *a)
990 {
991 	use_hammer = 0;
992 
993 	switch (dfui_be_present_dialog(a->c, _("Select file system"),
994 	    _("Use HAMMER|Use UFS|Return to Select Disk"),
995 	    _("Please select the file system you want to use with %s.\n\n"
996 	      "HAMMER is the new %s file system.  UFS is the traditional BSD file system."),
997 	    OPERATING_SYSTEM_NAME,
998 	    OPERATING_SYSTEM_NAME))
999 	{
1000 	case 1:
1001 		/* HAMMER */
1002 		use_hammer = 1;
1003 		break;
1004 	case 2:
1005 		/* UFS */
1006 		break;
1007 	case 3:
1008 		state = state_select_disk;
1009 		return;
1010 		/* NOTREACHED */
1011 		break;
1012 	default:
1013 		abort_backend();
1014 		break;
1015 	}
1016 	state = state_create_subpartitions;
1017 }
1018 
1019 /*
1020  * state_format_disk: ask the user if they wish to format the disk they
1021  * selected.
1022  */
1023 void
1024 state_format_disk(struct i_fn_args *a)
1025 {
1026 	switch (dfui_be_present_dialog(a->c, _("How Much Disk?"),
1027 	    _("Use Entire Disk|Use Part of Disk|Return to Select Disk"),
1028 	    _("Select how much of this disk you want to use for %s.\n\n%s"),
1029 	    OPERATING_SYSTEM_NAME,
1030 	    disk_get_desc(storage_get_selected_disk(a->s)))) {
1031 	case 1:
1032 		/* Entire Disk */
1033 		if (measure_activated_swap_from_disk(a, storage_get_selected_disk(a->s)) > 0) {
1034 			if (swapoff_all(a) == NULL) {
1035 				inform(a->c, _("Warning: swap could not be turned off."));
1036 				state = state_select_disk;
1037 				return;
1038 			}
1039 		}
1040 
1041 		fn_format_disk(a);
1042 		if (a->result)
1043 			state = state_ask_fs;
1044 		else
1045 			state = state_format_disk;
1046 		break;
1047 	case 2:
1048 		/* Part of Disk */
1049 		state = state_select_slice;
1050 		break;
1051 	case 3:
1052 		/* Return */
1053 		state = state_select_disk;
1054 		break;
1055 	default:
1056 		abort_backend();
1057 		break;
1058 	}
1059 }
1060 
1061 /*
1062  * state_select_slice: ask the user which slice they wish to install
1063  * DragonFly on.  In order to avoid confusing them, refer to it as
1064  * a primary partition, but tell them what BSD has traditionally called
1065  * it, too.
1066  */
1067 void
1068 state_select_slice(struct i_fn_args *a)
1069 {
1070 	char msg_buf[1][1024];
1071 
1072 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1073 	    _("Select the existing primary partition (also "
1074 	    "known as a `slice' in the BSD tradition) on "
1075 	    "which to install %s.\n\n"
1076 	    "Note that if you do not have any existing "
1077 	    "primary partitions on this disk, you must "
1078 	    "first create some. This installer does not "
1079 	    "currently have the ability to do this, so "
1080 	    "you will have to exit and run fdisk (in "
1081 	    "DOS or *BSD) or parted (in Linux) to do so."),
1082 	    OPERATING_SYSTEM_NAME);
1083 
1084 	a->short_desc = msg_buf[0];
1085 	a->cancel_desc = _("Return to Select Disk");
1086 	fn_select_slice(a);
1087 	if (!a->result || storage_get_selected_slice(a->s) == NULL) {
1088 		state = state_select_disk;
1089 	} else {
1090 		if (measure_activated_swap_from_slice(a, storage_get_selected_disk(a->s),
1091 		    storage_get_selected_slice(a->s)) > 0) {
1092 			if (swapoff_all(a) == NULL) {
1093 				inform(a->c, _("Warning: swap could not be turned off."));
1094 				state = state_select_slice;
1095 				return;
1096 			}
1097 		}
1098 
1099 		if (slice_get_capacity(storage_get_selected_slice(a->s)) < DISK_MIN) {
1100 			inform(a->c, _("WARNING: you should have a primary "
1101 			    "partition at least %dM in size, or "
1102 			    "you may encounter problems trying to "
1103 			    "install %s."), DISK_MIN, OPERATING_SYSTEM_NAME);
1104 		}
1105 
1106 		if (confirm_dangerous_action(a->c,
1107 		    _("WARNING!  ALL data in primary partition #%d,\n\n%s\n\non the "
1108 		    "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
1109 		    "ABSOLUTELY SURE you wish to take this action?  This is "
1110 		    "your LAST CHANCE to cancel!"),
1111 		    slice_get_number(storage_get_selected_slice(a->s)),
1112 		    slice_get_desc(storage_get_selected_slice(a->s)),
1113 		    disk_get_desc(storage_get_selected_disk(a->s)))) {
1114 			if (!format_slice(a)) {
1115 				inform(a->c, _("Primary partition #%d was "
1116 				    "not correctly formatted, and may "
1117 				    "now be in an inconsistent state. "
1118 				    "We recommend re-formatting it "
1119 				    "before proceeding."),
1120 				    slice_get_number(storage_get_selected_slice(a->s)));
1121 			} else {
1122 				inform(a->c, _("Primary partition #%d was formatted."),
1123 				    slice_get_number(storage_get_selected_slice(a->s)));
1124 				state = state_ask_fs;
1125 			}
1126 		} else {
1127 			inform(a->c, _("Action cancelled - no primary partitions were formatted."));
1128 			state = state_select_slice;
1129 		}
1130 	}
1131 }
1132 
1133 /*
1134  * state_create_subpartitions: let the user specify what subpartitions they
1135  * want on the disk, how large each should be, and where it should be mounted.
1136  */
1137 void
1138 state_create_subpartitions(struct i_fn_args *a)
1139 {
1140 	struct commands *cmds;
1141 
1142 	if (measure_activated_swap_from_slice(a, storage_get_selected_disk(a->s),
1143 	    storage_get_selected_slice(a->s)) > 0) {
1144 		if (swapoff_all(a) == NULL) {
1145 			inform(a->c, _("Warning: swap could not be turned off."));
1146 			state = disk_get_formatted(storage_get_selected_disk(a->s)) ?
1147 			    state_select_disk : state_select_slice;
1148 			return;
1149 		}
1150 	}
1151 
1152 	cmds = commands_new();
1153 
1154 	/*
1155 	 * Auto-disklabel the slice.
1156 	 * NB: one cannot use "/dev/adXsY" here -
1157 	 * it must be in the form "adXsY".
1158 	 */
1159 	command_add(cmds, "%s%s -W %s",
1160 	    a->os_root, cmd_name(a, "DISKLABEL64"),
1161 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1162 	command_add(cmds, "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
1163 	    a->os_root, cmd_name(a, "DD"),
1164 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1165 	command_add(cmds, "%s%s -B -r -w %s auto",
1166 	    a->os_root, cmd_name(a, "DISKLABEL64"),
1167 	    slice_get_device_name(storage_get_selected_slice(a->s)));
1168 	commands_execute(a, cmds);
1169 	commands_free(cmds);
1170 
1171 	if (use_hammer)
1172 		fn_create_subpartitions_hammer(a);
1173 	else
1174 		fn_create_subpartitions_ufs(a);
1175 
1176 	if (a->result) {
1177 		state = state_install_os;
1178 	} else {
1179 		state = disk_get_formatted(storage_get_selected_disk(a->s)) ?
1180 		    state_select_disk : state_select_slice;
1181 	}
1182 }
1183 
1184 /*
1185  * state_install_os: actually put DragonFly on the disk.
1186  */
1187 void
1188 state_install_os(struct i_fn_args *a)
1189 {
1190 	struct dfui_form *f;
1191 	struct dfui_response *r;
1192 	char msg_buf[1][1024];
1193 
1194 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1195 	    _("Everything is now ready to install the actual files which "
1196 	    "comprise the %s operating system "
1197 	    "on the selected partition of the selected disk.\n\n"
1198 	    "Note that this process will take quite a while to finish. "
1199 	    "You may wish to take a break now and come back to the "
1200 	    "computer in a short while."),
1201 	    OPERATING_SYSTEM_NAME);
1202 
1203 	f = dfui_form_create(
1204 	    "install_os",
1205 	    _("Install OS"),
1206 	    msg_buf[0],
1207 
1208 	    "",
1209 
1210 	    "p", "role", "confirm",
1211 	    "p", "special", "dfinstaller_install_os",
1212 
1213 	    "a", "ok", _("Begin Installing Files"), "", "",
1214 	    "a", "cancel", _("Return to Create Subpartitions"), "", "",
1215 	    "p", "accelerator", "ESC",
1216 
1217 	    NULL
1218 	);
1219 
1220 	if (!dfui_be_present(a->c, f, &r))
1221 		abort_backend();
1222 
1223 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1224 		state = state_create_subpartitions;
1225 	} else {
1226 		fn_install_os(a);
1227 		if (a->result)
1228 			state = state_install_bootstrap;
1229 	}
1230 
1231 	dfui_form_free(f);
1232 	dfui_response_free(r);
1233 }
1234 
1235 /*
1236  * state_install_bootstrap: put boot0 bootblocks on selected disks.
1237  */
1238 void
1239 state_install_bootstrap(struct i_fn_args *a)
1240 {
1241 	char msg_buf[1][1024];
1242 
1243 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1244 	    _("You may now wish to install bootblocks on one or more disks. "
1245 	    "If you already have a boot manager installed, you can skip "
1246 	    "this step (but you may have to configure your boot manager "
1247 	    "separately.)  If you installed %s on a disk other "
1248 	    "than your first disk, you will need to put the bootblock "
1249 	    "on at least your first disk and the %s disk."),
1250 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
1251 
1252 	a->short_desc = msg_buf[0];
1253 	a->cancel_desc = _("Skip this Step");
1254 	fn_install_bootblocks(a,
1255 	    disk_get_device_name(storage_get_selected_disk(a->s)));
1256 	state = state_finish_install;
1257 }
1258 
1259 /*
1260  * Finish up the install.
1261  */
1262 void
1263 state_finish_install(struct i_fn_args *a)
1264 {
1265 	char msg_buf[1][1024];
1266 	during_install = 1;
1267 
1268 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1269 	    "%s is Installed!",
1270 	    OPERATING_SYSTEM_NAME);
1271 
1272 	switch (dfui_be_present_dialog(a->c, msg_buf[0],
1273 	    _("Configure this System|Reboot|Return to Welcome Menu"),
1274 	    _("Congratulations!\n\n"
1275 	    "%s has successfully been installed on "
1276 	    "this computer. You may now proceed to configure "
1277 	    "the installation. Alternately, you may wish to "
1278 	    "reboot the computer and boot into the installed "
1279 	    "system to confirm that it works."),
1280 	    OPERATING_SYSTEM_NAME)) {
1281 	case 1:
1282 		state = state_configure_menu;
1283 		break;
1284 	case 2:
1285 		state = state_reboot;
1286 		break;
1287 	case 3:
1288 		state = state_welcome;
1289 		break;
1290 	default:
1291 		abort_backend();
1292 	}
1293 }
1294 
1295 /*
1296  * state_reboot: reboot the machine.
1297  */
1298 void
1299 state_reboot(struct i_fn_args *a)
1300 {
1301 	struct dfui_form *f;
1302 	struct dfui_response *r;
1303 
1304 	f = dfui_form_create(
1305 	    "reboot",
1306 	    _("Reboot"),
1307 	    _("This machine is about to be shut down. "
1308 	    "After the machine has reached its shutdown state, "
1309 	    "you may remove the CD from the CD-ROM drive tray "
1310 	    "and press Enter to reboot from the HDD."),
1311 
1312 	    "",
1313 
1314 	    "p", "role", "confirm",
1315 
1316 	    "a", "ok", _("Reboot"), "", "",
1317 	    "a", "cancel", _("Return to Welcome Menu"), "", "",
1318 	    "p", "accelerator", "ESC",
1319 	    NULL
1320 	);
1321 
1322 	if (!dfui_be_present(a->c, f, &r))
1323 		abort_backend();
1324 
1325 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1326 		state = state_welcome;
1327 	} else {
1328 		do_reboot = 1;
1329 		state = NULL;
1330 	}
1331 
1332 	dfui_form_free(f);
1333 	dfui_response_free(r);
1334 }
1335 
1336 /*
1337  *
1338  *  state_setup_remote_installation_server:
1339  *  Setup a remote boot installation environment where a machine
1340  *  can boot via DHCP/TFTP/NFS and have a running environment
1341  *  where the installer can setup the machine.
1342  *
1343  */
1344 void
1345 state_setup_remote_installation_server(struct i_fn_args *a)
1346 {
1347         FILE *p;
1348         struct commands *cmds;
1349         struct dfui_form *f;
1350 	struct dfui_action *k;
1351         struct dfui_response *r;
1352         char *word;
1353         char interface[256];
1354         char line[256];
1355 
1356         switch (dfui_be_present_dialog(a->c, _("Enable Netboot Installation Services?"),
1357             _("Enable NetBoot Installation Services|No thanks"),
1358             _("NetBoot Installation Services allows this machine to become "
1359             "a Installation Server that will allow the clients to boot over the network "
1360 	    "via PXE and start the Installation Environment."
1361 	    "\n\n*NOTE!*  This will assign the IP Address of 10.1.0.1/24 to the selected interface."
1362             "\n\nWould you like to provision this machine to serve up the LiveCD/Installer?"))) {
1363 		case 1:
1364 			/*
1365 			 * Get interface list.
1366 			 */
1367 			p = popen("/sbin/ifconfig -l", "r");
1368 			/* XXX it's possible (though extremely unlikely) this will fail. */
1369 			while (fgets(line, 255, p) != NULL)
1370 				line[strlen(line) - 1] = '\0';
1371 			pclose(p);
1372 
1373 			f = dfui_form_create(
1374 			    "assign_ip",
1375 			    _("Setup NetBoot Installation Environment"),
1376 			    _("Please select which interface you would like to configure:"),
1377 			    "",
1378 			    "p",        "role", "menu",
1379 			    NULL
1380 			);
1381 
1382 			/* Loop through array. */
1383 			word = strtok(line, " \t");
1384 			while (word != NULL) {
1385 				dfui_form_action_add(f, word,
1386 				    dfui_info_new(word, "", ""));
1387 				word = strtok(NULL, " ");
1388 			}
1389 
1390 			k = dfui_form_action_add(f, "cancel",
1391 			    dfui_info_new("Cancel", "", ""));
1392 			dfui_action_property_set(k, "accelerator", "ESC");
1393 
1394 			if (!dfui_be_present(a->c, f, &r))
1395 			abort_backend();
1396 
1397 			strlcpy(interface, dfui_response_get_action_id(r), 256);
1398 
1399 			if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1400 				dfui_form_free(f);
1401 				dfui_response_free(r);
1402 				return;
1403 			}
1404 
1405 			/*
1406 			 *
1407 			 * Issues the necessary commands to setup the remote boot environment
1408 			 *
1409 			 */
1410 			cmds = commands_new();
1411 			command_add(cmds, "%s%s %s 10.1.0.1 netmask 255.255.255.0",
1412 			    a->os_root, cmd_name(a, "IFCONFIG"), interface);
1413 			command_add(cmds, "%s%s -p %stftpdroot",
1414 			    a->os_root, cmd_name(a, "MKDIR"), a->tmp);
1415 			command_add(cmds, "%s%s %sboot/pxeboot %stftpdroot",
1416 			    a->os_root, cmd_name(a, "CP"), a->os_root, a->tmp);
1417 			command_add(cmds, "%s%s %s -ro -alldirs -maproot=root: -network 10.1.0.0 -mask 255.255.255.0 >> %setc/exports",
1418 			    a->os_root, cmd_name(a, "ECHO"), a->os_root, a->os_root);
1419 			command_add(cmds, "%s%s tftp dgram udp wait root %s%s tftpd -l -s %stftpdroot >> %setc/inetd.conf",
1420 			    a->os_root, cmd_name(a, "ECHO"),
1421 			    a->os_root, cmd_name(a, "TFTPD"),
1422 			    a->tmp, a->os_root);
1423 			command_add(cmds, "%s%s",
1424 			    a->os_root, cmd_name(a, "INETD"));
1425 			command_add(cmds, "%s%s %svar/db/dhcpd.leases",
1426 			    a->os_root, cmd_name(a, "TOUCH"), a->os_root);
1427 			command_add(cmds, "%s%s -cf /etc/dhcpd.conf >%sdev/null 2>&1",
1428 			    a->os_root, cmd_name(a, "DHCPD"), a->os_root);
1429 			command_add(cmds, "%s%s >%sdev/null 2>&1",
1430 			    a->os_root, cmd_name(a, "RPCBIND"), a->os_root);
1431 			command_add(cmds, "%s%s -ln >%sdev/null 2>&1",
1432 			    a->os_root, cmd_name(a, "MOUNTD"), a->os_root);
1433 			command_add(cmds, "%s%s -u -t -n 6 >%sdev/null 2>&1",
1434 			    a->os_root, cmd_name(a, "NFSD"), a->os_root);
1435 
1436 			if (commands_execute(a, cmds)) {
1437 				inform(a->c, _("NetBoot installation services are now started."));
1438 			} else {
1439 				inform(a->c, _("A failure occurred while provisioning the NetBoot environment.  Please check the logs."));
1440 			}
1441 
1442 			commands_free(cmds);
1443 			dfui_form_free(f);
1444 			dfui_response_free(r);
1445 
1446 			break;
1447 		case 2:
1448 
1449 			break;
1450 
1451 	};
1452 
1453 	state = state_welcome;
1454 
1455 }
1456 
1457 /*** MAIN ***/
1458 
1459 int
1460 flow(int transport, char *rendezvous, char *os_root,
1461      int booted_from_livecd __unused, int upgrade_menu_toggle __unused)
1462 {
1463 	struct i_fn_args *a;
1464 
1465 	rc_conf = config_vars_new();
1466 
1467 	if ((a = i_fn_args_new(os_root, DEFAULT_INSTALLER_TEMP,
1468 			       transport, rendezvous)) == NULL) {
1469 		return(0);
1470 	}
1471 
1472 	/*
1473 	 * XXX We can't handle this yet.
1474 	 *
1475 	   a->booted_from_livecd = booted_from_livecd;
1476 	   a->upgrade_menu_toggle = upgrade_menu_toggle;
1477 	*/
1478 	a->booted_from_livecd = 1;
1479 	a->upgrade_menu_toggle = 0;
1480 
1481 	/*
1482 	 * Execute the state machine here.  The global function pointer
1483 	 * variable `state' points to the next state_* function to execute.
1484 	 * Before it exits, this function should set `state' to the next
1485 	 * state to make a transition to, or NULL to indicate that the
1486 	 * state machine is finished.
1487 	 */
1488 #ifdef ENABLE_NLS
1489 	state = state_lang_menu;
1490 #else
1491 	state = state_welcome;
1492 #endif
1493 	for (; state != NULL; )
1494 		state(a);
1495 
1496 	config_vars_free(rc_conf);
1497 
1498 	i_fn_args_free(a);
1499 
1500 	return(do_reboot);
1501 }
1502