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