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