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);
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 	state = state_finish_install;
1256 }
1257 
1258 /*
1259  * Finish up the install.
1260  */
1261 void
1262 state_finish_install(struct i_fn_args *a)
1263 {
1264 	char msg_buf[1][1024];
1265 	during_install = 1;
1266 
1267 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
1268 	    "%s is Installed!",
1269 	    OPERATING_SYSTEM_NAME);
1270 
1271 	switch (dfui_be_present_dialog(a->c, msg_buf[0],
1272 	    _("Configure this System|Reboot|Return to Welcome Menu"),
1273 	    _("Congratulations!\n\n"
1274 	    "%s has successfully been installed on "
1275 	    "this computer. You may now proceed to configure "
1276 	    "the installation. Alternately, you may wish to "
1277 	    "reboot the computer and boot into the installed "
1278 	    "system to confirm that it works."),
1279 	    OPERATING_SYSTEM_NAME)) {
1280 	case 1:
1281 		state = state_configure_menu;
1282 		break;
1283 	case 2:
1284 		state = state_reboot;
1285 		break;
1286 	case 3:
1287 		state = state_welcome;
1288 		break;
1289 	default:
1290 		abort_backend();
1291 	}
1292 }
1293 
1294 /*
1295  * state_reboot: reboot the machine.
1296  */
1297 void
1298 state_reboot(struct i_fn_args *a)
1299 {
1300 	struct dfui_form *f;
1301 	struct dfui_response *r;
1302 
1303 	f = dfui_form_create(
1304 	    "reboot",
1305 	    _("Reboot"),
1306 	    _("This machine is about to be shut down. "
1307 	    "After the machine has reached its shutdown state, "
1308 	    "you may remove the CD from the CD-ROM drive tray "
1309 	    "and press Enter to reboot from the HDD."),
1310 
1311 	    "",
1312 
1313 	    "p", "role", "confirm",
1314 
1315 	    "a", "ok", _("Reboot"), "", "",
1316 	    "a", "cancel", _("Return to Welcome Menu"), "", "",
1317 	    "p", "accelerator", "ESC",
1318 	    NULL
1319 	);
1320 
1321 	if (!dfui_be_present(a->c, f, &r))
1322 		abort_backend();
1323 
1324 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1325 		state = state_welcome;
1326 	} else {
1327 		do_reboot = 1;
1328 		state = NULL;
1329 	}
1330 
1331 	dfui_form_free(f);
1332 	dfui_response_free(r);
1333 }
1334 
1335 /*
1336  *
1337  *  state_setup_remote_installation_server:
1338  *  Setup a remote boot installation environment where a machine
1339  *  can boot via DHCP/TFTP/NFS and have a running environment
1340  *  where the installer can setup the machine.
1341  *
1342  */
1343 void
1344 state_setup_remote_installation_server(struct i_fn_args *a)
1345 {
1346         FILE *p;
1347         struct commands *cmds;
1348         struct dfui_form *f;
1349 	struct dfui_action *k;
1350         struct dfui_response *r;
1351         char *word;
1352         char interface[256];
1353         char line[256];
1354 
1355         switch (dfui_be_present_dialog(a->c, _("Enable Netboot Installation Services?"),
1356             _("Enable NetBoot Installation Services|No thanks"),
1357             _("NetBoot Installation Services allows this machine to become "
1358             "a Installation Server that will allow the clients to boot over the network "
1359 	    "via PXE and start the Installation Environment."
1360 	    "\n\n*NOTE!*  This will assign the IP Address of 10.1.0.1/24 to the selected interface."
1361             "\n\nWould you like to provision this machine to serve up the LiveCD/Installer?"))) {
1362 		case 1:
1363 			/*
1364 			 * Get interface list.
1365 			 */
1366 			p = popen("/sbin/ifconfig -l", "r");
1367 			/* XXX it's possible (though extremely unlikely) this will fail. */
1368 			while (fgets(line, 255, p) != NULL)
1369 				line[strlen(line) - 1] = '\0';
1370 			pclose(p);
1371 
1372 			f = dfui_form_create(
1373 			    "assign_ip",
1374 			    _("Setup NetBoot Installation Environment"),
1375 			    _("Please select which interface you would like to configure:"),
1376 			    "",
1377 			    "p",        "role", "menu",
1378 			    NULL
1379 			);
1380 
1381 			/* Loop through array. */
1382 			word = strtok(line, " \t");
1383 			while (word != NULL) {
1384 				dfui_form_action_add(f, word,
1385 				    dfui_info_new(word, "", ""));
1386 				word = strtok(NULL, " ");
1387 			}
1388 
1389 			k = dfui_form_action_add(f, "cancel",
1390 			    dfui_info_new("Cancel", "", ""));
1391 			dfui_action_property_set(k, "accelerator", "ESC");
1392 
1393 			if (!dfui_be_present(a->c, f, &r))
1394 			abort_backend();
1395 
1396 			strlcpy(interface, dfui_response_get_action_id(r), 256);
1397 
1398 			if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1399 				dfui_form_free(f);
1400 				dfui_response_free(r);
1401 				return;
1402 			}
1403 
1404 			/*
1405 			 *
1406 			 * Issues the necessary commands to setup the remote boot environment
1407 			 *
1408 			 */
1409 			cmds = commands_new();
1410 			command_add(cmds, "%s%s %s 10.1.0.1 netmask 255.255.255.0",
1411 			    a->os_root, cmd_name(a, "IFCONFIG"), interface);
1412 			command_add(cmds, "%s%s -p %stftpdroot",
1413 			    a->os_root, cmd_name(a, "MKDIR"), a->tmp);
1414 			command_add(cmds, "%s%s %sboot/pxeboot %stftpdroot",
1415 			    a->os_root, cmd_name(a, "CP"), a->os_root, a->tmp);
1416 			command_add(cmds, "%s%s %s -ro -alldirs -maproot=root: -network 10.1.0.0 -mask 255.255.255.0 >> %setc/exports",
1417 			    a->os_root, cmd_name(a, "ECHO"), a->os_root, a->os_root);
1418 			command_add(cmds, "%s%s tftp dgram udp wait root %s%s tftpd -l -s %stftpdroot >> %setc/inetd.conf",
1419 			    a->os_root, cmd_name(a, "ECHO"),
1420 			    a->os_root, cmd_name(a, "TFTPD"),
1421 			    a->tmp, a->os_root);
1422 			command_add(cmds, "%s%s",
1423 			    a->os_root, cmd_name(a, "INETD"));
1424 			command_add(cmds, "%s%s %svar/db/dhcpd.leases",
1425 			    a->os_root, cmd_name(a, "TOUCH"), a->os_root);
1426 			command_add(cmds, "%s%s -cf /etc/dhcpd.conf >%sdev/null 2>&1",
1427 			    a->os_root, cmd_name(a, "DHCPD"), a->os_root);
1428 			command_add(cmds, "%s%s >%sdev/null 2>&1",
1429 			    a->os_root, cmd_name(a, "RPCBIND"), a->os_root);
1430 			command_add(cmds, "%s%s -ln >%sdev/null 2>&1",
1431 			    a->os_root, cmd_name(a, "MOUNTD"), a->os_root);
1432 			command_add(cmds, "%s%s -u -t -n 6 >%sdev/null 2>&1",
1433 			    a->os_root, cmd_name(a, "NFSD"), a->os_root);
1434 
1435 			if (commands_execute(a, cmds)) {
1436 				inform(a->c, _("NetBoot installation services are now started."));
1437 			} else {
1438 				inform(a->c, _("A failure occurred while provisioning the NetBoot environment.  Please check the logs."));
1439 			}
1440 
1441 			commands_free(cmds);
1442 			dfui_form_free(f);
1443 			dfui_response_free(r);
1444 
1445 			break;
1446 		case 2:
1447 
1448 			break;
1449 
1450 	};
1451 
1452 	state = state_welcome;
1453 
1454 }
1455 
1456 /*** MAIN ***/
1457 
1458 int
1459 flow(int transport, char *rendezvous, char *os_root,
1460      int booted_from_livecd __unused, int upgrade_menu_toggle __unused)
1461 {
1462 	struct i_fn_args *a;
1463 
1464 	rc_conf = config_vars_new();
1465 
1466 	if ((a = i_fn_args_new(os_root, DEFAULT_INSTALLER_TEMP,
1467 			       transport, rendezvous)) == NULL) {
1468 		return(0);
1469 	}
1470 
1471 	/*
1472 	 * XXX We can't handle this yet.
1473 	 *
1474 	   a->booted_from_livecd = booted_from_livecd;
1475 	   a->upgrade_menu_toggle = upgrade_menu_toggle;
1476 	*/
1477 	a->booted_from_livecd = 1;
1478 	a->upgrade_menu_toggle = 0;
1479 
1480 	/*
1481 	 * Execute the state machine here.  The global function pointer
1482 	 * variable `state' points to the next state_* function to execute.
1483 	 * Before it exits, this function should set `state' to the next
1484 	 * state to make a transition to, or NULL to indicate that the
1485 	 * state machine is finished.
1486 	 */
1487 #ifdef ENABLE_NLS
1488 	state = state_lang_menu;
1489 #else
1490 	state = state_welcome;
1491 #endif
1492 	for (; state != NULL; )
1493 		state(a);
1494 
1495 	config_vars_free(rc_conf);
1496 
1497 	i_fn_args_free(a);
1498 
1499 	return(do_reboot);
1500 }
1501