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