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