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